Модули против Классов и их влияние на потомков ActiveRecord :: Base - PullRequest
0 голосов
/ 22 февраля 2010

Вот Ruby OO head scratch для вас, вызванный этим сценарием Rails:

class Product < ActiveRecord::Base
  has_many(:prices)
  # define private helper methods 
end

module PrintProduct
  attr_accessor(:isbn)
  # override methods in ActiveRecord::Base
end

class Book < Product
  include PrintProduct
end

Product является базовым классом всех продуктов. Книги хранятся в таблице products через STI. Модуль PrintProduct обеспечивает некоторое общее поведение и состояние для потомков Product. Book используется внутри fields_for блоков в представлениях. Это работает для меня, но я обнаружил странное поведение:

  • После отправки формы внутри моего контроллера, если я вызываю метод для книги, определенной в PrintProduct, и этот метод вызывает вспомогательный метод, определенный в Product, который, в свою очередь, вызывает определенный метод prices на has_many я получу ошибку, сообщающую, что Book#prices не найден.

Почему это? Книга является прямым потомком Продукта!

Более интересно следующее ..

Когда я разработал эту иерархию, PrintProduct начал становиться более абстрактным ActiveRecord::Base, поэтому я подумал, что разумно переопределить все как таковое:

class Product < ActiveRecord::Base
end

class PrintProduct < Product
end

class Book < PrintProduct
end

Все определения методов и т. Д. Одинаковы. В этом случае, однако, моя веб-форма не будет загружаться, потому что атрибуты, определенные attr_accessor (которые являются «виртуальными атрибутами», на которые ссылается форма, но которые не сохраняются в БД), не найдены. Я получу сообщение о том, что нет метода Book#isbn. Это почему?? Я не вижу причины, по которой атрибуты attr_accessor не найдены внутри блока fields_for моей формы, когда PrintProduct является классом, но они обнаруживаются, когда PrintProduct является Module.

Любое понимание будет оценено. Я до смерти хочу знать, почему эти ошибки происходят!

1 Ответ

0 голосов
/ 23 февраля 2010

Возможно, вам повезет с задержкой вызова attr_accessor в PrintProduct до времени смешивания:

module PrintProduct
  def self.included(base)
    base.attr_accessor :isbn
  end
  # other instance methods here
end

Проблема, скорее всего, связана с синхронизацией вызова attr_accessor и с тем, как это относится к смешанным модулям. Я не уверен, что синхронизация определена спецификацией Ruby, поэтому она может варьироваться между реализациями или версиями ,

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