2010-11-07 69 views
2

如果第一个属性由值对象表示,为什么我无法将关联对象中的更改保存为当前对象?Rails 3.保存属性由值对象表示的关联

例如,我有一个简单的电子商务应用程序。它使用客户模型操纵客户

客户端模式

 

# db/migrate/<...>_create_clients.rb 

class CreateClients < ActiveRecord::Migration 
    def self.up 
    create_table :clients do |t| 
     t.string :name 
    end 
    end 

    def self.down 
    drop_table :clients 
    end 
end 
 

 

# app/models/client.rb 

Client < ActiveRecord::Base 
    has_one :balance 
end 
 

和相关平衡模型拿着thier余额。

余额模型

 

# db/migrate/<...>_create_balances.rb 

class CreateBalances < ActiveRecord::Migration 
    def self.up 
    create_table :balances do |t| 
     t.integer :amount 
     t.string  :currency 
     t.references :client 
    end 
    end 

    def self.down 
    drop_table :balances 
    end 
end 
 
 

# app/models/balance.rb 

class Balance < ActiveRecord::Base 
    belongs_to :client 

    composed_of :money, 
    :mapping  => 
     [%w{amount cents}, %w{currency currency_as_string}], 
    :constructor => 
     ->(amount, currency) { Money.new(amount || 0, currency || 'RUB') } 
end 
 

余额模型使用从所谓Money外部库中的钱对象。该对象表示模型的属性数量货币向模型添加了用于操作这些属性的有用方法。

的Gemfile

 

# Gemfile 

gem 'money' 

我在seeds.rb一些种子数据。

种子

 

# db/seeds.rb 

elena = Client.create(:name => 'Elena') 
elena.build_balance.money = Money.new(0, 'RUB') 
elena.save 
 

当我尝试更改客户端是不是尽管当前对象的保存方法的改变的平衡返回

 

>> elena = Client.find_by_name('Elena') 
=> #<Client id: 1, name: "Elena"> 

>> elena.balance 
=> #<Balance id: 1, amount: 0, currency: "RUB", client_id: 1> 

>> elena.balance.money 
=> 0.00 

>> elena.balance.money += Money.new(50000, 'RUB') 
=> 500.00 

>> elena.save 
=> true 

# log/development.log 
# no changes 
 

不过,我可以您可以采用以下两种方式的变化。

1.

 

>> elena = Client.find_by_name('Elena') 
=> #<Client id: 1, name: "Elena"> 

>> balance = Balance.find(elena.id) 
=> #<Balance id:1 , amount: 0, currency: "RUB", client_id: 1> 

>> balance.money += Money.new(50000, 'RUB') 
=> 500.00 

>> balance.save 
=> true 

# log/development.log 
# UPDATE "balances" SET "amount" = 50000 WHERE ("balances"."id" = 1) 

2。

 

>> elena = Client.find_by_name('Elena') 
=> #<Client id:1, name:"Elena"> 

>> elena.balance.money += Money.new(50000, 'RUB') 
=> 500.00 

>> elena.balance.save 
=> true 

# log/development.log 
# UPDATE "balances" SET "amount" = 50000 WHERE ("balances"."id" = 1) 
 

尽管我可以节省使用上述的方法,我想知道一个平衡的变化,为什么我不能用“传统” <current_model> .save方法做到这一点。

谢谢。

Debian GNU/Linux 5.0.6;

Ruby 1.9.2;

Ruby on Rails 3.0.1;

钱3.1.5。

回答

1

它是通过这样实现的:

# app/models/client.rb 

Client < ActiveRecord::Base 
    has_one :balance, :autosave => true 
end 

与之前的相关的问题是,当你调用elena.save,它只是想看看如果客户对象发生了变化。如果你在第一个例子中进行这样的检查:

>> elena.changed? 
=> false 
>> elena.balance.changed? 
=> true 

如果你不通知的ActiveRecord检查关联模型就会偷懒,保存父模型时忽略的变化。

+0

我现在明白了。非常感谢,帕特里克。 – Shamaoke 2010-11-07 13:23:18