如何检查对象上是否存在属性并更新丢失的属性?

时间:2018-05-15 04:15:16

标签: ruby-on-rails ruby ruby-on-rails-5 dry

想象一下,我有以下代码:

    stock = Stock.find_or_initialize_by(ticker: ticker)
    if stock.new_record?
      stock.assign_attributes(jse_link: link, name: name, price: price)
      stock.save!
      puts "#{stock.ticker} created successfully with price: #{stock.price}, name: #{stock.name} and can be viewed at #{stock.jse_link}."
    elsif stock.jse_link.empty? || stock.name.empty?
      stock.update!(jse_link: link, name: name, price: price)
      puts "#{stock.ticker} updated successfully with price: #{stock.price}, name: #{stock.name} and can be viewed at #{stock.jse_link}."
    elsif !stock.price.eql? price
      stock.update!(price: price)
      puts "#{stock.ticker} updated successfully with price: #{stock.price}."
    end

如何将上述代码重构为DRY&优雅?

2 个答案:

答案 0 :(得分:2)

您可能需要考虑Stock模型中的方法,如下所示:

def patch(price:, new_link:, new_name:)
  update(
    price: price,
    jse_link: (jse_link.presence || new_link),
    name: (name.presence || new_name)
  )
end

在没有条件的情况下在你的控制器中使用它:

if stock.new_record?
  # ...
else
  stock.patch(new_link: link, new_name: name, price: price)
end

答案 1 :(得分:0)

您可以使用validations

class Stock < ActiveRecord::Base
  validate :link_and_name, on: :validate_link_and_name

  def link_and_name
    if jse_link.empty? && name.empty?
      errors.add(:link_and_name_empty, 'need to provide link and name')
    end
  end
end

然后在你的控制器中:

stock.update(price: price)
unless stock.valid?(:validate_link_and_name)
  stock.update(jse_link: link, name: name)
end