Note that there are some explanatory texts on larger screens.

plurals
  1. PORails 3. Saving an association which attributes are represented by a value object
    primarykey
    data
    text
    <p>Why can't I save changes in an associated object saving a current object if attributes of the first one are represented by a value object?</p> <p>For example, I have a simple e-commerce application. It use a <em>Client</em> model for manipulating clients</p> <p><strong>Client model</strong></p> <pre> <code> # db/migrate/&lt;...&gt;_create_clients.rb class CreateClients &lt; ActiveRecord::Migration def self.up create_table :clients do |t| t.string :name end end def self.down drop_table :clients end end </code> </pre> <p> </p> <pre> <code> # app/models/client.rb Client &lt; ActiveRecord::Base has_one :balance end </code> </pre> <p>and an associated <em>Balance</em> model for holding thier balances.</p> <p><strong>Balance model</strong></p> <pre> <code> # db/migrate/&lt;...&gt;_create_balances.rb class CreateBalances &lt; 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 </code> </pre> <pre> <code> # app/models/balance.rb class Balance &lt; ActiveRecord::Base belongs_to :client composed_of :money, :mapping =&gt; [%w{amount cents}, %w{currency currency_as_string}], :constructor =&gt; -&gt;(amount, currency) { Money.new(amount || 0, currency || 'RUB') } end </code> </pre> <p>The <em>Balance</em> model uses a <em>Money</em> object from an external library called <a href="http://money.rubyforge.org/index.html" rel="nofollow">Money</a>. The object represents model's attributes <em>amount</em> and <em>currency</em> adding to the model useful methods for manipulating those attributes.</p> <p><strong>Gemfile</strong></p> <pre> <code> # Gemfile gem 'money' </pre> <p></code></p> <p>I have some seed data in <em>seeds.rb</em>.</p> <p><strong>Seeds</strong></p> <pre> <code> # db/seeds.rb elena = Client.create(:name => 'Elena') elena.build_balance.money = Money.new(0, 'RUB') elena.save </code> </pre> <p>When I try to change a balance of the client it isn't changed in spite of the <em>save</em> method of the current object returns <em>true</em>.</p> <pre> <code> &gt;&gt; elena = Client.find_by_name('Elena') =&gt; #&lt;Client id: 1, name: "Elena"&gt; &gt;&gt; elena.balance =&gt; #&lt;Balance id: 1, amount: 0, currency: "RUB", client_id: 1&gt; &gt;&gt; elena.balance.money =&gt; 0.00 &gt;&gt; elena.balance.money += Money.new(50000, 'RUB') =&gt; 500.00 &gt;&gt; elena.save =&gt; true # log/development.log # no changes </code> </pre> <p>However, I <em>can</em> save the changes using the following two ways.</p> <p><strong>1.</strong></p> <pre> <code> &gt;&gt; elena = Client.find_by_name('Elena') =&gt; #&lt;Client id: 1, name: "Elena"&gt; &gt;&gt; balance = Balance.find(elena.id) =&gt; #&lt;Balance id:1 , amount: 0, currency: "RUB", client_id: 1&gt; &gt;&gt; balance.money += Money.new(50000, 'RUB') =&gt; 500.00 &gt;&gt; balance.save =&gt; true # log/development.log # UPDATE "balances" SET "amount" = 50000 WHERE ("balances"."id" = 1) </pre> <p></code></p> <p><strong>2.</strong></p> <pre> <code> &gt;&gt; elena = Client.find_by_name('Elena') =&gt; #&lt;Client id:1, name:"Elena"&gt; &gt;&gt; elena.balance.money += Money.new(50000, 'RUB') =&gt; 500.00 &gt;&gt; elena.balance.save =&gt; true # log/development.log # UPDATE "balances" SET "amount" = 50000 WHERE ("balances"."id" = 1) </code> </pre> <p>Despite I can save changes of a balance using the aforementioned ways I would like to know why I can't do it using the “traditional” <i>&lt;current_model&gt;</i>.save method.</p> <p>Thanks.</p> <p>Debian GNU/Linux 5.0.6;</p> <p>Ruby 1.9.2;</p> <p>Ruby on Rails 3.0.1;</p> <p>Money 3.1.5.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload