Как поделиться кодом между моделями? (Рельсы 2.3) - PullRequest
13 голосов
/ 01 марта 2010

У меня есть несколько методов, которыми я бы хотел поделиться между моделями, а не копировать и вставлять их. В контроллере я могу сделать это, поместив методы в application_controller.rb, который автоматически включается в каждый контроллер. Есть ли аналогичная вещь для моделей?

Спасибо!

Ответы [ 5 ]

16 голосов
/ 01 марта 2010

Вы можете создать файл с именем functionality.rb или что-то похожее в каталоге lib вашего приложения Rails. Создайте файл с именем модуля для автозагрузки при запуске Rails. Например, если бы я хотел добавить пометки для нескольких моделей, я бы создал файл с именем lib/flagging.rb, и он бы выглядел так:

module Flagging
  # Flags an object for further review
  def flag!
    self.update_attribute(:flagged, true)
  end

  # Clears all flags on an object
  def deflag!
    self.update_attribute(:flagged, false)
  end
end

В каждой модели, к которой я хотел добавить эту функцию, я делал бы следующее:

class Foo < ActiveRecord::Base
  include Flagging
end

Тогда я смог бы сделать что-то вроде:

foo = Foo.create
foo.flag!
4 голосов
/ 29 декабря 2011

Лучшее решение, приведенное выше, сработало для меня. В Rails 3 я обнаружил, что мне также пришлось обновить файл application.rb: config.autoload_paths += Dir["#{config.root}/lib/**/"], как здесь ответили: Лучший способ загрузить модуль / класс из папки lib в Rails 3?

3 голосов
/ 01 марта 2010

Вы можете либо: а) сделать что-то похожее на application_controller и создать класс модели, из которого другие могут создать подкласс, либо б) использовать модуль.

2 голосов
/ 01 марта 2010

Существует несколько способов обмена методами между двумя классами моделей.

  • Используйте наследование , если модели связаны друг с другом, например, общий родительский класс, который содержит методы, или один подкласс, другой, содержащий методы.
  • Используйте модулей / миксинов , которые могут использоваться несколькими моделями
0 голосов
/ 15 февраля 2013

Чтобы добавить к ответу Джоша, иногда вам может понадобиться поделиться кодом, определяющим полиморфную ассоциацию. Вы не можете просто поместить вызов метода has_many в свой модуль, потому что вы получите ошибку, например, в модуле с именем Votable:

undefined method `has_many' for Voteable:Module (NoMethodError)

Так что вместо этого вам нужно использовать метод self.included(base) и base.instance_eval. Вот пример с моим Voteable модулем:

module Voteable

  def self.included(base)
    base.instance_eval do
      has_many :votes, as: :voteable
      has_many :voters, through: :votes
    end
  end

  def voted_up_by?(user)
    user and votes.exists?(value: 1, voter_id: user)
  end

  def voted_down_by?(user)
    user and votes.exists?(value: -1, voter_id: user)
  end

end

Теперь вы можете include Voteable в моделях, которые будут иметь такое поведение. Это выполнит метод self.included(base) и определит ассоциацию для включающего класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...