How to specify multiple values in where with AR query interface in rails3

前端 未结 7 1018
时光说笑
时光说笑 2020-12-28 13:31

Per section 2.2 of rails guide on Active Record query interface here:

which seems to indicate that I can pass a string specifying the condition(s), then an array of

相关标签:
7条回答
  • 2020-12-28 14:12

    If you want to chain together an open-ended list of conditions (attribute names and values), I would suggest using an arel table.

    It's a bit hard to give specifics since your question is so vague, so I'll just explain how to do this for a simple case of a Post model and a few attributes, say title, summary, and user_id (i.e. a user has_many posts).

    First, get the arel table for the model:

    table = Post.arel_table
    

    Then, start building your predicate (which you will eventually use to create an SQL query):

    relation = table[:title].eq("Foo")
    relation = relation.or(table[:summary].eq("A post about foo"))
    relation = relation.and(table[:user_id].eq(5))
    

    Here, table[:title], table[:summary] and table[:user_id] are representations of columns in the posts table. When you call table[:title].eq("Foo"), you are creating a predicate, roughly equivalent to a find condition (get all rows whose title column equals "Foo"). These predicates can be chained together with and and or.

    When your aggregate predicate is ready, you can get the result with:

    Post.where(relation)
    

    which will generate the SQL:

    SELECT "posts".* FROM "posts"
    WHERE (("posts"."title" = "Foo" OR "posts"."summary" = "A post about foo")
    AND "posts"."user_id" = 5)
    

    This will get you all posts that have either the title "Foo" or the summary "A post about foo", and which belong to a user with id 5.

    Notice the way arel predicates can be endlessly chained together to create more and more complex queries. This means that if you have (say) a hash of attribute/value pairs, and some way of knowing whether to use AND or OR on each of them, you can loop through them one by one and build up your condition:

    relation = table[:title].eq("Foo")
    hash.each do |attr, value|
      relation = relation.and(table[attr].eq(value))
      # or relation = relation.or(table[attr].eq(value)) for an OR predicate
    end
    Post.where(relation)
    

    Aside from the ease of chaining conditions, another advantage of arel tables is that they are independent of database, so you don't have to worry whether your MySQL query will work in PostgreSQL, etc.

    Here's a Railscast with more on arel: http://railscasts.com/episodes/215-advanced-queries-in-rails-3?view=asciicast

    Hope that helps.

    0 讨论(0)
提交回复
热议问题