在 Rails 中组合条件数组

发布于 2024-09-10 03:06:35 字数 1014 浏览 8 评论 0原文

我正在使用 Rails3 beta、will_paginate gem 和 geokit gem &插件。

作为 geokit-rails 插件,似乎不支持 Rails3 范围(包括 :origin 符号是问题),我需要使用 .find 语法。

我需要以数组格式组合两组条件来代替范围:

我有一个默认条件:

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

我可能需要将以下条件之一添加到默认条件,具体取决于 UI 选择:

#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]}

生成的查询类似于:

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

问题:

  1. 是否有一种简单的方法来组合这两个条件数组(如果我措辞正确)
  2. 虽然它不会导致问题,但是否有一种更干燥的方法来创建这些老化桶?
  3. 有没有办法将 Rails3 范围与 geokit-rails 插件一起使用?

感谢您抽出时间。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天煞孤星 2024-09-17 03:06:35

试试这个:

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]

编辑方法 2

Monkey 修补 Array 类。在 config/initializers 目录中创建一个名为 monkey_patch.rb 的文件。

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

现在你可以这样做:

cond = []
cond.where("id = ?", params[id]) if params[id].present?
cond.where("state IN (?)", states) unless states.empty?
User.all(:conditions => cond)

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)
谁与争疯 2024-09-17 03:06:35

我认为更好的方法是使用匿名范围。
在这里查看:
http://railscasts.com/episodes/112-anonymous-scopes

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文