首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Rails4中使用关注点

如何在Rails4中使用关注点
EN

Stack Overflow用户
提问于 2013-01-27 05:36:28
回答 6查看 243.4K关注 0票数 636

默认的Rails4项目生成器现在在控制器和模型下创建了目录"concerns“。我找到了一些关于如何使用路由问题的解释,但没有关于控制器或模型的解释。

我很确定这与当前社会上的"DCI潮流“有关,并愿意尝试一下。

问题是,我应该如何使用这个特性,是否有一个关于如何定义命名/类层次结构的约定,以便使其工作?如何在模型或控制器中包含关注点?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2013-02-26 06:50:30

所以我自己找出来了。这实际上是一个非常简单但强大的概念。它与代码重用有关,如下面的示例所示。基本上,这个想法是提取公共的和/或上下文特定的代码块,以便清理模型,避免它们变得太胖和混乱。

作为示例,我将使用一个众所周知的模式,即taggable模式:

代码语言:javascript
复制
# app/models/product.rb
class Product
  include Taggable

  ...
end

# app/models/concerns/taggable.rb
# notice that the file name has to match the module name 
# (applying Rails conventions for autoloading)
module Taggable
  extend ActiveSupport::Concern

  included do
    has_many :taggings, as: :taggable
    has_many :tags, through: :taggings

    class_attribute :tag_limit
  end

  def tags_string
    tags.map(&:name).join(', ')
  end

  def tags_string=(tag_string)
    tag_names = tag_string.to_s.split(', ')

    tag_names.each do |tag_name|
      tags.build(name: tag_name)
    end
  end

  # methods defined here are going to extend the class, not the instance of it
  module ClassMethods

    def tag_limit(value)
      self.tag_limit_value = value
    end

  end

end

因此,按照Product示例,您可以将Taggable添加到您想要的任何类中,并共享其功能。

DHH很好地解释了这一点。

在Rails 4中,我们将邀请程序员使用默认的应用程序/模型/关注点和应用程序/控制器/关注点目录的关注点,这些目录会自动成为加载路径的一部分。再加上ActiveSupport::Concern包装器,就足以让这个轻量级的分解机制大放异彩了。

票数 625
EN

Stack Overflow用户

发布于 2014-09-16 06:50:59

我一直在读到关于使用模型关注点对胖模型进行皮肤处理以及使模型代码变干的文章。以下是示例的解释:

1) DRYing up模型代码

考虑一个文章模型、一个事件模型和一个评论模型。一篇文章或一个事件有很多评论。评论属于文章或事件。

传统上,模型可能如下所示:

评论模型:

代码语言:javascript
复制
class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
end

文章模型:

代码语言:javascript
复制
class Article < ActiveRecord::Base
  has_many :comments, as: :commentable 

  def find_first_comment
    comments.first(created_at DESC)
  end

  def self.least_commented
   #return the article with least number of comments
  end
end

事件模型

代码语言:javascript
复制
class Event < ActiveRecord::Base
  has_many :comments, as: :commentable 

  def find_first_comment
    comments.first(created_at DESC)
  end

  def self.least_commented
   #returns the event with least number of comments
  end
end

正如我们所注意到的,有一段重要的代码对于事件和文章都是通用的。使用关注点,我们可以在一个单独的模块Commentable中提取这些公共代码。

为此,在app/models/concerns中创建一个commentable.rb文件。

代码语言:javascript
复制
module Commentable
  extend ActiveSupport::Concern

  included do
    has_many :comments, as: :commentable
  end

  # for the given article/event returns the first comment
  def find_first_comment
    comments.first(created_at DESC)
  end

  module ClassMethods
    def least_commented
      #returns the article/event which has the least number of comments
    end
  end
end

现在你的模型看起来像这样:

评论模型:

代码语言:javascript
复制
class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
end

文章模型:

代码语言:javascript
复制
class Article < ActiveRecord::Base
  include Commentable
end

事件模型:

代码语言:javascript
复制
class Event < ActiveRecord::Base
  include Commentable
end

2)皮肤化脂肪模型。

考虑一个事件模型。一个事件有很多参与者和评论。

通常,事件模型可能如下所示

代码语言:javascript
复制
class Event < ActiveRecord::Base   
  has_many :comments
  has_many :attenders


  def find_first_comment
    # for the given article/event returns the first comment
  end

  def find_comments_with_word(word)
    # for the given event returns an array of comments which contain the given word
  end 

  def self.least_commented
    # finds the event which has the least number of comments
  end

  def self.most_attended
    # returns the event with most number of attendes
  end

  def has_attendee(attendee_id)
    # returns true if the event has the mentioned attendee
  end
end

具有许多关联的模型有积累越来越多代码的趋势,并且变得难以管理。关注点提供了一种对fat模块进行皮肤化的方法,使其更加模块化和易于理解。

可以使用如下关注点重构上述模型:在app/models/ concerns /event文件夹中创建一个attendable.rbcommentable.rb文件

attendable.rb

代码语言:javascript
复制
module Attendable
  extend ActiveSupport::Concern

  included do 
    has_many :attenders
  end

  def has_attender(attender_id)
    # returns true if the event has the mentioned attendee
  end

  module ClassMethods
    def most_attended
      # returns the event with most number of attendes
    end
  end
end

commentable.rb

代码语言:javascript
复制
module Commentable
  extend ActiveSupport::Concern

  included do 
    has_many :comments
  end

  def find_first_comment
    # for the given article/event returns the first comment
  end

  def find_comments_with_word(word)
    # for the given event returns an array of comments which contain the given word
  end

  module ClassMethods
    def least_commented
      # finds the event which has the least number of comments
    end
  end
end

现在使用关注点,您的事件模型简化为

代码语言:javascript
复制
class Event < ActiveRecord::Base
  include Commentable
  include Attendable
end

*在使用关注点时,建议使用基于“域”的分组,而不是“技术”分组。基于域的分组类似于'Commentable','Photoable','Attendable‘。技术分组将意味着'ValidationMethods','FinderMethods‘等

票数 385
EN

Stack Overflow用户

发布于 2015-03-23 22:11:17

值得一提的是,许多人认为使用关注点是个坏主意。

  1. like this guy
  2. and this one

一些原因:

在幕后有一些黑魔法在发生-关注的是修补pattern.

  • Your方法,有一个完整的依赖处理系统-对于一些琐碎的东西来说太复杂了,好的老
  1. include类同样枯燥。如果你在不同的模块中填充50个公共方法并包含它们,你的类仍然有50个公共方法,只是你隐藏了代码的味道,把你的垃圾放在drawers.
  2. Codebase中实际上更难导航所有这些关注点。
  3. 你确定你团队的所有成员都有相同的理解吗,什么应该真正替代关注点?

担心很容易让你伤到自己的腿,小心对待它们。

票数 100
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14541823

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档