ruby on rails - rails - Rieles: Anulación del método de asociación ActiveRecord
ruby and rails documentation (7)
Creo que quería def tags.<<(*new_tags)
para la firma, que debería funcionar, o la siguiente que es equivalente y un poco más limpia si necesita anular múltiples métodos.
class << tags
def <<(*new_tags)
# rawr!
end
end
¿Hay alguna manera de anular uno de los métodos proporcionados por una asociación ActiveRecord?
Digamos, por ejemplo, que tengo el siguiente polimorfo típico has_many: a través de la asociación:
class Story < ActiveRecord::Base
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings, :order => :name
end
class Tag < ActiveRecord::Base
has_many :taggings, :dependent => :destroy
has_many :stories, :through => :taggings, :source => :taggable, :source_type => "Story"
end
Como probablemente sepa, esto agrega una gran cantidad de métodos asociados al modelo Story como etiquetas, etiquetas <<, etiquetas =, etiquetas.empty ?, etc.
¿Cómo hago para anular uno de estos métodos? Específicamente el método de las etiquetas <<. Es bastante fácil anular los métodos de una clase normal, pero parece que no puedo encontrar información sobre cómo anular los métodos de asociación. Haciendo algo como
def tags<< *new_tags
#do stuff
end
produce un error de sintaxis cuando se llama así que obviamente no es tan simple.
Debería definir el método de etiquetas para devolver un objeto que tenga un método <<
.
Podrías hacerlo así, pero realmente no lo recomendaría. Sería mucho mejor que simplemente al agregar un método para su modelo que hace lo que desea, en lugar de tratar de reemplazar algo que ActiveRecord usa.
Esto esencialmente ejecuta el método de tags
predeterminado agrega un método << al objeto resultante y devuelve ese objeto. Esto puede requerir un poco de recursos porque crea un nuevo método cada vez que lo ejecuta
def tags_with_append
collection = tags_without_append
def collection.<< (*arguments)
...
end
collection
end
# defines the method ''tags'' by aliasing ''tags_with_append''
alias_method_chain :tags, :append
El método que uso es extender la asociación. Puedes ver la forma en que manejo los atributos de ''cantidad'' aquí: https://gist.github.com/1399762
Básicamente, te permite simplemente hacer
has_many : tags, :through => : taggings, extend => QuantityAssociation
Sin saber exactamente qué esperas lograr anulando los métodos, es difícil saber si podrías hacer lo mismo.
Esto puede no ser útil en su caso, pero podría ser útil para otros que investigan esto.
Devolución de llamada de la asociación: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Ejemplo de los documentos:
class Project
has_and_belongs_to_many :developers, :after_add => :evaluate_velocity
def evaluate_velocity(developer)
...
end
end
Ver también Extensiones de asociación:
class Account < ActiveRecord::Base
has_many :people do
def find_or_create_by_name(name)
first_name, last_name = name.split(" ", 2)
find_or_create_by_first_name_and_last_name(first_name, last_name)
end
end
end
person = Account.first.people.find_or_create_by_name("David Heinemeier Hansson")
person.first_name # => "David"
person.last_name # => "Heinemeier Hansson"
Puedes usar block con has_many
para extender tu asociación con los métodos. Vea el comentario "Use un bloque para extender sus asociaciones" here .
Anular los métodos existentes también funciona, pero no sé si es una buena idea.
has_many :tags, :through => :taggings, :order => :name do
def << (value)
"overriden" #your code here
super value
end
end
Si desea acceder al modelo en Rails 3.2, debe usar proxy_association.owner
Ejemplo:
class Author < ActiveRecord::Base
has_many :books do
def << (book)
proxy_association.owner.add_book(book)
end
end
def add_book (book)
# do your thing here.
end
end
Ver documentation
Rails guía documentos sobre anular los métodos agregados directamente.
El problema de OP con anulación <<
es probablemente la única excepción a esto, por lo que sigue la respuesta principal . Pero no funcionaría para has_one
=
método de asignación o métodos getter.