如何使用虚拟属性更新模型的属性? [英] How to update a model's attribute with a virtual attribute?

查看:44
本文介绍了如何使用虚拟属性更新模型的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 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.

试试这个:

  1. 扔掉虚拟属性,去掉整个after_save回调的东西
  2. 丢弃模型中的 user_prices 方法
  3. 在表单中将all_dates属性名称改回purchase_date
  1. Throw out the virtual attribute, and get rid of the whole after_save callback stuff
  2. Throw away the user_prices method in your model
  3. Change the all_dates attribute name back to purchase_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