最初のオブジェクトの属性が値オブジェクトで表されている場合、現在のオブジェクトを保存する関連オブジェクトの変更を保存できないのはなぜですか?
たとえば、単純な電子商取引アプリケーションがあります。クライアントを操作するためにクライアントモデルを使用します
クライアント モデル
# 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
および残高を保持するための関連するBalanceモデル。
バランスモデル
# 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
Balanceモデルは、 Money という外部ライブラリのMoneyオブジェクトを使用します。オブジェクトはモデルの属性金額と通貨を表し、これらの属性を操作するための便利なメソッドをモデルに追加します。
Gemfile
# Gemfile
gem 'money'
seed.rbにいくつかのシード データがあります。
種
# db/seeds.rb
elena = Client.create(:name => 'Elena')
elena.build_balance.money = Money.new(0, 'RUB')
elena.save
クライアントのバランスを変更しようとすると、現在のオブジェクトのsaveメソッドがtrueを返すにもかかわらず変更されません。
>> 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
ただし、次の 2 つの方法を使用して変更を保存できます。
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;
ルビー 1.9.2;
Ruby on Rails 3.0.1;
お金 3.1.5.