Skip to content
New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any assocation with an extension block raises the deprecation warning about instance-dependence #18467

Closed
jaroslawr opened this issue Jan 12, 2015 · 2 comments
Milestone

Comments

@jaroslawr
Copy link
Contributor

With an association defined like this:

class Parent < ActiveRecord::Base
  has_many :children, ->() { order('id DESC') }, dependent: :destroy do
    def xyzyyx
       ...
    end
    ...
  end
end

and a query like this:

Parent.includes(:children).to_a

you get the deprecation warning about instance-depedence:

DEPRECATION WARNING: The association scope 'children' is instance dependent (the scope block takes an argument). Preloading happens before the individual instances are created. This means that there is no instance being passed to the association scope. This will most likely result in broken or incorrect behavior. Joining, Preloading and eager loading of these associations is deprecated and will be removed in the future. (called from test_preloading_of_associations at preloading_test.rb:25)

which does not seem to be sensible in this case.

Runnable test case:

gem 'activerecord', '4.2.0'
require 'active_record'
require 'minitest/autorun'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.default_timezone = :local

ActiveRecord::Schema.define do
  create_table(:parents)
  create_table(:children) { |t| t.integer :parent_id }
end

class Parent < ActiveRecord::Base
  has_many :children, ->() { order('id DESC') }, dependent: :destroy do
  end
end

class Child < ActiveRecord::Base
end

class Bug < Minitest::Test
  def test_preloading_of_associations
    Parent.create!
    Parent.create!
    Parent.includes(:children).to_a
  end
end

The culprit seems to be in CollectionAssociation in ActiveRecord::Associations::Builder, the initialize method says:

def initialize(model, name, scope, options)
  super
  @mod = nil
  if block_given?
    @mod = Module.new(&Proc.new)
    @scope = wrap_scope @scope, @mod
  end
end

And wrap_scope is:

def wrap_scope(scope, mod)
  if scope
    proc { |owner| instance_exec(owner, &scope).extending(mod) }
  else
    proc { extending(mod) }
  end
end

With this you end up with scope.arity > 0 even though there is no user-given scope (or the user-given scope actually is of arity 0).

@senny what do you think about this?

@senny
Copy link
Member

senny commented Jan 13, 2015

@jaroslawr thank you for reporting, I'll take a look.

@senny senny added this to the 4.2.1 milestone Jan 13, 2015
@senny
Copy link
Member

senny commented Jan 18, 2015

@jaroslawr I just pushed a patch to the 4-2-stable branch. Would be great to hear wether this solves your issue.

Will be released with the next patch version of 4.2..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants