Combine arrays of conditions in Rails

2019-01-23 22:11发布

I'm using the Rails3 beta, will_paginate gem, and the geokit gem & plugin.

As the geokit-rails plugin, doesn't seem to support Rails3 scopes (including the :origin symbol is the issue), I need to use the .find syntax.

In lieu of scopes, I need to combine two sets of criteria in array format:

I have a default condition:

conditions = ["invoices.cancelled = ? AND invoices.paid = ?", false, false]

I may need to add one of the following conditions to the default condition, depending on a UI selection:

#aged 0
lambda {["created_at IS NULL OR created_at < ?", Date.today + 30.days]}
#aged 30
lambda {["created_at >= ? AND created_at < ?", Date.today + 30.days, Date.today + 60.days]}
#aged > 90
lamdba {["created_at >= ?", Date.today + 90.days]}

The resulting query resembles:

@invoices = Invoice.find(
  :all, 
  :conditions => conditions,
  :origin => ll     #current_user's lat/lng pair
  ).paginate(:per_page => @per_page, :page => params[:page])

Questions:

  1. Is there an easy way to combine these two arrays of conditions (if I've worded that correctly)
  2. While it isn't contributing to the problem, is there a DRYer way to create these aging buckets?
  3. Is there a way to use Rails3 scopes with the geokit-rails plugin that will work?

Thanks for your time.

2条回答
做个烂人
2楼-- · 2019-01-23 22:35

I think a better way is to use Anonymous scopes.
Check it out here: http://railscasts.com/episodes/112-anonymous-scopes

查看更多
Animai°情兽
3楼-- · 2019-01-23 22:44

Try this:

ca =  [["invoices.cancelled = ? AND invoices.paid = ?", false, false]]

ca << ["created_at IS NULL OR created_at < ?", 
                    Date.today + 30.days] if aged == 0

ca << ["created_at >= ? AND created_at < ?", 
                    Date.today + 30.days, Date.today + 60.days] if aged == 30

ca << ["created_at >= ?", Date.today + 90.days] if aged > 30

condition = [ca.map{|c| c[0] }.join(" AND "), *ca.map{|c| c[1..-1] }.flatten]

Edit Approach 2

Monkey patch the Array class. Create a file called monkey_patch.rb in config/initializers directory.

class Array
  def where(*args)
    sql = args[0]     
    unless (sql.is_a?(String) and sql.present?)
      return self
    end    
    self[0] = self[0].present? ? " #{self[0]} AND #{sql}  " : sql 
    self.concat(args[1..-1])    
  end
end

Now you can do this:

cond = []
cond.where("id = ?", params[id]) if params[id].present?
cond.where("state IN (?)", states) unless states.empty?
User.all(:conditions => cond)
查看更多
登录 后发表回答