Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

first_or_create is applying scope to callbacks. #7391

Closed
beyond opened this Issue Aug 19, 2012 · 6 comments

Comments

Projects
None yet
6 participants
Contributor

beyond commented Aug 19, 2012

rails 3.2.8 / ActiveRecord 3.2.8
first_or_create method is applying given conditions by where to xxx_all methods in model's callbacks. It may be bug?

example:

class Comment < ActiveRecord::Base
  attr_accessible :enabled, :title
  before_save :diabled_old
  def diabled_old
    self.class.update_all enabled: false
  end
end

> Comment.where( title: "x" ).first_or_create
SQL (0.1ms)  UPDATE "comments" SET "enabled" = 'f' WHERE "comments"."title" = 'x'
SQL (0.2ms)  INSERT INTO "comments" ...

> Comment.where( title: "x2" ).first_or_initialize.save
SQL (0.1ms)  UPDATE "comments" SET "enabled" = 'f'
SQL (0.2ms)  INSERT INTO "comments" ...

> Comment.find_or_create_by_title "x3"
SQL (0.1ms)  UPDATE "comments" SET "enabled" = 'f'
SQL (0.2ms)  INSERT INTO "comments" ...

Did it change from older versions? If so, how was it working before? And can you try to bundle from 3-2-stable and check it again? Thanks.

Contributor

beyond commented Aug 19, 2012

The same problem occurred on 3-2-stable branch and version 3.2.1 (first_or_create is implemented from 3.2.0).

Contributor

al2o3cr commented Aug 21, 2012

This is a side-effect of the way that create is implemented on Relation:

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L119

Any code inside the scoping block will pick up the where conditions.

If you really want to hit all records reliably (which it looks like you do), self.class.unscoped.update_all will ensure there are no additional conditions applied.

Contributor

jroes commented Oct 11, 2012

Yeah, I find this behavior a bit odd as well. It essentially means I have to use a workaround like this:

Taxon.where(name: row[1], parent_id: parent.id).first_or_initialize.save

To save the record without applying the where conditions.

Seems to me that #first_or_initialize and #first_or_create should behave in exactly opposite ways, but that would necessitate a breaking change -- forcing the user to actually supply the original conditions in their #first_or_create call. Might be better for clarity though.

Member

senny commented Nov 4, 2012

I think this is a duplication of #7853, which was closed. You can see the relevant commit here eb72e62

Member

steveklabnik commented Nov 4, 2012

Yep.

@guigs guigs added a commit to guigs/rails that referenced this issue May 4, 2016

@guigs guigs Fix `ActiveRecord::Relation#create` and `#create!` scope leaking to
callbacks

Fixes #7391, #7853, #9894, #12305, #18952.
4189c65
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment