tutorial rails ejemplos descargar curso caracteristicas ruby-on-rails ruby-on-rails-4 dci

ruby on rails - ejemplos - Cómo usar las preocupaciones en Rails 4



ruby on rails tutorial (6)

Así que lo descubrí por mi cuenta. En realidad es un concepto bastante simple pero poderoso. Tiene que ver con la reutilización de código como en el siguiente ejemplo. Básicamente, la idea es extraer fragmentos de código comunes y / o específicos al contexto para limpiar los modelos y evitar que se vuelvan demasiado gruesos y desordenados.

Como ejemplo, pondré un patrón bien conocido, el patrón etiquetable:

# 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

Entonces, siguiendo el ejemplo del producto, puede agregar Taggable a cualquier clase que desee y compartir su funcionalidad.

Esto está bastante bien explicado por DHH :

En Rails 4, invitaremos a los programadores a usar las preocupaciones con los directorios predeterminados de aplicación / modelos / inquietudes y aplicación / controladores / inquietudes que son automáticamente parte de la ruta de carga. Junto con el envoltorio ActiveSupport :: Concern, es suficiente apoyo para hacer que brille este ligero mecanismo de factorización.

El generador de proyecto de Rails 4 predeterminado ahora crea el "problema" del directorio en los controladores y modelos. He encontrado algunas explicaciones sobre cómo usar las preocupaciones de enrutamiento, pero nada sobre controladores o modelos.

Estoy bastante seguro de que tiene que ver con la "tendencia actual de DCI" en la comunidad y me gustaría intentarlo.

La pregunta es, ¿cómo se supone que debo utilizar esta función, hay alguna convención sobre cómo definir la jerarquía de nombres / clases para que funcione? ¿Cómo puedo incluir una preocupación en un modelo o controlador?


En lo concerniente a hacer archivo file.rb

Por ejemplo, quiero en mi aplicación donde el atributo create_by existe actualice el valor en 1 y 0 para updated_by

module 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

Después de eso incluye en tu modelo así:

class Role < ActiveRecord::Base include TestConcern end


He estado leyendo sobre el uso de las preocupaciones de los modelos para personalizar los modelos de grasa, así como también SECAR los códigos de sus modelos. Aquí hay una explicación con ejemplos:

1) Secado de códigos modelo

Considere un modelo de artículo, un modelo de evento y un modelo de comentario. Un artículo o un evento tiene muchos comentarios. Un comentario pertenece al artículo o al evento.

Tradicionalmente, los modelos pueden verse así:

Modelo de comentario:

class Comment < ActiveRecord::Base belongs_to :commentable, polymorphic: true end

Modelo del artículo:

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

Modelo de evento

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

Como podemos observar, hay un importante fragmento de código común tanto para el evento como para el artículo. En cuanto a las preocupaciones, podemos extraer este código común en un módulo independiente que se puede comentar.

Para esto, cree un archivo commentable.rb en app / models / concern.

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

Y ahora tus modelos se ven así:

Modelo de comentario:

class Comment < ActiveRecord::Base belongs_to :commentable, polymorphic: true end

Modelo del artículo:

class Article < ActiveRecord::Base include Commentable end

Modelo de evento:

class Event < ActiveRecord::Base include Commentable end

2) Modelos de grasa para la piel.

Considere un modelo de evento. Un evento tiene muchos asistentes y comentarios.

Típicamente, el modelo de evento podría verse así

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

Los modelos con muchas asociaciones y por lo demás tienen tendencia a acumular cada vez más código y se vuelven inmanejables. Las inquietudes brindan una forma de personalizar los módulos de grasa para que sean más modulares y fáciles de entender.

El modelo anterior se puede refactorizar utilizando las preocupaciones de la siguiente manera: attendable.rb un archivo attendable.rb y commentable.rb en la carpeta de aplicaciones / modelos / preocupaciones / eventos

attendable.rb

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

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

