2014-07-07 170 views
4

看來像rails仍然不支持這種類型的關係,並引發ActiveRecord :: HasManyThroughAssociationPolymorphicThroughError錯誤。ActiveRecord has_many通過多態has_many

我能做些什麼來實現這種關係?

我有以下關聯:

Users 1..n Articles 
Categories n..n Articles 
Projects 1..n Articles 

這裏是訂閱模式

Subscription 1..1 User 
Subscription 1..1 Target (polymorphic (Article, Category or User)) 

我需要根據用戶訂閱#選擇通過認購##目標文章的文章。

我不知道燙到理想的情況下實現這個

我希望得到協會類的實例

更新1

下面是小例子

咱們說USER_1有4個訂閱記錄:

s1 = (user_id: 1, target_id: 3, target_type: 'User') 
s2 = (user_id: 1, target_id: 2, target_type: 'Category') 
s3 = (user_id: 1, target_id: 3, target_type: 'Project') 
s4 = (user_id: 1, target_id: 8, target_type: 'Project') 

我需要方法User#feed_articles,它提取所有屬於我訂閱的任何目標的文章。

user_1.feed_articles.order(created_at: :desc).limit(10) 

更新2

我通過鍵入用戶模型分開文章來源:

has_many :out_subscriptions, class_name: 'Subscription' 

    has_many :followes_users, through: :out_subscriptions, source: :target, source_type: 'User' 
    has_many :followes_categories, through: :out_subscriptions, source: :target, source_type: 'Category' 
    has_many :followes_projects, through: :out_subscriptions, source: :target, source_type: 'Project' 

    has_many :feed_user_articles, class_name: 'Article', through: :followes_users, source: :articles 
    has_many :feed_category_articles, class_name: 'Article', through: :followes_categories, source: :articles 
    has_many :feed_project_articles, class_name: 'Article', through: :followes_projects, source: :articles 

但我怎麼可以合併feed_category_articles和feed_project_articles feed_user_articles沒有性能比較的損失

更新3.1

我發現的唯一方法是使用原始SQL連接查詢。看起來它工作正常,但我不確定。

def feed_articles 
    join_clause = <<JOIN 
inner join users on articles.user_id = users.id 
inner join articles_categories on articles_categories.article_id = articles.id 
inner join categories on categories.id = articles_categories.category_id 
inner join subscriptions on 
    (subscriptions.target_id = users.id and subscriptions.target_type = 'User') or 
    (subscriptions.target_id = categories.id and subscriptions.target_type = 'Category') 
JOIN 

    Article.joins(join_clause).where('subscriptions.user_id' => id).distinct 
    end 

(這僅僅是對用戶和類別)

它支持範圍等特點。唯一令我感興趣的是:這個查詢是否會導致一些不良影響?

+0

所以,你基本上想要一個給定的用戶訂閱的所有文章? – nicooga

+0

是的,就是這樣。 – atomAltera

+0

沒有標準的解決方案,只需使用ActiveRecord dsl。我的解決方案將以與您的關係相同的方式工作,請參閱第二次編輯。 – nicooga

回答

0

我認爲從數據庫性能來看,使用UNION ALL多查詢將會比使用多態多連接更高效。它也會更具可讀性。我試圖編寫一個Arel查詢作爲示例,但它不能很好地發揮作用(我沒有正確地通過子句進行排序),所以我認爲你必須通過原始SQL來進行。您可以使用ORDER BY子句以外的SQL模板來乾燥它。

+0

關於order by子句,你是否把它放在union的末尾?例如對於工會的每個部分而言不是一個訂單。這是我上次寫聯合sql語句時絆倒了我。 (nb:我上次寫的是在oracle中的SQL,我不知道postgresql或mysql中的行爲是否不同) –

+0

@OleHenrikSkogstrømyep。根據SQL標準,ORDER BY子句必須放在所有聯合之後。但阿雷爾不能這樣做。我建議分割SQL和ORDER BY子句,以便可以使用不同順序的一個SQL。 –

0

你是正確的Rails不支持has_many:通過w /多態關聯。你可以通過在你的User類上定義一個實例方法來模仿這種行爲。這看起來像這樣:

def articles 
    Article. 
    joins("join subscriptions on subscriptions.target_id = articles.id and subscriptions.target_type = 'Article'"). 
    joins("join users on users.id = subscriptions.user_id") 
end