Je l'ai donc découvert par moi-même. C'est en fait un concept assez simple mais puissant. Cela concerne la réutilisation du code comme dans l'exemple ci-dessous. Fondamentalement, l'idée est d'extraire des morceaux de code communs et / ou spécifiques au contexte afin de nettoyer les modèles et d'éviter qu'ils ne deviennent trop gros et désordonnés.
À titre d'exemple, je vais mettre un modèle bien connu, le modèle taggable:
# 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
Ainsi, en suivant l'exemple de produit, vous pouvez ajouter Taggable à n'importe quelle classe de votre choix et partager ses fonctionnalités.
Ceci est assez bien expliqué par DHH :
Dans Rails 4, nous allons inviter les programmeurs à utiliser des préoccupations avec les répertoires app / models / concern et app / controllers / concern par défaut qui font automatiquement partie du chemin de chargement. Avec l'encapsuleur ActiveSupport :: Concern, c'est juste assez de support pour faire briller ce mécanisme d'affacturage léger.
J'ai lu comment utiliser les préoccupations des modèles pour maquiller les modèles gras et sécher vos codes de modèle. Voici une explication avec des exemples:
1) SÉCHAGE des codes modèles
Prenons un modèle d'article, un modèle d'événement et un modèle de commentaire. Un article ou un événement a de nombreux commentaires. Un commentaire appartient à un article ou à un événement.
Traditionnellement, les modèles peuvent ressembler à ceci:
Modèle de commentaire:
Modèle d'article:
Modèle d'événement
Comme nous pouvons le remarquer, il existe un morceau de code important commun à la fois à l'événement et à l'article. En utilisant des préoccupations, nous pouvons extraire ce code commun dans un module séparé Commentable.
Pour cela, créez un fichier commentable.rb dans app / models / préoccupations.
Et maintenant, vos modèles ressemblent à ceci:
Modèle de commentaire:
Modèle d'article:
Modèle d'événement:
2) Modèles Fat Skin-nizing.
Prenons un modèle d'événement. Un événement a de nombreux participants et commentaires.
En règle générale, le modèle d'événement peut ressembler à ceci
Les modèles avec de nombreuses associations et autrement ont tendance à accumuler de plus en plus de code et à devenir ingérables. Les préoccupations fournissent un moyen de skin-nize les modules adipeux les rendant plus modularisés et faciles à comprendre.
Le modèle ci-dessus peut être refactorisé en utilisant les préoccupations comme ci-dessous: Créez un fichier
attendable.rb
etcommentable.rb
dans le dossier app / models / concern / eventattendable.rb
commentable.rb
Et maintenant, en utilisant Préoccupations, votre modèle d'événement se réduit à
* Lors de l'utilisation, il est préférable d'opter pour un groupement basé sur un domaine plutôt que sur un groupement «technique». Le regroupement basé sur le domaine est comme «Commentable», «Photoable», «Attendable». Le regroupement technique signifie «ValidationMethods», «FinderMethods», etc.
la source
def self.my_class_method
), les méthodes d'instance et les appels et directives de méthode dans la portée de la classe. Pas besoin demodule ClassMethods
add_item
, par exemple, vous êtes foutu. Je me souviens avoir pensé que Rails était cassé lorsque certains validateurs ont cessé de fonctionner, mais quelqu'un s'était implémentéany?
dans un souci. Je propose une solution différente: utiliser le souci comme une interface dans une langue différente. Au lieu de définir la fonctionnalité, il définit la référence à une instance de classe distincte qui gère cette fonctionnalité. Ensuite, vous avez des classes plus petites et plus soignées qui font une chose ...Il convient de mentionner que l'utilisation de préoccupations est considérée comme une mauvaise idée par beaucoup.
Certaines raisons:
include
méthode de correction , il y a tout un système de gestion des dépendances - beaucoup trop de complexité pour quelque chose qui est un bon vieux modèle de mixage Ruby.Les soucis sont un moyen facile de se tirer une balle dans la jambe, soyez prudent avec eux.
la source
Ce message m'a aidé à comprendre les préoccupations.
la source
J'ai senti que la plupart des exemples présentés ici démontraient le pouvoir de
module
laActiveSupport::Concern
valeur ajoutée plutôt que la façon dont elle l' ajoutaitmodule
.Exemple 1: modules plus lisibles.
Donc, sans se soucier de la façon dont ce
module
sera typique .Après refactoring avec
ActiveSupport::Concern
.Vous voyez que les méthodes d'instance, les méthodes de classe et le bloc inclus sont moins compliqués. Les préoccupations les injecteront de manière appropriée pour vous. C'est un avantage de l'utilisation
ActiveSupport::Concern
.Exemple 2: Gérez les dépendances des modules avec élégance.
Dans cet exemple,
Bar
le module aHost
vraiment besoin. Mais puisque laBar
dépendance avecFoo
laHost
classe doit le faireinclude Foo
(mais attendez pourquoiHost
veut savoirFoo
? Peut-il être évité?).Bar
Ajoute donc la dépendance partout où il va. Et l' ordre d'inclusion est également important ici. Cela ajoute beaucoup de complexité / dépendance à une énorme base de code.Après refactoring avec
ActiveSupport::Concern
Maintenant, ça a l'air simple.
Si vous pensez pourquoi ne pouvons-nous pas ajouter de
Foo
dépendance dans leBar
module lui-même? Cela ne fonctionnera pas carmethod_injected_by_foo_to_host_klass
il doit être injecté dans une classe qui n'inclutBar
pas leBar
module lui-même.Source: Rails ActiveSupport :: Préoccupation
la source
En cas de soucis, créez le fichier filename.rb
Par exemple, je veux dans mon application où l'attribut create_by existe mettre à jour la valeur par 1, et 0 pour updated_by
Si vous voulez passer des arguments en action
après cela, incluez dans votre modèle comme ceci:
la source