我有两种模特关系:
class Totalsold < ActiveRecord::Base
attr_accessible :qty, :total_cost, :date, :price_id, :price_attributes
belongs_to :price
accepts_nested_attributes_for :price
before_validation :calculation_total_cost
private
def calculation_total_cost
@price = Price.where(:id => price_id).first
if qty.nil?
self.qty = 0
end
self.total_cost = qty.to_f * @price.cost
end
end
class Totalsold < ActiveRecord::Base
attr_accessible :cost
has_many :totalsolds
end
calculation_total_cost
方法从total_cost
* qty
cost
成功发布before_validation
计算。不是很好吗?因为我在提交表单时使用多个创建并查看日志here(我使用pastebin进行粘贴应用日志)。
我的案子还有另外一种方法吗?为更好的表现提供解决方案。
这是创建方法:
def create
@totalsolds = params[:totalsolds].values.collect { |ts| Totalsold.new(ts) }
if @totalsolds.all?(&:valid?)
@totalsolds.each(&:save!)
redirect_to lhg_path
else
render :action => 'new'
end
end
答案 0 :(得分:1)
为了提高效率,您需要执行以下操作:
- 将
save
调用减少为每个对象1个- 将您的功能移至
before_save
- 从回调中删除所有不必要的查询
创建强>
首先,您需要提高create
方法的效率。目前,您正在循环使用params[:totalsolds]
哈希,并运行验证&amp;每次都保存请求。它对我来说看起来很麻烦:
def create
totalsold = params[:totalsolds]
for total in totalsold do
if total.save #-> should invoke validation
redirect_to lhg_path
else
render :action => 'new'
end
end
保存前
目前,您正在呼叫before_validation
。这意味着每次验证ActiveRecord
对象时,您的回调都将运行。这是低效的,尽管可能是您的应用程序工作方式的一部分
我会将其移至before_save
回调:
before_save :set_qty
before_save :calculate_total_cost
private
def set_qty
self.qty = 0 if qty.nil?
end
def calculate_total_cost
price = Price.find(price_id).cost
total_cost = qty * price #-> qty doesn't need to be float (I think)
end
不必要的查询
您的主要问题是您使用了许多不需要的查询。 Prime示例:Price.where(:id => price_id).first
非常低效 - 只需使用find
来提取单个记录(当您处理主键时)
希望这会有所帮助!!