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)?Raíles que extienden ActiveRecord :: Base
Respuesta
Existen varios enfoques:
Usando ActiveSupport :: La preocupación (Preferido)
leer la documentación 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)
crear un archivo en el directorio llamado config/initializers
extensions.rb
y añadir la siguiente línea al archivo:
require "active_record_extension"
Herencia (Preferido)
Consulte Toby answer.
parches mono (se debe evitar)
crear un archivo en el directorio llamado config/initializers
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 por Jamie Zawinski puede ser re-propuesto para ilustrar los problemas asociados con el mono-aplicación de parches.
Some people, when confronted with a problem, think “I know, I'll use monkey patching.” Now they have two problems.
Monkey patching es fácil y rápido. Pero, el tiempo y el esfuerzo guardado se extraen siempre 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.
Hum ... para el segundo ejemplo cuando ejecuto ./scripts/console Recibo un error "' include ': TypeError: tipo de argumento incorrecto Class (Módulo esperado) ". – xpepermint
@xpepermint Parece que lo comenzó con' clase MyActiveRecordExtensions' en lugar de 'módulo MyActiveRecordExtensions'. –
No ... Me enojé con copiar y pegar. Extraño ... – xpepermint
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 :)
Supongo que el paso 2 debe colocarse en config/environment.rb. No funciona para mí :(. ¿Puedes escribir algo más de ayuda? Thx. – xpepermint
Puede ampliar la clase y simplemente usar la herencia.
class AbstractModel < ActiveRecord::Base
self.abstract_class = true
end
class Foo < AbstractModel
end
class Bar < AbstractModel
end
Me gusta esta idea porque es una forma estándar de hacerlo, pero ... Aparece un error Tabla 'moboolo_development. abstract_models 'does not exists: MOSTRAR CAMPOS DE 'abstract_models'. ¿Dónde debería ponerlo? – xpepermint
Agregue 'self.abstract_class = true' a su' AbstractModel'. Rails ahora reconocerá el modelo como un modelo abstracto. –
¡Guau! No pensé que esto fuera posible. Lo intenté antes y me rendí cuando ActiveRecord se atragantó buscando 'AbstractModel' en la base de datos. ¡Quién sabía que un simple setter me ayudaría a SECAR las cosas! (Estaba empezando a encogerme ... era malo). Gracias Toby y Harish! – dooleyo
También puede utilizar ActiveSupport::Concern
y ser más central rieles idiomática 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 un método de instancia y los métodos en ClassMethods
incluidos como métodos de clase. P.ej.en un FooBar < ActiveRecord::Base
tendrá: FooBar.bar
y FooBar#foo
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
Tenga en cuenta que 'InstanceMethods' está en desuso desde Rails 3.2, simplemente ponga sus métodos en el cuerpo del módulo. –
Coloqué 'ActiveRecord :: Base.send (: include, MyExtension)' en un inicializador y luego funcionó para mí. Rails 4.1.9 –
Sólo para añadir a este tema, pasé un tiempo trabajando cómo probar tales extensiones (descendí 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
que tienen
ActiveRecord::Base.extend Foo::Bar
en un inicializador
Para un módulo, como a continuación
module Foo
module Bar
end
end
con los carriles 4, el concepto de la utilización de las preocupaciones de modularizar y seco hasta su modelos ha estado en destacados.
Las preocupaciones básicamente le permiten agrupar código similar 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 tener este aspecto:
Comentario Modelo:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
Artículo Modelo:
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
Evento Modelo
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 notar , ahí es una pieza importante 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 sus modelos se parecen a esto:
Comentario Modelo:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
Artículo Modelo:
class Article < ActiveRecord::Base
include Commentable
end
Modelo de eventos
class Event < ActiveRecord::Base
include Commentable
end
Un punto que me gustaría resaltar durante el uso de las preocupaciones es que Las preocupaciones se deben utilizar 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 link to a post que encontré muy útil para entender las preocupaciones en los modelos.
Esperamos que la valoración crítica ayude :)
Esa es mi respuesta favorita aquí, gracias :) –
rieles 5 proporciona un mecanismo incorporado para extender ActiveRecord::Base
.
Esto se consigue 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 que uno:
class Post < ApplicationRecord
end
Véase, por ejemplo this blogpost.
Con Rails 5, todos los modelos se heredan de ApplicationRecord & y ofrecen una forma agradable de incluir o ampliar otras bibliotecas de extensiones.
# 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, se incluyen 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, extienda 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!
- 1. Raíles: ActiveRecord db sort operación caso insensible
- 2. Funciones recursivas y listas que añaden/extienden
- 3. clases de PHP extienden
- 4. alias_method en ActiveRecord :: Base resultados en NameError
- 5. :: Significado de la parte base en ActiveRecord :: Base
- 6. ¿Las tareas de rastrillar raíles proporcionan acceso a los modelos de ActiveRecord?
- 7. Eclipse: encuentre todas las clases que extienden la interfaz
- 8. Raíles con en la base de datos de memoria
- 9. ¿Raíles que combinan dos matrices de hashes?
- 10. base de datos eficiente de actualización de raíles
- 11. raíles 3 validadores e i18n
- 12. Rspec con raíles 3.1 da ADVERTENCIA DE DEPRESIÓN ActiveRecord :: Associations :: AssociationCollection está en desuso?
- 13. Usar compilación con una asociación has_one en raíles
- 14. En tiempo de ejecución, se encuentran todas las clases en una aplicación Java que se extienden una clase base
- 15. Los raíles encuentran registro con cero has_many records asociados
- 16. Tipo de base de datos personalizada en ActiveRecord
- 17. Almacenamiento de matrices en la base de datos utilizando ActiveRecord
- 18. ¿Por qué ActiveRecord :: Base # update_attributes está en desuso?
- 19. Migración de una base de datos de Activerecord a Mongoid
- 20. ¿Cómo puedo usar ActiveRecord en una base de datos que tiene una columna llamada 'válida'? (DangerousAttributeError)
- 21. cómo verificar el nombre de la base de datos que ActiveRecord usa
- 22. Método indefinido `mass_assignment_sanitizer = 'para ActiveRecord :: Base: Class (NoMethodError)
- 23. Cualquiera que use ruby-protobuf y ActiveRecord
- 24. ¿Cómo se extienden a su clase Assert
- 25. CoffeeScript extienden constructor de la clase
- 26. Django: ¿se extienden otras aplicaciones ModelAdmin?
- 27. ActiveRecord :: UnknownAttributeError?
- 28. ActiveRecord :: DangerousAttributeError
- 29. ¿Hay clases de recopilación JAVA nativas que extienden la lista que no permite elementos nulos?
- 30. combinación compleja que con ActiveRecord y los carriles 3
¿Qué tipo de extensiones? Realmente necesitamos más para continuar. – jonnii