active_record_upsert icon indicating copy to clipboard operation
active_record_upsert copied to clipboard

Upsert nil in place of current value

Open bvallier opened this issue 6 years ago • 10 comments

I'm running an upsert that replaces the current value (e.g. a non-nil value) with a nil, but the nil fails to get upserted. Upserts of any other value seems to work. Is this unexpected behavior? Am I missing something?

bvallier avatar Nov 28 '18 01:11 bvallier

I’d say it’s probably a bug. I’ll investigate.

28 nov. 2018 kl. 03:39 skrev Brice Vallieres [email protected]:

I'm running an upsert that replaces the current value (e.g. a non-nil value) with a nil, but the nil fails to get upserted. Upserts of any other value seems to work. Is this unexpected behavior? Am I missing something?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

jesjos avatar Nov 28 '18 05:11 jesjos

😱 @jesjos Please let us know your findings.

abinoda avatar Nov 28 '18 08:11 abinoda

@bvallier @jesjos Just checking on this... is it an actual issue?

abinoda avatar Dec 03 '18 19:12 abinoda

@bvallier I'm having trouble reproducing this, can you write a failing test?

jesjos avatar Dec 13 '18 18:12 jesjos

` describe 'upsert_nil' do

it 'returns false if nil fails to get upserted' do
        s = Student.find_or_initialize_by(unique_id: '1234567', first_name: 'Brice')
	s.upsert!

	#now try and change it to nil
	s2 = Student.find_or_initialize_by(unique_id: '1234567', first_name: nil)
	#s2 = Student.find_or_initialize_by(unique_id: '1234567', first_name: 'John')
	s2.upsert!

	first_name = Student.where(:unique_id => '1234567').pluck(:first_name)[0]

	expect(first_name).to be_nil
	#expect(first_name).to     eq('John')
end

end `

You can uncomment the scenario where "John" is upserted and that test will pass, but upsert of nil doesn't work for me...

bvallier avatar Dec 14 '18 22:12 bvallier

I am getting hit by this as well. Any progress? Thanks!

zdrummond avatar Jan 16 '19 23:01 zdrummond

@zdrummond @bvallier Does this only happen when you use find_or_initialize_by?

abinoda avatar Jan 17 '19 00:01 abinoda

I am doing a new passing in the latest data. Note: using Postgres

[15] pry(main)> updated_ss = StoryState.new latest_story_state
=> #<StoryState:0x007fce1fe1d580 id: 10, estimate: nil, story_id: 4194, iteration_id: ****, created_at: nil, updated_at: nil, owners: ["****"], workflow_state_id: ****, date_of_state: nil>
[16] pry(main)> updated_ss.upsert
   (0.2ms)  BEGIN
  Story Load (0.2ms)  SELECT  "stories".* FROM "stories" WHERE "stories"."id" = $1 LIMIT $2  [["id", 4194], ["LIMIT", 1]]
  StoryState Upsert (0.4ms)  INSERT INTO "story_states" ("id", "estimate", "story_id", "iteration_id", "created_at", "updated_at", "owners", "workflow_state_id", "date_of_state") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT  ("id")  DO UPDATE  SET "story_id" = $10, "iteration_id" = $11, "updated_at" = $12, "owners" = $13, "workflow_state_id" = $14 RETURNING *, (xmax = 0) AS _upsert_created_record  [["id", 10], ["estimate", nil], ["story_id", 4194], ["iteration_id", ****], ["created_at", "2019-01-17 00:24:38.664396"], ["updated_at", "2019-01-17 00:24:38.664396"], ["owners", "{****}"], ["workflow_state_id", ****], ["date_of_state", nil], ["story_id", 4194], ["iteration_id", ****], ["updated_at", "2019-01-17 00:24:38.664396"], ["owners", "{****}"], ["workflow_state_id", ****]]
  PaperTrail::Version Create (43.5ms)  INSERT INTO "versions" ("item_type", "item_id", "event", "created_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["item_type", "StoryState"], ["item_id", 10], ["event", "create"], ["created_at", "2019-01-17 00:24:38.664396"]]
   (0.6ms)  COMMIT
=> #<StoryState:0x007fce1fe1d580 id: 10, estimate: 11, story_id: ****, iteration_id: ****, created_at: Wed, 16 Jan 2019 23:54:26 UTC +00:00, updated_at: Thu, 17 Jan 2019 00:24:38 UTC +00:00, owners: ["****"], workflow_state_id: ****, date_of_state: Wed, 16 Jan 2019>
[17] pry(main)> updated_ss
=> #<StoryState:0x007fce1fe1d580 id: 10, estimate: 11, story_id: ****, iteration_id: ****, created_at: Wed, 16 Jan 2019 23:54:26 UTC +00:00, updated_at: Thu, 17 Jan 2019 00:24:38 UTC +00:00, owners: ["****"], workflow_state_id: ****, date_of_state: Wed, 16 Jan 2019>

Note the estimate in the updated starts off as nil then reverts back to 11 Note2: I hand blanked some of the data with **** just to hide the private ids, but none of that data was to be updated

zdrummond avatar Jan 17 '19 00:01 zdrummond

This spec should demonstrate that setting stuff to nil is possible on some level: https://github.com/jesjos/active_record_upsert/blob/master/spec/active_record/base_spec.rb#L66

I think maybe something more subtle is going on. Still investigating.

jesjos avatar Jan 20 '19 14:01 jesjos

Oh, I'm sorry. That test runs green b/c it uses attributes: [:id, :name].

jesjos avatar Jan 20 '19 15:01 jesjos