本文翻译自:How to use concerns in Rails 4
The default Rails 4 project generator now creates the directory "concerns" under controllers and models.
默认的Rails 4项目生成器现在在控制器和模型下创建目录“Concer”。I have found some explanations about how to use routing concerns, but nothing about controllers or models.
我找到了一些关于如何使用路由问题的解释,但没有关于控制器或模型的解释。I am pretty sure it has to do with the current "DCI trend" in the community and would like to give it a try.
我很确定它与社区当前的“DCI趋势”有关,并且想尝试一下。The question is, how am I supposed to use this feature, is there a convention on how to define the naming / class hierarchy in order to make it work?
问题是,我应该如何使用此功能,是否有关于如何定义命名/类层次结构以使其工作的约定?How can I include a concern in a model or controller?
如何在模型或控制器中包含问题?#1楼
参考:https://stackoom.com/question/z0zX/如何在Rails-中使用问题
#2楼
So I found it out by myself.
所以我自己发现了它。It is actually a pretty simple but powerful concept.
它实际上是一个非常简单但功能强大的概念。It has to do with code reuse as in the example below.
它与代码重用有关,如下例所示。Basically, the idea is to extract common and / or context specific chunks of code in order to clean up the models and avoid them getting too fat and messy.
基本上,这个想法是提取常见的和/或特定于上下文的代码块,以便清理模型并避免它们变得太胖和混乱。As an example, I'll put one well known pattern, the taggable pattern:
作为一个例子,我将放置一个众所周知的模式,可标记的模式:# 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
So following the Product sample, you can add Taggable to any class you desire and share its functionality.
因此,按照Product示例,您可以将Taggable添加到您想要的任何类并共享其功能。This is pretty well explained by DHH :
DHH很好地解释了这一点:In Rails 4, we're going to invite programmers to use concerns with the default app/models/concerns and app/controllers/concerns directories that are automatically part of the load path. 在Rails 4中,我们将邀请程序员使用默认app / models / concerns和app / controllers / concerns目录中的问题,这些目录自动成为加载路径的一部分。 Together with the ActiveSupport::Concern wrapper, it's just enough support to make this light-weight factoring mechanism shine. 与ActiveSupport :: Concern包装一起,它足以支持这种轻量级因子机制。
#3楼
This post helped me understand concerns.
这篇文章帮助我理解了问题。# app/models/trader.rb
class Trader
include Shared::Schedule
end
# app/models/concerns/shared/schedule.rb
module Shared::Schedule
extend ActiveSupport::Concern
...
end
#4楼
I have been reading about using model concerns to skin-nize fat models as well as DRY up your model codes.
我一直在阅读有关使用模型问题来修饰脂肪模型以及干掉模型代码的问题。Here is an explanation with examples:
以下是对示例的解释:1) DRYing up model codes 1)干掉型号代码
Consider a Article model, a Event model and a Comment model.
考虑文章模型,事件模型和评论模型。An article or an event has many comments.
文章或事件有很多评论。A comment belongs to either Article or Event.
评论属于文章或事件。Traditionally, the models may look like this:
传统上,模型可能如下所示:Comment Model:
评论模型:class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
Article Model:
文章模型: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
Event Model
事件模型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
As we can notice, there is a significant piece of code common to both Event and Article.
我们可以注意到,事件和文章都有一个共同的重要代码。Using concerns we can extract this common code in a separate module Commentable.
使用关注点,我们可以在单独的模块中提取此公共代码。For this create a commentable.rb file in app/models/concerns.
为此,在app / models / concerns中创建一个commentable.rb文件。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
And now your models look like this :
现在您的模型看起来像这样:Comment Model:
评论模型:class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
Article Model:
文章模型:class Article < ActiveRecord::Base
include Commentable
end
Event Model:
活动模型:class Event < ActiveRecord::Base
include Commentable
end
2) Skin-nizing Fat Models. 2)皮肤肥胖模型。
Consider a Event model.
考虑事件模型。A event has many attenders and comments.
一个活动有很多参与者和评论。Typically, the event model might look like this
通常,事件模型可能如下所示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
Models with many associations and otherwise have tendency to accumulate more and more code and become unmanageable.
具有许多关联的模型,否则倾向于积累越来越多的代码并变得难以管理。Concerns provide a way to skin-nize fat modules making them more modularized and easy to understand.
关注点提供了一种皮肤化脂肪模块的方法,使它们更加模块化和易于理解。The above model can be refactored using concerns as below: Create a
attendable.rb
and
commentable.rb
file in app/models/concerns/event folder
可以使用以下关注点重构上述模型:在app / models / concerns / event文件夹中创建attendable.rb
和 commentable.rb
文件 attendable.rb
attendable.rbmodule 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
commentable.rbmodule 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
And now using Concerns, your Event model reduces to
现在使用Concerns,您的事件模型减少到class Event < ActiveRecord::Base
include Commentable
include Attendable
end
* While using concerns its advisable to go for 'domain' based grouping rather than 'technical' grouping.
*在使用问题时,建议采用“域名”分组而不是“技术”分组。Domain Based grouping is like 'Commentable', 'Photoable', 'Attendable'.
基于域的分组就像“可评论”,“可照片”,“可以参加”。Technical grouping will mean 'ValidationMethods', 'FinderMethods' etc
技术分组将意味着'ValidationMethods','FinderMethods'等#5楼
In concerns make file filename.rb
关注make文件filename.rbFor example I want in my application where attribute create_by exist update there value by 1, and 0 for updated_by
例如,我想在我的应用程序中,属性create_by存在,将值更新为1,更新为update_bymodule TestConcern
extend ActiveSupport::Concern
def checkattributes
if self.has_attribute?(:created_by)
self.update_attributes(created_by: 1)
end
if self.has_attribute?(:updated_by)
self.update_attributes(updated_by: 0)
end
end
end
If you want to pass arguments in action
如果你想传递参数included do
before_action only: [:create] do
blaablaa(options)
end
end
after that include in your model like this:
之后,在您的模型中包含如下:class Role < ActiveRecord::Base
include TestConcern
end
#6楼
It's worth to mention that using concerns is considered bad idea by many.
值得一提的是,使用顾虑被很多人认为是坏主意。- like this guy 喜欢这个家伙
- and this one 还有这个
Some reasons:
一些原因:- There is some dark magic happening behind the scenes - Concern is patching
method, there is a whole dependency handling system - way too much complexity for something that's trivial good old Ruby mixin pattern. 幕后发生了一些黑暗魔法 - 关注是修补include
方法,有一个完整的依赖处理系统 - 对于一些琐碎的好旧Ruby混合模式的东西太复杂了。include
- Your classes are no less dry. 你的课程也不干。 If you stuff 50 public methods in various modules and include them, your class still has 50 public methods, it's just that you hide that code smell, sort of put your garbage in the drawers. 如果你在各种模块中填充50个公共方法并包含它们,你的类仍然有50个公共方法,只是你隐藏了代码味道,有点把你的垃圾放在抽屉里。
- Codebase is actually harder to navigate with all those concerns around. 代码库实际上更难以解决所有这些问题。
- Are you sure all members of your team have same understanding what should really substitute concern? 您确定您的团队中的所有成员都有同样的理解应该真正替代关注点吗?
Concerns are easy way to shoot yourself in the leg, be careful with them.
关注是轻松拍摄腿部的方法,小心使用它们。