rails queries active ruby-on-rails extend rails-activerecord

ruby-on-rails - queries - rails where



Rieles que extienden ActiveRecord:: Base (9)

Con Rails 4, el concepto de utilizar las preocupaciones para modularizar y DRY hasta sus modelos ha estado en lo más destacado.

Las preocupaciones básicamente le permiten agrupar códigos similares de un modelo o en varios modelos en un solo módulo y luego usar este módulo en los modelos. Aquí hay un ejemplo:

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 a cualquier artículo o 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 fragmento significativo de código común para el modelo de evento y artículo. Usando las preocupaciones, podemos extraer este código común en un módulo separado Commentable.

Para esto crea un archivo commentable.rb en la aplicación / modelo / inquietudes.

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

Un punto que me gustaría resaltar al usar Preocupaciones es que las Preocupaciones deberían usarse para la agrupación ''basada en dominio'' en lugar de la agrupación ''técnica''. Por ejemplo, una agrupación de dominios es como ''Commentable'', ''Etiquetable'', etc. Una agrupación basada en tecnología será como ''FinderMethods'', ''ValidationMethods''.

Aquí hay un enlace a una publicación que encontré muy útil para entender las preocupaciones en los Modelos.

Espero que la crítica ayude :)

He leído algo sobre cómo extender ActiveRecord: clase base para que mis modelos tengan algunos métodos especiales. ¿Cuál es la manera más fácil de ampliarlo (tutorial paso a paso)?


Con Rails 5, todos los modelos se heredan de ApplicationRecord y ofrece una forma agradable de incluir o ampliar otras bibliotecas de extensión.

# app/models/concerns/special_methods.rb module SpecialMethods extend ActiveSupport::Concern scope :this_month, -> { where("date_trunc(''month'',created_at) = date_trunc(''month'',now())") } def foo # Code end end

Supongamos que el módulo de métodos especiales debe estar disponible en todos los modelos, inclúyalo en el archivo application_record.rb. Si queremos aplicar esto para un conjunto particular de modelos, luego incluirlo en las respectivas clases modelo.

# app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base self.abstract_class = true include SpecialMethods end # app/models/user.rb class User < ApplicationRecord include SpecialMethods # Code end

Si desea tener los métodos definidos en el módulo como métodos de clase, amplíe el módulo a ApplicationRecord.

# app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base self.abstract_class = true extend SpecialMethods end

Espero que ayude a los demás!


Hay varios enfoques:

Uso de ActiveSupport :: Preocupación (Preferido)

Lea la documentación de ActiveSupport::Concern para más detalles.

Cree un archivo llamado active_record_extension.rb en el directorio lib .

module ActiveRecordExtension extend ActiveSupport::Concern # add your instance methods here def foo "foo" end # add your static(class) methods here class_methods do #E.g: Order.top_ten def top_ten limit(10) end end end # include the extension ActiveRecord::Base.send(:include, ActiveRecordExtension)

Cree un archivo en el directorio config/initializers llamado extensions.rb y agregue la siguiente línea al archivo:

require "active_record_extension"

Herencia (Preferido)

Consulte la answer de Toby.

Parche de mono (debe evitarse)

Cree un archivo en el directorio config/initializers llamado active_record_monkey_patch.rb .

class ActiveRecord::Base #instance method, E.g: Order.new.foo def foo "foo" end #class method, E.g: Order.top_ten def self.top_ten limit(10) end end

La famosa cita sobre expresiones regulares de Jamie Zawinski se puede reutilizar para ilustrar los problemas asociados con el parche de monos.

Algunas personas, cuando se enfrentan con un problema, piensan "Lo sé, utilizaré el parche de monos". Ahora tienen dos problemas.

El parche de mono es fácil y rápido. Pero, el tiempo y el esfuerzo ahorrado siempre se extraen en el futuro; con interés compuesto. En estos días, limito el parche de mono para prototipar rápidamente una solución en la consola de rieles.


Puedes extender la clase y simplemente usar herencia.

class AbstractModel < ActiveRecord::Base self.abstract_class = true end class Foo < AbstractModel end class Bar < AbstractModel end


Rails 5 proporciona un mecanismo integrado para extender ActiveRecord::Base .

Esto se logra proporcionando capa adicional:

# app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base self.abstract_class = true # put your extensions here end

y todos los modelos heredan de ese:

class Post < ApplicationRecord end

Ver, por ejemplo, este blogpost .


Solo para agregar a este tema, pasé un tiempo trabajando en cómo probar tales extensiones (bajé por la ruta ActiveSupport::Concern ).

Así es como configuré un modelo para probar mis extensiones.

describe ModelExtensions do describe :some_method do it ''should return the value of foo'' do ActiveRecord::Migration.create_table :test_models do |t| t.string :foo end test_model_class = Class.new(ActiveRecord::Base) do def self.name ''TestModel'' end attr_accessible :foo end model = test_model_class.new(:foo => ''bar'') model.some_method.should == ''bar'' end end end


También puede usar ActiveSupport::Concern y tener más Core Rails Idiomatic como:

module MyExtension extend ActiveSupport::Concern def foo end module ClassMethods def bar end end end ActiveRecord::Base.send(:include, MyExtension)

[Editar] siguiendo el comentario de @daniel

Entonces todos sus modelos tendrán el método foo incluido como método de instancia y los métodos en ClassMethods incluidos como métodos de clase. Por ejemplo, en FooBar < ActiveRecord::Base tendrás: FooBar.bar y FooBar#foo

ActiveSupport::Concern


yo tengo

ActiveRecord::Base.extend Foo::Bar

en un inicializador

Para un módulo como a continuación

module Foo module Bar end end


Paso 1

module FooExtension def foo puts "bar :)" end end ActiveRecord::Base.send :include, FooExtension

Paso 2

# Require the above file in an initializer (in config/initializers) require ''lib/foo_extension.rb''

Paso 3

There is no step 3 :)