0

我正在使用Ruby on Rails 4.1,我想「合併」兩個has_many模型關聯的結果。也就是說,我有以下型號和協會:如何「合併」兩個`has_many`模型關聯的結果?

class Article < ActiveRecord::Base 
    has_many :assigned_comments 
    has_many :unassigned_comments 
end 

class AssignedComment < ActiveRecord::Base 
    belongs_to :article 
end 

class UnassignedComment < ActiveRecord::Base 
    belongs_to :article 
end 

我想爲了運行@article.comments並使其返回兩個數據的@article.assigned_comments@article.unassigned_comments實施「東西」。

我該如何做到這一點?有一些常見的做法?怎麼樣返回數據和數據庫查詢?

+0

我不認爲這是一種常見的做法。你可以用find_by_sql和UNION來做到這一點 –

+0

在我的情況下應該如何顯示'find_by_sql'和'UNION'語句?什麼是缺點? – Backo

+0

可以在任何活動記錄上調用'find_by_sql'(就像'find'),並且可以將任何SQL語句傳遞給它,例如'Article.find_by_sql(「從assigned_comments中選擇COUNT(*)」)。 UNION是一個標準的SQL事物(google瞭解更多)。缺點是它是非標準的軌道 - 它不會像一個普通的協會那樣以一組整齊的模型回來。 –

回答

0

has_many創建的訪問器返回一個ActiveRecord::Relation,它基本上只是SQL查詢的包裝器。

您可以輕鬆編寫一種方法將關係的所有結果組合到一個數組中。

def comments 
    self.assigned_comments.to_a + self.unassigned_comments.to_a 
end 

但是這有幾個缺點:

  1. 它總是加載並初始化所有assigned_commentsunassigned_comments到內存中。

  2. 它不會有任何的ActiveRecord::Relation的便利方法

根據UnassignedComment如何相似AssignedComment和的列,一個更好的解決方案可能是將它們組合成一個單一的表和子。

class Article < ActiveRecord::Base 
    has_many :comments 
    has_many :assigned_comments, -> { where(assigned: true) } 
    has_many :unassigned_comments, -> { where(assigned: false) } 
end 

class Comment < ActiveRecord::Base 
    belongs_to :article 

    # Common functionality 
end 

class AssignedComment < Comment 
    default_scope { where(assigned: true) } 
    before_save -> { self.assigned = true } 

    # Functionality specific to AssignedComment 
end 

class UnassignedComment < Comment 
    default_scope { where(assigned: false) } 
    before_save -> { self.assigned = false } 

    # Functionality specific to UnassignedComment 
end 
+0

在過去,我試圖繼承,但它是一個錯... – Backo

0

我知道這可能不是您的問題的答案。這是針對您的案例的性病簡介。

處理共享大部分相同功能和數據字段的模型類時,應考慮單表繼承。

http://eewang.github.io/blog/2013/03/12/how-and-when-to-use-single-table-inheritance-in-rails/

class Article < ActiveRecord::Base 
    has_many :comments 
end 

class Comment < ActiveRecord::Base 
    belongs_to :article 
    scope :assigned, where(type: "AssignedComment") 
    scope :unassigned, where(type: "UnassignedComment") 
end 

class AssignedComment < Comment 

end 

class UnassignedComment < Comment 

end 

all = @article.comments 
assigned = @article.comments.assigned 
unassigned = @article.comments.unassigned 
+0

在過去,我試圖繼承,但它是一個錯... – Backo

1

如果AssignedCommentUnassignedComment具有相同的屬性和狀態assigned可以變更爲unassigned,並在相反的情況下,爲什麼不只是添加和屬性is_signedComment,做這樣的事情:

class Article < ActiveRecord::Base 
    has_many :comments 
end 

class Comment < ActiveRecord::Base 
    belongs_to :article 
    scope  :assigneds, -> { where(is_signed: true) } 
    scope  :unassigneds, -> { where(is_signed: false) } 
end 

隨着範圍,你可以做@article.comments.assigneds@article.comments.unassigneds,當然你可以你可以簡單地做@article.comments以獲得屬於@article的所有comments

+1

你應該遵守德米特法律。 – sonnyhe2002

+0

@Frozenna - 我不能只是添加屬性'is_signed'到'Comment',因爲'AssignedComment'和'UnassignedComment'具有* not *相同的屬性。 – Backo

相關問題