我们通过以下方式获得了基本的 has_many:针对用户和公司。
class User < ActiveRecord::Base
extends CompanyMethods
has_many :company_users
has_many :companies, through: company_users
has_many :orders
end
class CompanyUser < ActiveRecord::Base
belongs_to :user
belongs_to :company
validates_uniqueness_of :company_id, scope: :user_id
end
class Company < ActiveRecord::Base
has_many :company_users
has_many :users, through: company_users
end
然后我们有这个CompanyMethods
库,它default_scope
向用户添加了一个:
module CompanyMethods
def self.extended(klass)
klass.class_eval do
default_scope do
c_ids = Authorization.current_company_ids
includes(:companies).where(companies: { id: c_ids })
end
end
end
end
因此,当我们调用时,我们User.find_by_email('michael@widgetworks.com')
只会返回范围为Authorization.current_company_ids
.
这是sql:
SELECT DISTINCT `users`.id FROM `users` LEFT OUTER JOIN `company_users` ON `company_users`.`user_id` = `users`.`id` LEFT OUTER JOIN `companies` ON `companies`.`id` = `company_users`.`company_id` WHERE `companies`.`id` IN (4) AND `users`.`email` = 'michael@widgetworks.com' LIMIT 1
在很多情况下,这一切都很好。但这就是它开始变得时髦的地方。
当另一个对象(例如 CreditCard)调用通过 User 的关联时,将companies.id
在子对象上调用范围。
class CreditCard < ActiveRecord::Base
has_one :user, through: :user_profile
has_many :orders, through: :user
end
class UserProfile < ActiveRecord::Base
belongs_to :user
end
这是它生成的sql:
SELECT `orders`.* FROM `orders` INNER JOIN `users` ON `orders`.`user_id` = `users`.`id` INNER JOIN `user_profiles` ON `users`.`id` = `user_profiles`.`user_id` WHERE `orders`.`company_id` IN (4) AND `companies`.`id` IN (4) AND `user_profiles`.`id` = 47717
credit_card.orders
抛出一个错误,因为它的 SQL 查询在它应该只调用它时调用“ companies
. id
IN (4)” on 。reservation
user
我已经能够通过破解而不是使用through
关联来解决问题,我只是编写了一个名为reservations
CreditCard 的方法。
class CreditCard < ActiveRecord::Base
has_one :user, through: :user_profile
def orders
user.orders
end
end
这几乎解决了问题,但它不是一个很好的解决方案。