在Rails中使用多个belongs_to创建或更新的正确方法

时间:2012-12-10 17:39:02

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

Rails和Ruby的新手,并尝试正确

这是我的模特。一切都很好,但我想做的事情"对"可以这么说。 我有一个导入过程,它采用CSV并尝试创建新记录或更新现有记录。

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

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

CSV行每行可以有多个制造商(导致两个几乎相同的行,只有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

2 个答案:

答案 0 :(得分:0)

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

  

new_record?()public

     

如果尚未保存此对象(即记录),则返回true   对象尚不存在;否则,返回false。

以下内容仅在parcel对象确实是新记录时执行:

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

答案 1 :(得分:0)