使用ActiveRecord进行条件链接

den*_*lin 3 activerecord ruby-on-rails

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

控制器索引动作代码:

@range_start = params[:range_start]
@range_stop = params[:range_stop]
Contract.within_range(@range_start, @range_stop)
Run Code Online (Sandbox Code Playgroud)

型号代码:

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
Run Code Online (Sandbox Code Playgroud)

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

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

range_start.blank? ? self : self.where('start_date >=?', range_start)
Run Code Online (Sandbox Code Playgroud)

UPDATE2:如果range_stop未设置,则此代码started_after不起作用,条件不适用.

我必须从什么地方回来started_before放松第一个条件?

wds*_*pkr 10

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

def self.started_before(range_stop)
  if range_stop.blank?
    all
  else
    where('start_date<=?', range_stop)
  end
end
Run Code Online (Sandbox Code Playgroud)

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

scope :started_before, ->(range_stop){ range_stop.blank? ? all : where('start_date<=?', range_stop) }
Run Code Online (Sandbox Code Playgroud)

  • 范围总是返回可链接的对象,因此在范围内不需要"all".试试这个:`scope:started_before, - >(range_stop){where('start_date <=?',range_stop)如果是range_stop.present?}` (3认同)
  • `.all`不返回`ActiveRecord :: Relation`; 它**执行查询并返回一个数组**.因此,如果函数返回`.all`,则意味着它不可链接.另外,返回一个`.all`意味着该函数并不总是返回相同的类型 - 由于它们具有不同的接口,将来很可能会出现问题.注意:rails 4.x和3.x之间可能有所不同. (2认同)