尝试按first_name和last_name搜索

时间:2014-09-20 04:27:20

标签: ruby-on-rails ruby ruby-on-rails-4 rails-activerecord

我正在尝试通过我的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“users”WHERE(first_name LIKE'%蜘蛛侠'或last_name LIKE'%蜘蛛侠'或'ful_name LIKE'%蜘蛛侠') 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 %>

2 个答案:

答案 0 :(得分: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中的字符串文字使用单引号,而不是双引号。此外,如果您使用声称支持标准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主义,但是当你使用它们时需要注意,你应该尽可能地遵守标准。
  2. 报价再次是特定于数据库的。标准SQL对字符串文字使用单引号,对标识符使用双引号(例如表名和列名)。 MySQL使用反向标记作为标识符,SQLite(AFAIK)允许您对标识符使用双引号或反向标记,对字符串使用单引号或双引号。再次,尽可能坚持标准,以建立良好的习惯。

答案 1 :(得分:0)

我想做同样的事情,我遵循了这个好的tuto:https://www.youtube.com/watch?v=s88Uc0InOAM

然后我遇到了同样的问题,我想同时搜索姓名和姓氏。 这就是我所做的并且正在运行:

    @indiens = Indien.where("name LIKE ?", "%" + params[:q] + "%" ).or(Indien.where("surname LIKE ?", "%" + params[:q] + "%" ))

可能有更多的链接,但是我没有测试。

我知道已经有5年了,也许会对别人有帮助。