【问题标题】:rails OR query based on multiple checkbox selections基于多个复选框选择的 rails OR 查询
【发布时间】:2012-07-02 21:07:13
【问题描述】:

这似乎应该是一个常见问题,但我无法找到答案。基本上我想要一个包含 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]])如果选中了两个框,等等。

感谢您的任何见解。

【问题讨论】:

    标签: ruby-on-rails-3 activerecord arel


    【解决方案1】:

    这对你有用吗?

    Book.where(author_id: [array_of_author_ids])
    

    你需要先从params中收集author_ids

    【讨论】:

    • 到目前为止,根据他的代码,我认为他将其作为参数[作者]。所以你明白了。在 Rails 2.3 中我必须这样做: Book.all(:conditions => ["author_id IN (?)", params[authors]) ... where() 真的允许我像你在 3 中那样做吗.x?
    • 是的,这非常有效。谢谢你。我试图让它变得比它需要的更复杂。 (我会投票给你,但还没有完全达到,代表明智。)
    • @qalep 很高兴它对您有所帮助。
    【解决方案2】:

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

    我创建了一个以 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
    

    下面我以作者为例:

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

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

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

    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 方式一样工作。 :)

    【讨论】:

    • 这样的负载是多余的。如果你愿意
    • 抱歉,您的评论似乎被截断了。有什么更好的方法来做到这一点?
    • hi fatshu,对不起,它被切断了,因为我昨晚在我的iphone上写了它后要删除它,但不能。很多这些东西都是多余的...... 在这种情况下,我打算删除我的评论,因为你在这里给出的内容是针对你所面临的问题(而不是上面的问题)。对于这个问题 - 如果他想保存查询 - 您只需将作者存储为序列化,而不是 JSON 样式。然后就像上面的 alper 一样将其放入 find 中。再说一遍:抱歉,适合您的情况的代码很好,而不是这个问题。
    • 我明白了。我认为这个问题像我的一样是通用的,我必须处理与“书”相关的多条记录。但我现在明白我是如何误解了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 2011-03-06
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多