1

モデルの関係を正しく設定する際に問題が発生しています。私は次のクラスを持っています:

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 つのポートフォリオ (3 つのうちの 1 つ) しか得られないことです。ユーザー。ソースとしてのviewable_portfolios使用has_many :throughです。PersonalPortfolio.portfolios_as_viewer

2 番目のコマンドによって生成されたクエリを見ると、portfoliosテーブルが 2 回使用されていることがわかります。

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_managerfalse を返しながら true を返すので、私には奇妙ですUser.find(3).viewable_portfolios == User.find(3).personal_portfolios.first.portfolios_as_viewer。そして、関係は同じように見えますが、企業は問題なく機能します (ただし、依存関係/データが異なるため、正しい関係を示しているわけではありません)。

質問 どうすれば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問題は、両方が必要であり、実際には whenpersonal_portfolios_viewable_portfolios_joinが任意のタイプである必要があることだと思います。これにより、私はそれが私がどのように関係を築いているかを信じるようになりますが、100%確実ではありません.PersonalPortfolioportfolios

もっといります? さらに情報/コードが必要な場合はお知らせください。余分なことをしすぎないようにしましたが、役に立つほど十分に与えられなかったかもしれません。

4

1 に答える 1

0

OR必要に応じて比較を行うことができないようです。これは Rails のバグかもしれませんが、わかりにくいです。

trueモデル (またはさらに高速な DB 列) で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_infocan_edit_cap_table更新するだけのフィルターをモデルに設定すると、おそらく最速/最も効率的です。これには、DB 操作が単純になるという追加の利点もあり、(私の意見では) 読みやすく、何が起こっているのかを理解するのが少し簡単になります。

それが理にかなっているかどうか教えてください!

于 2013-09-26T19:38:05.960 に答える