Rails ActiveRecord :pluck and :map return two different values - why?
up vote
0
down vote
favorite
I have an ActiveRecord model (using STI) MonetaryChange::PaymentPromise
that has subtotal_cents
as an attribute / column (an integer).
My controller is updating that model/attribute, but for some reason, I'm getting the old/original value when I call map
and the updated (correct) value when I call pluck
. For example:
V410MonetaryChange::PaymentPromise.where(id: 1).pluck(:subtotal_cents)
=> [24600] # this is the correct updated value
V410MonetaryChange::PaymentPromise.where(id: 1).map(&:subtotal_cents)
=> [12300] # this is the original value, but it should have been updated to 24600
I notice that the SQL that Rails generates for the pluck
method is much simpler:
(0.5ms) SELECT "v410_monetary_changes"."subtotal_cents"
FROM "v410_monetary_changes"
WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise')
AND "v410_monetary_changes"."deleted_at" IS NULL
AND "v410_monetary_changes"."id" = $1 [["id", 1]]
but the SQL for the map
method loads a whole bunch of associations after the first query:
V410MonetaryChange::PaymentPromise Load (0.6ms) SELECT "v410_monetary_changes".* FROM "v410_monetary_changes" WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise') AND "v410_monetary_changes"."deleted_at" IS NULL AND "v410_monetary_changes"."id" = $1 [["id", 1]]
V410OrderedSku Load (0.3ms) SELECT "v410_ordered_skus".* FROM "v410_ordered_skus" WHERE "v410_ordered_skus"."deleted_at" IS NULL AND "v410_ordered_skus"."id" = $1 LIMIT 1 [["id", 1]]
V410OrderedSkusV410Sku Load (0.2ms) SELECT "v410_ordered_skus_v410_skus".* FROM "v410_ordered_skus_v410_skus" WHERE "v410_ordered_skus_v410_skus"."v410_ordered_sku_id" = $1 LIMIT 1 [["v410_ordered_sku_id", 1]]
V410Sku Load (0.2ms) SELECT "v410_skus".* FROM "v410_skus" WHERE "v410_skus"."id" = $1 LIMIT 1 [["id", 1]]
Any idea why this is the case, and how I can resolve this?
I tried adding .reload
to my query, but the results were the same:
V410MonetaryChange::PaymentPromise.where(id: 1).reload.map(&:subtotal_cents)
=> [12300]
Edit 1:
I can confirm that the database has the correct value (24600). When I open a psql
console, and run the query:
SELECT "v410_monetary_changes"."subtotal_cents"
FROM "v410_monetary_changes"
WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise')
AND "v410_monetary_changes"."deleted_at" IS NULL
AND "v410_monetary_changes"."id" = 1;
I get:
subtotal_cents
----------------
24600
(1 row)
So Rails must be doing something with the associations that is causing it to give me an old version of the record. Any ideas why?
ruby-on-rails ruby-on-rails-4 activerecord
add a comment |
up vote
0
down vote
favorite
I have an ActiveRecord model (using STI) MonetaryChange::PaymentPromise
that has subtotal_cents
as an attribute / column (an integer).
My controller is updating that model/attribute, but for some reason, I'm getting the old/original value when I call map
and the updated (correct) value when I call pluck
. For example:
V410MonetaryChange::PaymentPromise.where(id: 1).pluck(:subtotal_cents)
=> [24600] # this is the correct updated value
V410MonetaryChange::PaymentPromise.where(id: 1).map(&:subtotal_cents)
=> [12300] # this is the original value, but it should have been updated to 24600
I notice that the SQL that Rails generates for the pluck
method is much simpler:
(0.5ms) SELECT "v410_monetary_changes"."subtotal_cents"
FROM "v410_monetary_changes"
WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise')
AND "v410_monetary_changes"."deleted_at" IS NULL
AND "v410_monetary_changes"."id" = $1 [["id", 1]]
but the SQL for the map
method loads a whole bunch of associations after the first query:
V410MonetaryChange::PaymentPromise Load (0.6ms) SELECT "v410_monetary_changes".* FROM "v410_monetary_changes" WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise') AND "v410_monetary_changes"."deleted_at" IS NULL AND "v410_monetary_changes"."id" = $1 [["id", 1]]
V410OrderedSku Load (0.3ms) SELECT "v410_ordered_skus".* FROM "v410_ordered_skus" WHERE "v410_ordered_skus"."deleted_at" IS NULL AND "v410_ordered_skus"."id" = $1 LIMIT 1 [["id", 1]]
V410OrderedSkusV410Sku Load (0.2ms) SELECT "v410_ordered_skus_v410_skus".* FROM "v410_ordered_skus_v410_skus" WHERE "v410_ordered_skus_v410_skus"."v410_ordered_sku_id" = $1 LIMIT 1 [["v410_ordered_sku_id", 1]]
V410Sku Load (0.2ms) SELECT "v410_skus".* FROM "v410_skus" WHERE "v410_skus"."id" = $1 LIMIT 1 [["id", 1]]
Any idea why this is the case, and how I can resolve this?
I tried adding .reload
to my query, but the results were the same:
V410MonetaryChange::PaymentPromise.where(id: 1).reload.map(&:subtotal_cents)
=> [12300]
Edit 1:
I can confirm that the database has the correct value (24600). When I open a psql
console, and run the query:
SELECT "v410_monetary_changes"."subtotal_cents"
FROM "v410_monetary_changes"
WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise')
AND "v410_monetary_changes"."deleted_at" IS NULL
AND "v410_monetary_changes"."id" = 1;
I get:
subtotal_cents
----------------
24600
(1 row)
So Rails must be doing something with the associations that is causing it to give me an old version of the record. Any ideas why?
ruby-on-rails ruby-on-rails-4 activerecord
It should be the same. Try restarting your rails console.
– EvanG
Nov 12 at 16:50
@EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
– Greg Matthew Crossley
Nov 12 at 16:51
Did you override yoursubtotal_cents
in your model?
– Marcin Kołodziej
Nov 12 at 16:54
@MarcinKołodziej I have two othersubtotal_cents
methods in parent models, but not in the model I am querying.
– Greg Matthew Crossley
Nov 12 at 16:59
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have an ActiveRecord model (using STI) MonetaryChange::PaymentPromise
that has subtotal_cents
as an attribute / column (an integer).
My controller is updating that model/attribute, but for some reason, I'm getting the old/original value when I call map
and the updated (correct) value when I call pluck
. For example:
V410MonetaryChange::PaymentPromise.where(id: 1).pluck(:subtotal_cents)
=> [24600] # this is the correct updated value
V410MonetaryChange::PaymentPromise.where(id: 1).map(&:subtotal_cents)
=> [12300] # this is the original value, but it should have been updated to 24600
I notice that the SQL that Rails generates for the pluck
method is much simpler:
(0.5ms) SELECT "v410_monetary_changes"."subtotal_cents"
FROM "v410_monetary_changes"
WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise')
AND "v410_monetary_changes"."deleted_at" IS NULL
AND "v410_monetary_changes"."id" = $1 [["id", 1]]
but the SQL for the map
method loads a whole bunch of associations after the first query:
V410MonetaryChange::PaymentPromise Load (0.6ms) SELECT "v410_monetary_changes".* FROM "v410_monetary_changes" WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise') AND "v410_monetary_changes"."deleted_at" IS NULL AND "v410_monetary_changes"."id" = $1 [["id", 1]]
V410OrderedSku Load (0.3ms) SELECT "v410_ordered_skus".* FROM "v410_ordered_skus" WHERE "v410_ordered_skus"."deleted_at" IS NULL AND "v410_ordered_skus"."id" = $1 LIMIT 1 [["id", 1]]
V410OrderedSkusV410Sku Load (0.2ms) SELECT "v410_ordered_skus_v410_skus".* FROM "v410_ordered_skus_v410_skus" WHERE "v410_ordered_skus_v410_skus"."v410_ordered_sku_id" = $1 LIMIT 1 [["v410_ordered_sku_id", 1]]
V410Sku Load (0.2ms) SELECT "v410_skus".* FROM "v410_skus" WHERE "v410_skus"."id" = $1 LIMIT 1 [["id", 1]]
Any idea why this is the case, and how I can resolve this?
I tried adding .reload
to my query, but the results were the same:
V410MonetaryChange::PaymentPromise.where(id: 1).reload.map(&:subtotal_cents)
=> [12300]
Edit 1:
I can confirm that the database has the correct value (24600). When I open a psql
console, and run the query:
SELECT "v410_monetary_changes"."subtotal_cents"
FROM "v410_monetary_changes"
WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise')
AND "v410_monetary_changes"."deleted_at" IS NULL
AND "v410_monetary_changes"."id" = 1;
I get:
subtotal_cents
----------------
24600
(1 row)
So Rails must be doing something with the associations that is causing it to give me an old version of the record. Any ideas why?
ruby-on-rails ruby-on-rails-4 activerecord
I have an ActiveRecord model (using STI) MonetaryChange::PaymentPromise
that has subtotal_cents
as an attribute / column (an integer).
My controller is updating that model/attribute, but for some reason, I'm getting the old/original value when I call map
and the updated (correct) value when I call pluck
. For example:
V410MonetaryChange::PaymentPromise.where(id: 1).pluck(:subtotal_cents)
=> [24600] # this is the correct updated value
V410MonetaryChange::PaymentPromise.where(id: 1).map(&:subtotal_cents)
=> [12300] # this is the original value, but it should have been updated to 24600
I notice that the SQL that Rails generates for the pluck
method is much simpler:
(0.5ms) SELECT "v410_monetary_changes"."subtotal_cents"
FROM "v410_monetary_changes"
WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise')
AND "v410_monetary_changes"."deleted_at" IS NULL
AND "v410_monetary_changes"."id" = $1 [["id", 1]]
but the SQL for the map
method loads a whole bunch of associations after the first query:
V410MonetaryChange::PaymentPromise Load (0.6ms) SELECT "v410_monetary_changes".* FROM "v410_monetary_changes" WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise') AND "v410_monetary_changes"."deleted_at" IS NULL AND "v410_monetary_changes"."id" = $1 [["id", 1]]
V410OrderedSku Load (0.3ms) SELECT "v410_ordered_skus".* FROM "v410_ordered_skus" WHERE "v410_ordered_skus"."deleted_at" IS NULL AND "v410_ordered_skus"."id" = $1 LIMIT 1 [["id", 1]]
V410OrderedSkusV410Sku Load (0.2ms) SELECT "v410_ordered_skus_v410_skus".* FROM "v410_ordered_skus_v410_skus" WHERE "v410_ordered_skus_v410_skus"."v410_ordered_sku_id" = $1 LIMIT 1 [["v410_ordered_sku_id", 1]]
V410Sku Load (0.2ms) SELECT "v410_skus".* FROM "v410_skus" WHERE "v410_skus"."id" = $1 LIMIT 1 [["id", 1]]
Any idea why this is the case, and how I can resolve this?
I tried adding .reload
to my query, but the results were the same:
V410MonetaryChange::PaymentPromise.where(id: 1).reload.map(&:subtotal_cents)
=> [12300]
Edit 1:
I can confirm that the database has the correct value (24600). When I open a psql
console, and run the query:
SELECT "v410_monetary_changes"."subtotal_cents"
FROM "v410_monetary_changes"
WHERE "v410_monetary_changes"."type" IN ('V410MonetaryChange::PaymentPromise')
AND "v410_monetary_changes"."deleted_at" IS NULL
AND "v410_monetary_changes"."id" = 1;
I get:
subtotal_cents
----------------
24600
(1 row)
So Rails must be doing something with the associations that is causing it to give me an old version of the record. Any ideas why?
ruby-on-rails ruby-on-rails-4 activerecord
ruby-on-rails ruby-on-rails-4 activerecord
edited Nov 12 at 17:05
asked Nov 12 at 16:41
Greg Matthew Crossley
323314
323314
It should be the same. Try restarting your rails console.
– EvanG
Nov 12 at 16:50
@EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
– Greg Matthew Crossley
Nov 12 at 16:51
Did you override yoursubtotal_cents
in your model?
– Marcin Kołodziej
Nov 12 at 16:54
@MarcinKołodziej I have two othersubtotal_cents
methods in parent models, but not in the model I am querying.
– Greg Matthew Crossley
Nov 12 at 16:59
add a comment |
It should be the same. Try restarting your rails console.
– EvanG
Nov 12 at 16:50
@EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
– Greg Matthew Crossley
Nov 12 at 16:51
Did you override yoursubtotal_cents
in your model?
– Marcin Kołodziej
Nov 12 at 16:54
@MarcinKołodziej I have two othersubtotal_cents
methods in parent models, but not in the model I am querying.
– Greg Matthew Crossley
Nov 12 at 16:59
It should be the same. Try restarting your rails console.
– EvanG
Nov 12 at 16:50
It should be the same. Try restarting your rails console.
– EvanG
Nov 12 at 16:50
@EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
– Greg Matthew Crossley
Nov 12 at 16:51
@EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
– Greg Matthew Crossley
Nov 12 at 16:51
Did you override your
subtotal_cents
in your model?– Marcin Kołodziej
Nov 12 at 16:54
Did you override your
subtotal_cents
in your model?– Marcin Kołodziej
Nov 12 at 16:54
@MarcinKołodziej I have two other
subtotal_cents
methods in parent models, but not in the model I am querying.– Greg Matthew Crossley
Nov 12 at 16:59
@MarcinKołodziej I have two other
subtotal_cents
methods in parent models, but not in the model I am querying.– Greg Matthew Crossley
Nov 12 at 16:59
add a comment |
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
OK, important Rails lesson learned today!
I recently added an after_initialize
callback to this model, which set the default values (including subtotal_cents
) for newly initialized records.
What I didn't realise is that this callback was re-initializing (ie overwriting in memory after load) existing records with the default values.
My fix was to change
after_initialize :set_default_currency_amounts
to
after_initialize :set_default_currency_amounts, unless: Proc.new { |pp| pp.persisted? }
In my case, this is why the SQL was so long - my defaults required the loading of some associated models to get the default value for subtotal_cents
. This was the clue that helped me solve this.
Thank you to everyone for your help!
I think you are starting to realize that all ActiveRecord callbacks are evil. I'd aim to move theafter_initialize
to a factory which will help to create your record. Running 3 queries by callingModel.new
is a nasty side effect in my opinion.
– Marcin Kołodziej
Nov 12 at 17:36
You should be able to say justunless: :persisted?
or perhapsif: :new_record?
.
– mu is too short
Nov 12 at 18:49
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
OK, important Rails lesson learned today!
I recently added an after_initialize
callback to this model, which set the default values (including subtotal_cents
) for newly initialized records.
What I didn't realise is that this callback was re-initializing (ie overwriting in memory after load) existing records with the default values.
My fix was to change
after_initialize :set_default_currency_amounts
to
after_initialize :set_default_currency_amounts, unless: Proc.new { |pp| pp.persisted? }
In my case, this is why the SQL was so long - my defaults required the loading of some associated models to get the default value for subtotal_cents
. This was the clue that helped me solve this.
Thank you to everyone for your help!
I think you are starting to realize that all ActiveRecord callbacks are evil. I'd aim to move theafter_initialize
to a factory which will help to create your record. Running 3 queries by callingModel.new
is a nasty side effect in my opinion.
– Marcin Kołodziej
Nov 12 at 17:36
You should be able to say justunless: :persisted?
or perhapsif: :new_record?
.
– mu is too short
Nov 12 at 18:49
add a comment |
up vote
2
down vote
accepted
OK, important Rails lesson learned today!
I recently added an after_initialize
callback to this model, which set the default values (including subtotal_cents
) for newly initialized records.
What I didn't realise is that this callback was re-initializing (ie overwriting in memory after load) existing records with the default values.
My fix was to change
after_initialize :set_default_currency_amounts
to
after_initialize :set_default_currency_amounts, unless: Proc.new { |pp| pp.persisted? }
In my case, this is why the SQL was so long - my defaults required the loading of some associated models to get the default value for subtotal_cents
. This was the clue that helped me solve this.
Thank you to everyone for your help!
I think you are starting to realize that all ActiveRecord callbacks are evil. I'd aim to move theafter_initialize
to a factory which will help to create your record. Running 3 queries by callingModel.new
is a nasty side effect in my opinion.
– Marcin Kołodziej
Nov 12 at 17:36
You should be able to say justunless: :persisted?
or perhapsif: :new_record?
.
– mu is too short
Nov 12 at 18:49
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
OK, important Rails lesson learned today!
I recently added an after_initialize
callback to this model, which set the default values (including subtotal_cents
) for newly initialized records.
What I didn't realise is that this callback was re-initializing (ie overwriting in memory after load) existing records with the default values.
My fix was to change
after_initialize :set_default_currency_amounts
to
after_initialize :set_default_currency_amounts, unless: Proc.new { |pp| pp.persisted? }
In my case, this is why the SQL was so long - my defaults required the loading of some associated models to get the default value for subtotal_cents
. This was the clue that helped me solve this.
Thank you to everyone for your help!
OK, important Rails lesson learned today!
I recently added an after_initialize
callback to this model, which set the default values (including subtotal_cents
) for newly initialized records.
What I didn't realise is that this callback was re-initializing (ie overwriting in memory after load) existing records with the default values.
My fix was to change
after_initialize :set_default_currency_amounts
to
after_initialize :set_default_currency_amounts, unless: Proc.new { |pp| pp.persisted? }
In my case, this is why the SQL was so long - my defaults required the loading of some associated models to get the default value for subtotal_cents
. This was the clue that helped me solve this.
Thank you to everyone for your help!
answered Nov 12 at 17:29
Greg Matthew Crossley
323314
323314
I think you are starting to realize that all ActiveRecord callbacks are evil. I'd aim to move theafter_initialize
to a factory which will help to create your record. Running 3 queries by callingModel.new
is a nasty side effect in my opinion.
– Marcin Kołodziej
Nov 12 at 17:36
You should be able to say justunless: :persisted?
or perhapsif: :new_record?
.
– mu is too short
Nov 12 at 18:49
add a comment |
I think you are starting to realize that all ActiveRecord callbacks are evil. I'd aim to move theafter_initialize
to a factory which will help to create your record. Running 3 queries by callingModel.new
is a nasty side effect in my opinion.
– Marcin Kołodziej
Nov 12 at 17:36
You should be able to say justunless: :persisted?
or perhapsif: :new_record?
.
– mu is too short
Nov 12 at 18:49
I think you are starting to realize that all ActiveRecord callbacks are evil. I'd aim to move the
after_initialize
to a factory which will help to create your record. Running 3 queries by calling Model.new
is a nasty side effect in my opinion.– Marcin Kołodziej
Nov 12 at 17:36
I think you are starting to realize that all ActiveRecord callbacks are evil. I'd aim to move the
after_initialize
to a factory which will help to create your record. Running 3 queries by calling Model.new
is a nasty side effect in my opinion.– Marcin Kołodziej
Nov 12 at 17:36
You should be able to say just
unless: :persisted?
or perhaps if: :new_record?
.– mu is too short
Nov 12 at 18:49
You should be able to say just
unless: :persisted?
or perhaps if: :new_record?
.– mu is too short
Nov 12 at 18:49
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53266528%2frails-activerecord-pluck-and-map-return-two-different-values-why%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
It should be the same. Try restarting your rails console.
– EvanG
Nov 12 at 16:50
@EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
– Greg Matthew Crossley
Nov 12 at 16:51
Did you override your
subtotal_cents
in your model?– Marcin Kołodziej
Nov 12 at 16:54
@MarcinKołodziej I have two other
subtotal_cents
methods in parent models, but not in the model I am querying.– Greg Matthew Crossley
Nov 12 at 16:59