1

这似乎应该是一个常见问题,但我无法找到答案。基本上我想要一个包含 10 个左右复选框的表单,我用check_box_tag. 提交表单后,我想生成一个查询,该查询返回与任何选中的选择匹配的所有记录。因此,选中的选项数量会有所不同。

所以,例如,如果我有

class Book < ActiveRecord::Base
  belongs_to :author
end

我想生成类似的东西

Book.where("author_id = ? or author_id = ?", params[authors[0]], params[authors[1]])如果选中了两个框,等等。

感谢您的任何见解。

4

2 回答 2

4

这对你有用吗?

Book.where(author_id: [array_of_author_ids])

您需要先从 params 收集 author_ids

于 2012-07-02T21:16:44.997 回答
0

我最近不得不做类似的事情,这就是我实现这一目标的方式。这很聪明(至少我是这么认为的。:))

我创建了一个查询模型,它在 JSON 中序列化查询列(文本字段)。我使用表单从带有选择字段的用户那里获取查询数据。

class BookQuery < ActiveRecord::Base
  has_many :books



  # loop through each foreign key of the Book table and create a hash with empty selection
  def self.empty_query
    q = {}
    Book.column_names.each do |column_name|
      next unless column_name.ends_with?("_id")
      q.merge column_name => []
    end
  end
end

下面我以作者为例: <%= form_for @book_query do |f| %> <% for author in Author.all %> <%= check_box_tag "book_query[query][author_ids][]", author.id, false%> <%= author.name %> <% end %> <% = f.submit "保存查询" %> <% end %>

提交此表单时,您最终会得到如下参数: 提交表单时,它会生成此参数:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"XXXXXXXXXXX", "book_query"=>{"query"=>{"author_ids"=>["2", "3"]}}, "commit"=>"Save Query"}

现在在 BookQuery 控制器的 create 操作中,您可以执行 create 函数始终执行的操作:

def create
  @book_query = BookQuery.build(params[:book_query])
  if @book_query.save
    flash[:success] = "Book query successfully saved."
    redirect_to ...
  else
    flash[:error] = "Failed to save book query."
    render :new
  end
end

但默认情况下,rails 将数据序列化为哈希类型:

1.9.3p194 :015 > pp BookQuery.find(9).query
BookQuery Load (0.7ms)  SELECT "book_queries".* FROM "book_queries" WHERE "book_queries"."id" = $1 LIMIT 1  [["id", 9]]
"--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\nauthor_ids:\n- '2'\n- '3'\n"
=> "--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\nauthor_ids:\n- '2'\n- '3'\n" 

在 BookQuery 模型中,添加以下内容:

serialize :query, JSON

但是 rail 会将 ID 更改为字符串:

1.9.3p194 :018 > query = JSON.parse(BookQuery.find(10).query)
BookQuery Load (0.5ms)  SELECT "book_queries".* FROM "book_queries" WHERE "book_queries"."id" = $1 LIMIT 1  [["id", 10]]
=> {"author_ids"=>["2", "3"]} 
1.9.3p194 :019 > query["author_ids"]
=> ["2", "3"]

然后我所做的是覆盖 BookQuery 模型中的属性访问器:

必须完成以下操作,因为哈希返回字符串,而不是整数中的 id。

def query=(query)
  query.each_pair do |k, v|
    if query[k].first.present?
      query[k].map!(&:to_i)
    else
      query.except!(k)
    end
  end
  write_attribute(:query, query)
end

# just want to avoid getting nil query's
def query
  read_attribute(:query) || {}
end

要使用此查询查找书籍,您只需将此函数添加到您的 Book 模型:

def self.find_by_book_query(book_query, options = {})
  options[:conditions] = book_query.query
  find(:all, options)
end

现在,您将获得一个基于模型定义 Book 的可自定义查询字符串,并且一切都像 Rails 方式一样工作。:)

于 2012-07-02T22:04:31.293 回答