2011-07-12 221 views
4

我使用on Rails的Ruby的3.0.7,我想變幹(不要重複自己)我的範圍的方法。DRY範圍方法

在模型文件我有:

class Articles::Category < ActiveRecord::Base 
    scope :article_related_to, lambda { |user| where('articles_categories_article_relationships.user_id = ?', user.id) } 
    scope :comment_related_to, lambda { |user| where('comments_articles_article_category_relationships.user_id = ?', user.id) } 


    has_many :comment_article_category_relationships 
    has_many :comments, 
    :class_name => 'Comments::Articles::ArticleCategoryRelationship', 
    :through  => :comment_article_category_relationships, 
    :source  => :comment 

    has_many :article_relationships 
    :class_name => 'Articles::Categories::ArticleRelationship', 
    has_many :articles, 
    :through  => :article_relationships, 
    :source  => :article 
end 

通過使用上面的代碼,我可以這樣做:

@comment.article_categories.comment_related_to(@current_user) 
@comment.article_categories.article_related_to(@current_user) 

我如何「幹」作用域,以使可能的方法均使用:article_related_to:comment_related_to以使用類似以下的內容

@comment.article_categories.related_to(@current_user) 

# In order to pass the correct "context" 'article' or 'comment' I thought 
# something like 
# 
# @comment.article_categories.related_to(@current_user, 'article') 
# @comment.article_categories.related_to(@current_user, 'comment') 
# 
# but, maybe, there is a way to retrieve automatically that "context" so to 
# write only one "DRYed" scope method. 

+1

吆,我的眼睛都在流血只是試圖讓這件事直!無論如何,你可以通過@current_user對象獲得你正在尋找的東西嗎? – dogenpunk

+0

@dogenpunk - 順便說一句:「我的眼睛在流血只是試圖讓這件事直」 ......你什麼意思? - 在我的情況下,我能得到什麼,我在尋找通過「@current_user」對象,但是,在這另一面,如問題描述我有同樣的問題。 – Backo

+1

我認爲這是一個幹太遠個人:可讀性爲我拍幹,這使得代碼更難閱讀。 DRY應該是關於保持功能或值等在一個地方,而不是減少的代碼行。 –

回答

1

我能提供的最好的是以下幾點:

scope :related_to, lambda { |user, context| 
    tbl = context == :article ? :articles_categories_article_relationships 
          : :comments_articles_article_category_relationships 
    where("#{tbl}.user_id = ?", user.id) 
} 

,將給你@comment.article_categories.related_to(@current_user, :article)喜歡你的建議。但我同意Max Williams的意見。這會不必要地混淆您的代碼而沒有真正的收益。

如果你真的渴望混淆您的代碼進一步可以做到這一點:

def self.method_missing(method, *args) 
    if method =~ /^(.*)_related_to$/ 
    related_to(*args, $1) 
    else 
    super 
    end 
end 

def self.related_to(user, context) 
    through = reflections[context.to_s.pluralize.to_sym].options[:through] 
    tbl = reflections[through].options[:class_name].underscore.pluralize.gsub('/', '_') 
    where("#{tbl}.user_id = ?", user.id) 
end 

請注意,我相信你的協會有幾個錯別字。也許應該是:

has_many :comment_article_category_relationships, 
    :class_name => 'Comments::Articles::ArticleCategoryRelationship' 
has_many :comments, 
    :through  => :comment_article_category_relationships, 
    :source  => :comment 

has_many :article_relationships, 
    :class_name => 'Articles::Categories::ArticleRelationship' 
has_many :articles, 
    :through  => :article_relationships, 
    :source  => :article