СУХИЕ методы области - PullRequest
       24

СУХИЕ методы области

4 голосов
/ 13 июля 2011

Я использую Ruby on Rails 3.0.7, и я хотел бы СУХОЙ (не повторять себя) мои методы области видимости.

В файле модели у меня есть:

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)

Как я могу "СУХОЙ" методы областей, чтобы позволить и для 1010 *, и для :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 Ответ

1 голос
/ 17 июля 2011

Лучшее, что я могу предложить, это:

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), как вы предложили. Но я согласен с Максом Уильямсом. Это излишне запутывает ваш код без реальной выгоды.

Если вы действительно хотите запутать свой код дальше, вы можете сделать это:

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
...