Модель совместного использования для полиморфных ассоциаций - PullRequest
0 голосов
/ 11 октября 2010

Допустим, полиморфная ассоциация, скажем, «бизнес» и «персонал», оба из которых являются «оплачиваемыми» (имеется в виду, что им назначены часы) Каков рекомендуемый подход, чтобы модель «часа» выполняла те же методы для часов бизнес-объекта или объекта персонала?

Для простого примера модель «часа» может содержать:

  def self.find_hours_for_id(id)
    Business.find( id ).hours
  end

Однако я могу захотеть выполнить этот же метод для сотрудника, и в этом случае тот же метод будет вызывать эквивалент

Staff.find( id ).hours

Хорошо или плохо устанавливать имя модели в базовом классе модели:

class BusinessHour < Hour
  @mymodel = "Business"
end

class Hour < ActiveRecord::Base
  def self.find_hours_for_id(id)
    @mymodel.constantize.find( id ).hours
  end
end

Затем с контроллера позвоните:

BusinessHour.find_hours_for_id(id)

Есть ли лучшее решение?

Ответы [ 2 ]

1 голос
/ 11 октября 2010

Предположим, о, например, ваша объектная модель выглядит следующим образом:

class Business < ActiveRecord::Base
  has_many :hours, :as => :hourable
end

class Staff < ActiveRecord::Base
  has_many :hours, :as => :hourable
end

class Hour < ActiveRecord::Base
  belongs_to :hourable, :polymorphic => true
end

class BusinessHour < Hour
  # etc
end

Тогда у вас уже есть ссылка на нужный вам класс в 'hourable', и вы можете добавить искатель следующим образом:

class Hour < ActiveRecord::Base
  belongs_to :hourable, :polymorphic => true

  def self.get_hours_by_hourable_id(id)
    hourable.class.find(id).hours
  end
end

Просто предложение, но вы можете рассмотреть вопрос о проверке подклассов, чтобы гарантировать, что: hourable - это соответствующий тип, например:

class BusinessHour < Hour
  validates :hourable_must_be_business

  def hourable_must_be_business
    unless hourable_type == 'Business'
      self.errors.add_to_base("Hourable for BusinessHour must be Business") 
    end
  end
end
1 голос
/ 11 октября 2010

Вы также можете использовать модуль, как этот.

module Hour
  def hours_by(model)
    class_eval do
      def self.find_hours_for_id(id)
        model.find(id).hours
      end
    end
  end
end

class BusinessHour < AR
  extends Hour
  hours_by Business
end

BusinessHour.find_hours_for_id(id)
...