Rails ActiveRecord :pluck and :map return two different values - why?












0














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?










share|improve this question
























  • It should be the same. Try restarting your rails console.
    – EvanG
    Nov 12 '18 at 16:50










  • @EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
    – Greg Matthew Crossley
    Nov 12 '18 at 16:51










  • Did you override your subtotal_cents in your model?
    – Marcin Kołodziej
    Nov 12 '18 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 '18 at 16:59
















0














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?










share|improve this question
























  • It should be the same. Try restarting your rails console.
    – EvanG
    Nov 12 '18 at 16:50










  • @EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
    – Greg Matthew Crossley
    Nov 12 '18 at 16:51










  • Did you override your subtotal_cents in your model?
    – Marcin Kołodziej
    Nov 12 '18 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 '18 at 16:59














0












0








0







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?










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 '18 at 17:05

























asked Nov 12 '18 at 16:41









Greg Matthew Crossley

340314




340314












  • It should be the same. Try restarting your rails console.
    – EvanG
    Nov 12 '18 at 16:50










  • @EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
    – Greg Matthew Crossley
    Nov 12 '18 at 16:51










  • Did you override your subtotal_cents in your model?
    – Marcin Kołodziej
    Nov 12 '18 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 '18 at 16:59


















  • It should be the same. Try restarting your rails console.
    – EvanG
    Nov 12 '18 at 16:50










  • @EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
    – Greg Matthew Crossley
    Nov 12 '18 at 16:51










  • Did you override your subtotal_cents in your model?
    – Marcin Kołodziej
    Nov 12 '18 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 '18 at 16:59
















It should be the same. Try restarting your rails console.
– EvanG
Nov 12 '18 at 16:50




It should be the same. Try restarting your rails console.
– EvanG
Nov 12 '18 at 16:50












@EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
– Greg Matthew Crossley
Nov 12 '18 at 16:51




@EvanG - yes, I thought of that too. Sadly restarting the console changes nothing!
– Greg Matthew Crossley
Nov 12 '18 at 16:51












Did you override your subtotal_cents in your model?
– Marcin Kołodziej
Nov 12 '18 at 16:54






Did you override your subtotal_cents in your model?
– Marcin Kołodziej
Nov 12 '18 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 '18 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 '18 at 16:59












1 Answer
1






active

oldest

votes


















2














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!






share|improve this answer





















  • 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 '18 at 17:36










  • You should be able to say just unless: :persisted? or perhaps if: :new_record?.
    – mu is too short
    Nov 12 '18 at 18:49











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















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

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














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!






share|improve this answer





















  • 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 '18 at 17:36










  • You should be able to say just unless: :persisted? or perhaps if: :new_record?.
    – mu is too short
    Nov 12 '18 at 18:49
















2














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!






share|improve this answer





















  • 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 '18 at 17:36










  • You should be able to say just unless: :persisted? or perhaps if: :new_record?.
    – mu is too short
    Nov 12 '18 at 18:49














2












2








2






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!






share|improve this answer












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!







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 12 '18 at 17:29









Greg Matthew Crossley

340314




340314












  • 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 '18 at 17:36










  • You should be able to say just unless: :persisted? or perhaps if: :new_record?.
    – mu is too short
    Nov 12 '18 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 '18 at 17:36










  • You should be able to say just unless: :persisted? or perhaps if: :new_record?.
    – mu is too short
    Nov 12 '18 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 '18 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 '18 at 17:36












You should be able to say just unless: :persisted? or perhaps if: :new_record?.
– mu is too short
Nov 12 '18 at 18:49




You should be able to say just unless: :persisted? or perhaps if: :new_record?.
– mu is too short
Nov 12 '18 at 18:49


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Florida Star v. B. J. F.

Danny Elfman

Lugert, Oklahoma