Y ahora usando Concerns, su modelo de evento se reduce a

class Event < ActiveRecord::Base include Commentable include Attendable end

* Si bien su uso se refiere, es aconsejable ir a la agrupación basada en el "dominio" en lugar de la agrupación "técnica". La agrupación basada en el dominio es como ''Comentable'', ''Fotogenerable'', ''Atendible''. La agrupación técnica significará ''ValidationMethods'', ''FinderMethods'', etc.


Sentí que la mayoría de los ejemplos aquí demuestran la potencia del module lugar de cómo ActiveSupport::Concern agrega valor al module .

Ejemplo 1: Módulos más legibles.

Así que sin preocuparnos de cómo será un module típico.

module M def self.included(base) base.extend ClassMethods base.class_eval do scope :disabled, -> { where(disabled: true) } end end def instance_method ... end module ClassMethods ... end end

Después de refactorizar con ActiveSupport::Concern .

require ''active_support/concern'' module M extend ActiveSupport::Concern included do scope :disabled, -> { where(disabled: true) } end class_methods do ... end def instance_method ... end end

Verás que los métodos de instancia, los métodos de clase y el bloque incluido son menos complicados. Las preocupaciones los inyectarán apropiadamente para usted. Esa es una ventaja de usar ActiveSupport::Concern .

Ejemplo 2: Manejar las dependencias del módulo con gracia.

module Foo def self.included(base) base.class_eval do def self.method_injected_by_foo_to_host_klass ... end end end end module Bar def self.included(base) base.method_injected_by_foo_to_host_klass end end class Host include Foo # We need to include this dependency for Bar include Bar # Bar is the module that Host really needs end

En este ejemplo, Bar es el módulo que Host realmente necesita. Pero como Bar tiene dependencia con Foo la clase Host tiene que include Foo (pero espera, ¿por qué Host quiere saber acerca de Foo ? ¿Se puede evitar?).

Así que Bar agrega dependencia donde quiera que vaya. Y el orden de inclusión también importa aquí. Esto agrega mucha complejidad / dependencia a una base de código enorme.

Después de refactorizar con ActiveSupport::Concern

require ''active_support/concern'' module Foo extend ActiveSupport::Concern included do def self.method_injected_by_foo_to_host_klass ... end end end module Bar extend ActiveSupport::Concern include Foo included do self.method_injected_by_foo_to_host_klass end end class Host include Bar # It works, now Bar takes care of its dependencies end

Ahora parece simple.

¿Si estás pensando por qué no podemos agregar la dependencia de Foo en el módulo Bar ? Eso no funcionará, ya que method_injected_by_foo_to_host_klass se debe inyectar en la clase que incluye Bar no en el módulo Bar sí.

Fuente: Rails ActiveSupport :: Preocupación


Vale la pena mencionar que el uso de las preocupaciones es considerado una mala idea por muchos.

  1. como este chico
  2. y éste

Algunas razones:

  1. Hay algo de magia oscura detrás de las escenas: la preocupación es parchear el método de include , hay todo un sistema de manejo de dependencias: demasiada complejidad para algo que es trivial y un viejo patrón de mezcla Ruby.
  2. Tus clases no son menos secas. Si metes 50 métodos públicos en varios módulos y los incluyes, tu clase todavía tiene 50 métodos públicos, es solo que escondes el olor del código, de alguna forma metes la basura en los cajones.
  3. Codebase es realmente más difícil de navegar con todas esas preocupaciones alrededor.
  4. ¿Está seguro de que todos los miembros de su equipo tienen el mismo entendimiento de lo que realmente debería sustituir a la preocupación?

Las preocupaciones son una manera fácil de dispararte en la pierna, ten cuidado con ellas.


Este post me ayudó a entender las preocupaciones.

# app/models/trader.rb class Trader include Shared::Schedule end # app/models/concerns/shared/schedule.rb module Shared::Schedule extend ActiveSupport::Concern ... end