Rails: Overriding ActiveRecord association method

蓝咒 提交于 2019-11-27 19:00:24
Voyta

You can use block with has_many to extend your association with methods. See comment "Use a block to extend your associations" here.
Overriding existing methods also works, don't know whether it is a good idea however.

  has_many :tags, :through => :taggings, :order => :name do
    def << (value)
      "overriden" #your code here
      super value
    end     
  end

If you want to access the model itself in Rails 3.2 you should use proxy_association.owner

Example:

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

See documentation

I think you wanted def tags.<<(*new_tags) for the signature, which should work, or the following which is equivalent and a bit cleaner if you need to override multiple methods.

class << tags
  def <<(*new_tags)
    # rawr!
  end
end

You would have to define the tags method to return an object which has a << method.

You could do it like this, but I really wouldn't recommend it. You'd be much better off just adding a method to your model that does what you want than trying to replace something ActiveRecord uses.

This essentially runs the default tags method adds a << method to the resulting object and returns that object. This may be a bit resource intensive because it creates a new method every time you run it

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  

The method I use is to extend the association. You can see the way I handle 'quantity' attributes here: https://gist.github.com/1399762

It basically allows you to just do

has_many : tags, :through => : taggings, extend => QuantityAssociation

Without knowing exactly what your hoping to achieve by overriding the methods its difficult to know if you could do the same.

This may not be helpful in your case but could be useful for others looking into this.

Association Callbacks: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Example from the docs:

class Project
  has_and_belongs_to_many :developers, :after_add => :evaluate_velocity

  def evaluate_velocity(developer)
    ...
  end
end

Also see Association Extensions:

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"
lulalala

Rails guides documents about overriding the added methods directly.

OP's issue with overriding << probably is the only exception to this, for which follow the top answer. But it wouldn't work for has_one's = assignment method or getter methods.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!