【问题标题】:Correct way to create or update with multiple belongs_to in Rails在 Rails 中使用多个 belongs_to 创建或更新的正确方法
【发布时间】:2012-11-28 04:11:15
【问题描述】:

刚接触 Rails 和 Ruby 并尝试正确地做事

这是我的模型。一切正常,但我想以“正确”的方式做事。 我有一个导入过程,它采用 CSV 并尝试创建新记录或更新现有记录。

所以过程是 1.) 解析 csv 行 2.) 查找或创建记录 3.) 保存记录

我的工作很完美,但代码似乎可以改进。如果不涉及 ParcelType 那就没问题了,因为我正在从制造商创建/检索一个包裹,所以该外键已为我预先填充。但是 ParcelType 不是。无论如何都要预先填充类型和制造商,因为我在搜索中都使用它们?

CSV 行每行可以有多个制造商(导致 2 个几乎相同的行,只是使用 diff mfr_id)所以这就是 .each 的含义

manufacturer_id.split(";").each do |mfr_string|
  mfr = Manufacturer.find_by_name(mfr_string)

  # If it's a mfr we don't care about, don't put it in the db
  next if mfr.nil?

  # Unique parcel is defined by it's manufacturer, it's type, it's model number, and it's reference_number
  parcel = mfr.parcels.of_type('FR').find_or_initialize_by_model_number_and_reference_number(attributes[:model_number], attributes[:reference_number])
  parcel.assign_attributes(attributes)

  # this line in particular is a bummer. if it finds a parcel and I'm updating, this line is superfulous, only necessary when it's a new parcel
  parcel.parcel_type = ParcelType.find_by_code('FR')

  parcel.save!
end


class Parcel < ActiveRecord::Base
  belongs_to :parcel_type
  belongs_to :manufacturer

  def self.of_type(type)
    joins(:parcel_type).where(:parcel_types => {:code => type.upcase}).readonly(false) unless type.nil?
  end
end


class Manufacturer < ActiveRecord::Base
  has_many :parcels
end


class ParcelType < ActiveRecord::Base
  has_many :parcels
end

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 activerecord idioms


    【解决方案1】:

    听起来new_record? 方法就是您正在寻找的。

    new_record?() 公开

    如果此对象尚未保存,则返回 true ——即一条记录 因为对象还不存在;否则,返回 false。

    只有在包裹对象确实是新记录时才会执行以下操作:

    parcel.parcel_type = ParcelType.find_by_code('FR') if parcel.new_record?
    

    【讨论】:

    • 我想我也可以只做'if parcel.parcel_type.ni?'但更多的是我正在寻找的是一种方法来拥有一个新的包裹,它的制造商和类型已经预先填充(我可以通过 Mfr 创建包裹来获得 Mfr)
    • 嗯,如果它只是真正为您节省一行代码而没有任何性能提升,那可能有点不必要的复杂。老实说,我不确定您是否甚至可以构建一个具有多个默认情况下自动预填充的单个父对象的子对象。如果您真的想将所有内容留给 ActiveRecord,那么您最好的选择可能是 ActiveRecord callback 方法之一。
    • 给了你正确的答案,这是不必要的复杂。我真正需要做的唯一地方是在后端导入脚本中,所以没什么大不了的。
    【解决方案2】:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    相关资源
    最近更新 更多