我有一个表材质,has_one
与MaterialCosts相关,has_one
与MaterialCharges相关。它们都属于材料,在删除或记录材料时应dependent: :destroy
。
我不确定如何构造Material类。必须使用每个Material实例的两个属性来计算MaterialCosts和MaterialCharges中的字段。这些是cost_per_sqm
和ink_per_sqm
。 factor
是Material中的一个字段,也用于MaterialCharges。我是否需要在Material中初始化它们,以便为create方法使用实例变量?或者是attr_accessor
所需要的全部内容?
我知道代码需要重构,但是当我尝试播种数据时,我也遇到了这个错误:
NoMethodError: undefined method `[]' for nil:NilClass on line 26 seeds.rb
第26行种子.rb:
Material.create({
product_name: "Novajet Art 255gsm", guk_name: "none", roll_width_in: 44, roll_length_m: 30, factor: 7, rounded_sale_price: 71, list_price: 240.00, cost_per_sqm: 7.16, ink_per_sqm: 3, supplier_discount: 0, sell_per_sqm: 71.11
})
这是我的代码:
class Material < ApplicationRecord
has_and_belongs_to_many :job_entries
has_one :material_cost, dependent: :destroy
has_one :material_charge, dependent: :destroy
attr_accessor :cost_per_sqm, :ink_per_sqm, :factor
def initialize(options)
@cost_per_sqm = options['cost_per_sqm'].to_f
@ink_per_sqm = options['ink_per_sqm'].to_f
@factor = options['@factor'].to_f
@total_cost = @cost_per_sqm * @ink_per_sqm
end
after_create :set_material_cost, :set_material_charge
A4_FACTOR = 0.0626514876
A3_FACTOR = 0.124548139
A2_FACTOR = 0.249096276
A1_FACTOR = 0.499702226
B0_FACTOR = 1.41585523
B1_FACTOR = 0.706656651
B2_FACTOR = 0.353328326
B3_FACTOR = 0.176664163
B4_FACTOR = 0.0878836952
private
def set_material_cost
@material_cost = self.create_material_cost(
cost_a4: @total_cost * A4_FACTOR,
cost_a3: @total_cost * A3_FACTOR,
cost_a2: @total_cost * A2_FACTOR,
cost_a1: @total_cost * A1_FACTOR,
cost_b0: @total_cost * B0_FACTOR,
cost_b1: @total_cost * B1_FACTOR,
cost_b2: @total_cost * B2_FACTOR,
cost_b3: @total_cost * B3_FACTOR,
cost_b4: @total_cost * B4_FACTOR
)
end
def set_material_charge
@material_charge = self.create_material_charge(
sell_a4: @total_cost * A4_FACTOR * @factor,
sell_a3: @total_cost * A3_FACTOR * @factor,
sell_a2: @total_cost * A2_FACTOR * @factor,
sell_a1: @total_cost * A1_FACTOR * @factor,
sell_b0: @total_cost * B0_FACTOR * @factor,
sell_b1: @total_cost * B1_FACTOR * @factor,
sell_b2: @total_cost * B2_FACTOR * @factor,
sell_b3: @total_cost * B3_FACTOR * @factor,
sell_b4: @total_cost * B4_FACTOR * @factor
)
end
end
class MaterialCost < ApplicationRecord
belongs_to :material
end
class MaterialCharge < ApplicationRecord
belongs_to :material
end
这是代码应该是什么样的?
答案 0 :(得分:1)
如曹提到的那样,请勿覆盖initialize
,但如果有,则必须拨打super
。
# use '*args' so super can use any arguments to 'new'
def initialize(*args)
# as first line so Rails will do it's "magic" before yours
super
# these have got values by Rails (in super) IF you have them
# in the call to 'new'
@cost_per_sqm = @cost_per_sqm.to_f
@ink_per_sqm = @ink_per_sqm.to_f
# (you have forgot this as attr_accessor?)
@factor = @factor.to_f
@total_cost = @cost_per_sqm * @ink_per_sqm
end
但我不想使用initialize
,而是使用其他方法
# instead of overriding 'initialize'
def init_after_create
return if @total_cost
# these have got values by Rails (in new) IF you have them
# in the call to 'new'
@cost_per_sqm = @cost_per_sqm.to_f
@ink_per_sqm = @ink_per_sqm.to_f
# (you have forgot this as attr_accessor?)
@factor = @factor.to_f
@total_cost = @cost_per_sqm * @ink_per_sqm
end
def set_material_cost
init_after_create
@material_cost = self.create_material_cost(
cost_a4: @total_cost * A4_FACTOR,
cost_a3: @total_cost * A3_FACTOR,
....
end
def set_material_charge
init_after_create
@material_charge = self.create_material_charge(
sell_a4: @total_cost * A4_FACTOR * @factor,
sell_a3: @total_cost * A3_FACTOR * @factor,
...
end
提示,如果您在方法调用中有Hash
作为最后一个参数,或者在Array
中您不必使用{ ... }
# example method
def some_method(options)
...
end
some_method(xxx: 1, yyy: 2)
# example array
arr = [ 1, 2, xxx: 1, yyy: 2 ]
#=> [1, 2, {:xxx=>1, :yyy=>2}]