4

我试图实现条件链接,这就是我得到的:

控制器索引动作代码:

@range_start = params[:range_start]
@range_stop = params[:range_stop]
Contract.within_range(@range_start, @range_stop)

型号代码:

def self.within_range(range_start = Date.today - 1.month, range_stop = nil)
  self.started_after(range_start).started_before(range_stop)
end

def self.started_after(range_start)
  if range_start.blank?
    self
  else
    self.where('start_date >=?', range_start)
  end
end

def self.started_before(range_stop)
  if range_stop.blank?
    self
  else
    self.where('start_date<=?', range_stop)
  end
end

它有效,但看起来不太好。我尝试使用 对其进行一些改进tap,但没有成功。如何改进此代码?

更新: in 可以转换为内联条件,但也许可以改进其他的东西?

range_start.blank? ? self : self.where('start_date >=?', range_start)

UPDATE2:如果range_stop没有设置,这个代码不是真的有效,started_after条件不适用。

我必须started_before从不放松的首要条件是什么?

4

4 回答 4

10

时间已经过去,denis.peplin 的解决方案已经被弃用。否则它是正确的,你需要一个用于链接的关系。因此,scoped您应该all像这样使用,而不是使用:

def self.started_before(range_stop)
  if range_stop.blank?
    all
  else
    where('start_date<=?', range_stop)
  end
end

但是您也可以将其写为更简洁的范围:

scope :started_before, ->(range_stop){ range_stop.blank? ? all : where('start_date<=?', range_stop) }
于 2014-01-21T12:06:08.583 回答
3

在红宝石世界中,有一种东西叫做scope可以做你想做的事。

scope :started_after, lambda {|x| where("start_date >=?", x) }
scope :started_before, lambda{|x| where("start_date <=?", x) }

或者在一行

scope :starts_between, lambda{|start,finish| where("start_date >=? AND start_date <= ?", start, finish) }

范围是一个活跃的记录功能,所以你可以简单地调用:

Contract.starts_between(date1, date2)

当您希望第二个参数有条件时:

def self.within_range(start, finish = nil)
  data = Contract.started_after(start)
  data = data.started_before(finish) unless finish.nil?
  data
end
于 2012-10-16T08:49:32.927 回答
3

我想尝试澄清以这种方式进行条件链接的目的:想法是将条件隐藏在某些方法中,并链接方法,因此生成的方法将很简单。

这是可能的,但 ActiveRecord::Base 类的子级不能被链接起来。只有关系可以链接。

所以不要这样做:

def self.started_before(range_stop)
  if range_stop.blank?
    self
  else
    self.where('start_date<=?', range_stop)
  end
end

应该这样做:

def self.started_before(range_stop)
  if range_stop.blank?
    scoped
  else
    self.where('start_date<=?', range_stop)
  end
end

只有一个变化:self被替换为scoped,并且 now 方法总是返回一个范围,并且可以被链接。

感谢这篇文章的提示:http ://blog.mitchcrowe.com/blog/2012/04/14/10-most-underused-activerecord-relation-methods/

于 2012-11-08T16:33:44.767 回答
1

我添加了这个:

scope :dynamic, -> (chain=nil) { chain.present? ? chain.call : nil }

现在你可以像这样使用它

conditional_scope = x ? Model.scope1 : Model.scope2
Model.scope3.dynamic(conditional_scope).scope4
于 2015-05-13T16:39:42.090 回答