我遇到了正确设置模型关系的问题。我有以下课程:
personal_portfolio.rb
class PersonalPortfolio < Portfolio
has_many :user_stake_in_portfolios, :foreign_key => :possession_id
belongs_to :owner, :class_name => 'User'
has_many :managers, :through => :user_stake_in_portfolios, :source => :user
has_many :company_permissions, :foreign_key => :owner_id
has_many :company_permissions_as_viewer, :class_name => 'CompanyPermission', :foreign_key => :owner_id, :conditions => 'can_view_info = true || can_edit_cap_table = true || can_view_key_metric = true || can_view_all_metrics = true || can_view_cap_table = true || can_edit_managers = true || can_edit_info = true || can_edit_metrics = true'
has_many :companies_as_viewer, :class_name => 'Company', :through => :company_permissions_as_viewer, :source => :entity
has_many :company_permissions_as_manager, :class_name => 'CompanyPermission', :foreign_key => :owner_id, :conditions => { :can_edit_managers => true }
has_many :companies_as_manager, :class_name => 'Company', :through => :company_permissions_as_manager, :source => :entity
has_many :portfolio_permissions, :foreign_key => :owner_id
has_many :portfolio_permissions_as_viewer, :class_name => 'PortfolioPermission', :foreign_key => :owner_id, :conditions => 'can_view_info = true || can_edit_cap_table = true || can_view_key_metric = true || can_view_all_metrics = true || can_view_cap_table = true || can_edit_managers = true || can_edit_info = true || can_edit_metrics = true'
has_many :portfolios_as_viewer, :class_name => 'Portfolio', :through => :portfolio_permissions_as_viewer, :source => :entity
has_many :portfolio_permissions_as_manager, :class_name => 'PortfolioPermission', :foreign_key => :owner_id, :conditions => { :can_edit_managers => true }
has_many :portfolios_as_manager, :class_name => 'GroupPortfolio', :through => :portfolio_permissions_as_manager, :source => :entity
after_create :add_manager
...
end
user.rb
class User < ActiveRecord::Base
...
has_many :user_stake_in_portfolios, foreign_key: :owner_id
has_many :portfolios, through: :user_stake_in_portfolios
has_many :personal_portfolios, through: :user_stake_in_portfolios, :class_name => 'PersonalPortfolio', :source => :portfolio, :conditions => { :type => 'PersonalPortfolio' }
has_many :companies, through: :portfolios, source: :portfolio_companies, class_name: 'Company'
has_many :managed_portfolios, :through => :personal_portfolios, :source => :portfolios_as_manager
has_many :viewable_portfolios, :through => :personal_portfolios, :source => :portfolios_as_viewer
has_many :managed_companies, :through => :personal_portfolios, :source => :companies_as_manager
has_many :viewable_companies, :through => :personal_portfolios, :source => :companies_as_viewer
...
end
奇怪的是,如果我运行命令User.find(3).personal_portfolios.first.portfolios_as_viewer
,我会得到我期望的结果(3个投资组合)。但问题是当我尝试User.find(3).viewable_portfolios
时,我只得到1个投资组合(三个投资组合中的一个)。用户viewable_portfolios
是使用has_many :through
作为来源的PersonalPortfolio.portfolios_as_viewer
。
查看第二个命令生成的查询时,您可以看到它正在使用portfolios
表两次:
SELECT `portfolios`.*
FROM `portfolios`
INNER JOIN `permissions`
ON `portfolios`.`id` = `permissions`.`entity_id`
INNER JOIN `portfolios` `personal_portfolios_viewable_portfolios_join`
ON `permissions`.`owner_id` =
`personal_portfolios_viewable_portfolios_join`.`id`
INNER JOIN `stakes`
ON `personal_portfolios_viewable_portfolios_join`.`id` =
`stakes`.`possession_id`
WHERE `permissions`.`type` IN ( 'PortfolioPermission' )
AND `portfolios`.`type` IN ( 'PersonalPortfolio' )
AND `stakes`.`type` IN ( 'UserStakeInPortfolio' )
AND `stakes`.`owner_id` = 3
AND ( can_view_info = true
|| can_edit_cap_table = true
|| can_view_key_metric = true
|| can_view_all_metrics = true
|| can_view_cap_table = true
|| can_edit_managers = true
|| can_edit_info = true
|| can_edit_metrics = true )
AND ( `personal_portfolios_viewable_portfolios_join`.`type` = 'PersonalPortfolio' )
这对我来说很奇怪,因为User.find(3).managed_portfolios == User.find(3).personal_portfolios.first.portfolios_as_manager
返回true而User.find(3).viewable_portfolios == User.find(3).personal_portfolios.first.portfolios_as_viewer
返回false。虽然关系看起来是一样的,但公司工作得很好(虽然没有表明正确的关系,因为依赖关系/数据不同)。
问题
如何User.find(3).viewable_portfolios
返回与User.find(3).personal_portfolios.first.portfolios_as_viewer
相同的内容?
有用的输出
1.9.3-p362 :122 > User.find(3).viewable_portfolios
User Load (0.8ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
Portfolio Load (1.1ms) SELECT `portfolios`.* FROM `portfolios` INNER JOIN `permissions` ON `portfolios`.`id` = `permissions`.`entity_id` INNER JOIN `portfolios` `personal_portfolios_viewable_portfolios_join` ON `permissions`.`owner_id` = `personal_portfolios_viewable_portfolios_join`.`id` INNER JOIN `stakes` ON `personal_portfolios_viewable_portfolios_join`.`id` = `stakes`.`possession_id` WHERE `permissions`.`type` IN ('PortfolioPermission') AND `portfolios`.`type` IN ('PersonalPortfolio') AND `stakes`.`type` IN ('UserStakeInPortfolio') AND `stakes`.`owner_id` = 3 AND (can_view_info = true || can_edit_cap_table = true || can_view_key_metric = true || can_view_all_metrics = true || can_view_cap_table = true || can_edit_managers = true || can_edit_info = true || can_edit_metrics = true) AND (`personal_portfolios_viewable_portfolios_join`.`type` = 'PersonalPortfolio')
=> [#<PersonalPortfolio id: 3, name: "Manager Man's portfolio", established: "2013-09-24", created_at: "2013-09-24 23:20:34", updated_at: "2013-09-24 23:20:34", type: "PersonalPortfolio", base_capital_invested: nil, total_shares: nil, logo_file_name: nil, logo_content_type: nil, logo_file_size: nil, logo_updated_at: nil, city: nil, state: nil, invited_manager_email: nil, claim_code: nil, angellist_url: nil, facebook_url: nil, linkedin_url: nil, twitter_url: nil, website_url: nil, longitude: nil, latitude: nil, is_single_use_fund: false, tagline: nil, thumb_file_name: nil, thumb_content_type: nil, thumb_file_size: nil, thumb_updated_at: nil, use_committed_capital: true, owner_id: 3>]
1.9.3-p362 :123 > User.find(3).viewable_portfolios.count
User Load (0.9ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
(2.2ms) SELECT COUNT(*) FROM `portfolios` INNER JOIN `permissions` ON `portfolios`.`id` = `permissions`.`entity_id` INNER JOIN `portfolios` `personal_portfolios_viewable_portfolios_join` ON `permissions`.`owner_id` = `personal_portfolios_viewable_portfolios_join`.`id` INNER JOIN `stakes` ON `personal_portfolios_viewable_portfolios_join`.`id` = `stakes`.`possession_id` WHERE `permissions`.`type` IN ('PortfolioPermission') AND `portfolios`.`type` IN ('PersonalPortfolio') AND `stakes`.`type` IN ('UserStakeInPortfolio') AND `stakes`.`owner_id` = 3 AND (can_view_info = true || can_edit_cap_table = true || can_view_key_metric = true || can_view_all_metrics = true || can_view_cap_table = true || can_edit_managers = true || can_edit_info = true || can_edit_metrics = true) AND (`personal_portfolios_viewable_portfolios_join`.`type` = 'PersonalPortfolio')
=> 1
1.9.3-p362 :124 > User.find(3).personal_portfolios.first.portfolios_as_viewer
User Load (0.9ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
PersonalPortfolio Load (0.8ms) SELECT `portfolios`.* FROM `portfolios` INNER JOIN `stakes` ON `portfolios`.`id` = `stakes`.`possession_id` WHERE `stakes`.`type` IN ('UserStakeInPortfolio') AND `portfolios`.`type` IN ('PersonalPortfolio') AND `stakes`.`owner_id` = 3 AND (`portfolios`.`type` = 'PersonalPortfolio') LIMIT 1
Portfolio Load (1.0ms) SELECT `portfolios`.* FROM `portfolios` INNER JOIN `permissions` ON `portfolios`.`id` = `permissions`.`entity_id` WHERE `permissions`.`type` IN ('PortfolioPermission') AND `permissions`.`owner_id` = 3 AND (can_view_info = true || can_edit_cap_table = true || can_view_key_metric = true || can_view_all_metrics = true || can_view_cap_table = true || can_edit_managers = true || can_edit_info = true || can_edit_metrics = true)
=> [#<PersonalPortfolio id: 3, name: "Manager Man's portfolio", established: "2013-09-24", created_at: "2013-09-24 23:20:34", updated_at: "2013-09-24 23:20:34", type: "PersonalPortfolio", base_capital_invested: nil, total_shares: nil, logo_file_name: nil, logo_content_type: nil, logo_file_size: nil, logo_updated_at: nil, city: nil, state: nil, invited_manager_email: nil, claim_code: nil, angellist_url: nil, facebook_url: nil, linkedin_url: nil, twitter_url: nil, website_url: nil, longitude: nil, latitude: nil, is_single_use_fund: false, tagline: nil, thumb_file_name: nil, thumb_content_type: nil, thumb_file_size: nil, thumb_updated_at: nil, use_committed_capital: true, owner_id: 3>, #<GroupPortfolio id: 5, name: "New Fund, LLC", established: "2009-01-01", created_at: "2013-09-24 23:20:36", updated_at: "2013-09-24 23:20:36", type: "GroupPortfolio", base_capital_invested: 2000000, total_shares: 1000000, logo_file_name: nil, logo_content_type: nil, logo_file_size: nil, logo_updated_at: nil, city: "Hamlin", state: "WV", invited_manager_email: nil, claim_code: nil, angellist_url: nil, facebook_url: nil, linkedin_url: nil, twitter_url: nil, website_url: nil, longitude: -82.1029, latitude: 38.2787, is_single_use_fund: false, tagline: nil, thumb_file_name: nil, thumb_content_type: nil, thumb_file_size: nil, thumb_updated_at: nil, use_committed_capital: false, owner_id: nil>, #<GroupPortfolio id: 6, name: "SB, LLC", established: "2009-01-01", created_at: "2013-09-24 23:20:36", updated_at: "2013-09-24 23:20:36", type: "GroupPortfolio", base_capital_invested: 2000000, total_shares: 2000000, logo_file_name: nil, logo_content_type: nil, logo_file_size: nil, logo_updated_at: nil, city: "Bloomington", state: "IN", invited_manager_email: nil, claim_code: nil, angellist_url: nil, facebook_url: nil, linkedin_url: nil, twitter_url: nil, website_url: nil, longitude: -86.5264, latitude: 39.1653, is_single_use_fund: false, tagline: nil, thumb_file_name: nil, thumb_content_type: nil, thumb_file_size: nil, thumb_updated_at: nil, use_committed_capital: true, owner_id: nil>]
1.9.3-p362 :125 > User.find(3).personal_portfolios.first.portfolios_as_viewer.count
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
PersonalPortfolio Load (0.5ms) SELECT `portfolios`.* FROM `portfolios` INNER JOIN `stakes` ON `portfolios`.`id` = `stakes`.`possession_id` WHERE `stakes`.`type` IN ('UserStakeInPortfolio') AND `portfolios`.`type` IN ('PersonalPortfolio') AND `stakes`.`owner_id` = 3 AND (`portfolios`.`type` = 'PersonalPortfolio') LIMIT 1
(0.7ms) SELECT COUNT(*) FROM `portfolios` INNER JOIN `permissions` ON `portfolios`.`id` = `permissions`.`entity_id` WHERE `permissions`.`type` IN ('PortfolioPermission') AND `permissions`.`owner_id` = 3 AND (can_view_info = true || can_edit_cap_table = true || can_view_key_metric = true || can_view_all_metrics = true || can_view_cap_table = true || can_edit_managers = true || can_edit_info = true || can_edit_metrics = true)
=> 3
1.9.3-p362 :126 > User.find(3).personal_portfolios
User Load (0.9ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
PersonalPortfolio Load (0.5ms) SELECT `portfolios`.* FROM `portfolios` INNER JOIN `stakes` ON `portfolios`.`id` = `stakes`.`possession_id` WHERE `stakes`.`type` IN ('UserStakeInPortfolio') AND `portfolios`.`type` IN ('PersonalPortfolio') AND `stakes`.`owner_id` = 3 AND (`portfolios`.`type` = 'PersonalPortfolio')
=> [#<PersonalPortfolio id: 3, name: "Manager Man's portfolio", established: "2013-09-24", created_at: "2013-09-24 23:20:34", updated_at: "2013-09-24 23:20:34", type: "PersonalPortfolio", base_capital_invested: nil, total_shares: nil, logo_file_name: nil, logo_content_type: nil, logo_file_size: nil, logo_updated_at: nil, city: nil, state: nil, invited_manager_email: nil, claim_code: nil, angellist_url: nil, facebook_url: nil, linkedin_url: nil, twitter_url: nil, website_url: nil, longitude: nil, latitude: nil, is_single_use_fund: false, tagline: nil, thumb_file_name: nil, thumb_content_type: nil, thumb_file_size: nil, thumb_updated_at: nil, use_committed_capital: true, owner_id: 3>]
1.9.3-p362 :127 > User.find(3).personal_portfolios.count
User Load (0.8ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
(0.4ms) SELECT COUNT(*) FROM `portfolios` INNER JOIN `stakes` ON `portfolios`.`id` = `stakes`.`possession_id` WHERE `stakes`.`type` IN ('UserStakeInPortfolio') AND `portfolios`.`type` IN ('PersonalPortfolio') AND `stakes`.`owner_id` = 3 AND (`portfolios`.`type` = 'PersonalPortfolio')
=> 1
另一种变化(插图/简洁
如果我将personal_portfolio.rb
中的定义更改为:
has_many :portfolio_permissions_as_viewer, :class_name => 'PortfolioPermission', :foreign_key => :owner_id, :conditions => { :can_view_info => true }
User.find(3).viewable_portfolios == User.find(3).personal_portfolios.first.portfolios_as_viewer
仍然返回false。但是User.find(3).viewable_portfolios
SELECT `portfolios`.*
FROM `portfolios`
INNER JOIN `permissions`
ON `portfolios`.`id` = `permissions`.`entity_id`
INNER JOIN `portfolios` `personal_portfolios_viewable_portfolios_join`
ON `permissions`.`owner_id` =
`personal_portfolios_viewable_portfolios_join`.`id`
INNER JOIN `stakes`
ON `personal_portfolios_viewable_portfolios_join`.`id` =
`stakes`.`possession_id`
WHERE `permissions`.`type` IN ( 'PortfolioPermission' )
AND `portfolios`.`type` IN ( 'PersonalPortfolio' )
AND `stakes`.`type` IN ( 'UserStakeInPortfolio' )
AND `stakes`.`owner_id` = 3
AND ( `permissions`.`can_view_info` = 1 )
AND ( `personal_portfolios_viewable_portfolios_join`.`type` =
'PersonalPortfolio' )
我认为问题在于portfolios
和personal_portfolios_viewable_portfolios_join
要求PersonalPortfolio
实际上portfolios
应该属于任何类型。这让我相信这是我建立关系的方式,但不是100%肯定。
需要更多? 如果您需要更多信息/代码,请与我们联系。我尽量不要过于多余,但可能没有给予足够的帮助。
答案 0 :(得分:0)
看起来您可能无法根据需要进行OR
比较。这可能是Rails中的一个错误,但很难说。
您可以在模型上创建一个方法(甚至更快,一个数据库列),为您的长串比较返回true
或false
,例如。
def has_permissions_as_viewer
can_view_info == true || can_edit_cap_table == true || can_view_key_metric == true || can_view_all_metrics == true || can_view_cap_table == true || can_edit_managers == true || can_edit_info == true || can_edit_metrics == true
end
然后只使用该方法而不是长条件
has_many :company_permissions_as_viewer, :class_name => 'CompanyPermission', :foreign_key => :owner_id, :conditions => :has_permission_as_viewer
在模型上设置过滤器可能是最快/最有效的,只要更改任何其他列(has_permission_as_viewer
,can_view_info
等,就会更新can_edit_cap_table
列)。这也有更简单的数据库操作的额外好处,并且(在我看来)会更容易阅读和理解正在发生的事情。
如果有意义,请告诉我!