如何使用虚拟属性更新模型的属性? [英] How to update a model's attribute with a virtual attribute?
问题描述
我有一个名为 UserPrice
的模型,它的表中有属性 :purchase_date
(一个 date_select).使用我的表单,我可以一次创建多个 user_prices,但为了用户方便,我在我的 UserPrice
模型中创建了一个名为 :all_dates
的虚拟属性,它也是一个 date_select 字段,它的工作是替换 :purchase_dates
,因此用户只需选择 :all_dates
字段作为日期.
I have a model named UserPrice
which has the attribute :purchase_date
(a date_select) in its table. With my form I can create multiple user_prices at once but for user convenience I made a virtual attribute inside of my UserPrice
model called :all_dates
that's also a date_select field and its job is to be the replacement of the :purchase_dates
so users only have to select the :all_dates
field for the date.
问题&问题
:all_dates
字段不会更新我正在创建的 user_prices 的 :purchase_date
字段.我需要做什么才能让我的 :all_dates
字段更新我的新 UserPrices
的 :purchase_date
字段?
The :all_dates
field is not updating the :purchase_date
fields of my user_prices that are being created. What do I need to do in order to get my :all_dates
field to update the :purchase_date
fields of my new UserPrices
?
有没有人有关于如何做到这一点的任何提示?
参数
Parameters:
"user_price"=> {
"all_dates(2i)"=>"10",
"all_dates(3i)"=>"27",
"all_dates(1i)"=>"2011"
},
"user_prices"=>
{
"0"=>{"product_name"=>"Item1", "store"=>"Apple Store","price"=>"6"},
"1"=>{"product_name"=>"Item2", "store"=>"Apple Store", "price"=>"7"}
},
"commit"=>"Submit"}
<小时>
代码
class CreateUserPrices < ActiveRecord::Migration
def self.up
create_table :user_prices do |t|
t.decimal :price
t.integer :product_id
t.date :purchase_date
t.timestamps
end
end
end
我去掉了 :purchase_date
字段,所以它不在 user_price 循环内.
I took out the :purchase_date
field so it isn't inside of the user_price loop.
<%= form_tag create_multiple_user_prices_path, :method => :post do %>
<%= date_select("user_price", "all_dates" ) %>
<% @user_prices.each_with_index do |user_price, index| %>
<%= fields_for "user_prices[#{index}]", user_price do |up| %>
<%= render "user_price_fields", :f => up %>
<% end %>
<% end %>
<% end %>
class UserPrice < ActiveRecord::Base
attr_accessible :price, :product_name, :purchase_date, :all_dates, :store
attr_accessor :all_dates
after_save :save_all_dates_to_user_prices
composed_of :all_dates, :class_name => "DateTime",
:mapping => %w(Time to_s),
:constructor => Proc.new { |item| item },
:converter => Proc.new { |item| item }
def user_prices
@user_prices = Array.new() { UserPrice.new }
end
protected
def save_all_dates_to_user_prices
if !self.all_dates.nil?
self.user_prices.each {|up| up.purchase_date = self.all_dates if up.new_record?}
end
end
class UserPricesController < ApplicationController
def new
@user_prices = Array.new(5) { UserPrice.new }
end
def create_multiple
@user_prices = params[:user_prices].values.collect { |up| UserPrice.new(up) }
if @user_prices.all?(&:valid?)
@user_prices.each(&:save!)
redirect_to :back, :notice => "Successfully added prices."
else
redirect_to :back, :notice => "Error, please try again."
end
end
推荐答案
这是一个尝试在模型中做最好留给控制器的事情.您在这里要做的就是在创建时从与模型没有直接关联的参数自动分配某个属性.但是您甚至没有将额外的参数传递给模型的任何地方 - 您正在从参数哈希的 user_prices
部分创建模型实例,但是 user_price
子 -散列不在任何地方使用.无论如何,与模型相比,这是与视图和采取的操作更密切相关的行为,因此请将其保留在控制器中.
This is a case of trying to do in a model what is better left to the controller. All you're trying to do here is to auto-assign a certain attribute on creation from a parameter not directly tied to your model. But you're not even passing that extra parameter to the model anywhere - you're creating your model instances from the user_prices
parts of the parameter hash, but the user_price
sub-hash is not used anywhere. In any case, this is behavior that is more closely related to the view and action taken than the model, so keep it in the controller.
试试这个:
- 扔掉虚拟属性,去掉整个
after_save
回调的东西 - 丢弃模型中的
user_prices
方法 - 在表单中将
all_dates
属性名称改回purchase_date
- Throw out the virtual attribute, and get rid of the whole
after_save
callback stuff - Throw away the
user_prices
method in your model - Change the
all_dates
attribute name back topurchase_date
in the form
那么你的参数哈希应该是这样的:
Then your parameter hash should look like this:
{"user_price"=> {
"purchase_date(2i)"=>"10",
"purchase_date(3i)"=>"27",
"purchase_date(1i)"=>"2011"
},
"user_prices"=>
{
"0"=>{"product_name"=>"Item1", "store"=>"Apple Store","price"=>"6"},
"1"=>{"product_name"=>"Item2", "store"=>"Apple Store", "price"=>"7"}
}}
剩下要做的就是将单个 user_price
属性合并到 create_multiple
操作中的每个 user_prices
子哈希中.用这个替换该操作中的第一行:
All that's left to do is to merge the single user_price
attributeS into each user_prices
sub-hash in your create_multiple
action. Replace the first line in that action with this:
@user_prices = params[:user_prices].values.collect do |attributes|
UserPrice.new(attributes.merge(params[:user_price]))
end
这篇关于如何使用虚拟属性更新模型的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!