2014-09-20 47 views
3

我想通过我的Rails应用程序中的名字和姓氏搜索用户,目前我正在尝试每种方法都得到混合结果。有没有办法重新编写这些方法来获得我想要的结果?试图通过名字和姓氏搜索

user_controller.rb

方法#1

def self.search(query) 
    where("first_name LIKE ? OR last_name LIKE ?", "%#{query}%", "%#{query}%") 
end 

这适用于任何名字或姓氏,但不能同时使用。

方法2

def self.search(keywords) 
    if keywords 
    where(:all, :conditions => ["concat(first_name," ",last_name) like?", "%#{keywords}%"]) 
    end 
end 

这不返回任何结果

方法#3

def self.search(search) 
    if search 
    select('(first_name || " " || last_name) as \'ful_name\', *') 
    where ['first_name LIKE :s OR last_name LIKE :s OR ful_name LIKE :s', :s => "%#{search}"] 
    else 
    scoped 
end 
end 

这将返回错误

的SQLite3 ::的SQLException:没有这样的列:ful_name:SELECT“users”。* FROM“us ers“WHERE(first_name LIKE'%Spider Man'或last_name LIKE'%Spider Man'或ful_name LIKE'%Spider Man')ORDER BY created_at DESC

app/views/users/index.html.erb:5:在`_app_views_users_index_html_erb__848623016_40254132'

index.html.erb

<% provide(:title, 'Search') %> 
<h1>Search</h1> 

<ul class="span4 users"> 
    <%= render @users %> 
</ul> 

_user.html.erb

<li> 
    <%= image_tag user.avatar(:medium) %> 
    <h4><%= link_to user.full_name, feed_user_path(user), :class => "follow-color" %></h4> 
    <% if current_user.admin? && !current_user?(user) %> 
    | <%= link_to "delete", user, method: :delete, 
            data: { confirm: "You sure?" } %> 
    <% end %> 
</li> 

_header.html。 ERB

<%= form_tag users_path, method: "get", class: "search-bar" do %> 
    <%= text_field_tag :search, params[:search], placeholder: "Search" %> 
<% end %> 
+0

第一varitan看起来是正确的,但你是什么意思'这适用于名字或姓氏,但不是两个.'? – IS04 2014-09-20 04:36:53

+0

它将通过我在数据库中的名字或姓氏字符串进行搜索,但不会为first_name + last_name搜索 – teddybear 2014-09-20 04:45:55

回答

4

这一个:

:conditions => ["concat(first_name," ",last_name) like?", "%#{keywords}%"] 

不会工作,因为你有一个(阴险)报价的问题。在Ruby中,这样的:

"a" "b" 

是一样的:

"ab" 

所以你:conditions真的是这样的:

:conditions => ["concat(first_name,,last_name) like?", "%#{keywords}%"] 

你的意思是说:

:conditions => ["concat(first_name, ' ', last_name) like ?", "%#{keywords}%"] 

SQL中的字符串文字使用单引号s,而不是双引号。另外,如果你使用的是声称支持标准的SQL数据库,你应该使用||操作字符串连接:

:conditions => ["first_name || ' ' || last_name like ?", "%#{keywords}%"] 

第三个不会起作用,因为在SELECT子句中定义的别名不一般在WHERE子句中可用,因此出现“未知列”错误。你也扔掉select调用的结果,所以我想你错过了在.这里太:

select('(first_name || " " || last_name) as \'ful_name\', *') 
where ['first_name LIKE :s OR last_name LIKE :s OR ful_name LIKE :s', :s => "%#{search}"] 

还有报价问题的潜力:字符串常量在SQL中使用单引号,双引号为标识符。你想,只是说:

where("first_name like :s or last_name like :s or first_name || ' ' || last_name like :s", :s => "%#{search}") 

或者只是:

where("first_name || ' ' || last_name like :s", :s => "%#{search}") 

需要注意几个问题:

  1. 字符串连接运营商是特定于数据库。标准SQL使用||,但根据配置,MySQL希望使用concat函数。 AFAIK,SQLite支持很多MySQL-isms,但是当你使用它们时你需要知道,并且你应该尽可能地坚持标准。
  2. 引用是数据库特有的。标准SQL对于字符串文字使用单引号,对于标识符使用双引号(例如表名和列名)。 MySQL使用back-ticks作为标识符,SQLite(AFAIK)可以让你使用双引号或者back-ticks标识符和单引号或者双引号。再次坚持标准尽可能建立良好的习惯。
+0

真的很好的答案! – 2014-09-20 07:04:54

+0

@RichPeck:谢谢。简单的“做X”答案让我感觉不对。 – 2014-09-20 18:46:16

+0

你真棒。最后一个工作。 – teddybear 2014-09-21 22:37:39