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

How do I check for the existence of attributes on an object and update missing ones?

假设我有以下代码:

    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

如何重构上面的代码以使其更加干练和优雅?

您可以使用 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

您可能想在 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