Given the following functional snippet I'm having trouble reducing the database queries:
class User < ApplicationRecord
belongs_to :account
def self.do_something
self.find_each do |user|
puts "#{self.new.account.name}:#{user.name} did something"
end
end
end
class Account < ApplicationRecord
has_many :users
end
a = Account.first
puts 'starting'
a.users.do_something
Account Load (0.4ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
starting
Account Load (0.3ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Test:User did something
Account Load (0.3ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Test:User did something
Account Load (0.3ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Test:User did something
Account Load (0.3ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Test:User did something
You can see that the Account model is being fetched from the database per user!
I was hoping to use something like self.account in the Singleton method to reference the original account, but the relationship obviously doesn't exist by default which is why I'm currently using self.new.account.
Is there anywhere else I can fetch the original Account model saved in a from inside self.do_something? I can obviously pass the account in a parameter, but that seems tedious especially if I may add arguments later...
Inside your
find_eachloop, you should be able to useuser.account.Outside that loop, I don't believe there's a documented / supported / won't-disappear-without-warning way to find the object. Depending on your Rails version, something like
self.current_scope.proxy_association.ownermight give you the answer you need... but do preferuser.accountif at all possible: the more you use private APIs, the harder future upgrades can be.Alternatively, consider using association extensions to define your
do_somethingmethod inside thehas_manyassociation only -- if it's not suited to be called asUser.do_somethingorUser.where(name: "Bob").do_something(because those don't have an associatedaccount), maybe it shouldn't be a top-level method after all.