Имя/тип класса Rails не работает для полиморфного has_many :through

У меня есть система выставления счетов, которая управляет дебетом и кредитом. В основном сумма счета-фактуры получается по сумме его дебетов, а баланс получается путем взятия суммы его кредитов и вычитания ее из общей суммы.

Я делаю это с четырьмя моделями.

  1. Счет
  2. Позиция
  3. Списание средств
  4. Кредит

Это работает через модель соединения (элемент строки), которая имеет полиморфную ассоциацию, называемую записываемой. На первый взгляд все работает правильно. Однако проверка позиции показывает, что, хотя значение recordable_id отображается правильно, значение параметра recordable_type равно нулю.

Вот разбивка кода:

class Invoice < ActiveRecord::Base
  has_many :line_items, :dependent => :destroy
  has_many :debits, :through => :line_items, :as => :recordable
  has_many :credits, :through => :line_items, :as => :recordable
end

class LineItem < ActiveRecord::Base
  belongs_to :invoice
  belongs_to :recordable, :polymorphic => true
  belongs_to :credit, :class_name => "Credit", :foreign_key => "recordable_id"
  belongs_to :debit,  :class_name => "Debit",   :foreign_key => "recordable_id"
end

class Credit < ActiveRecord::Base
  has_many :line_items, :as => :recordable, :dependent => :destroy
end

class Debit < ActiveRecord::Base
  has_many :line_items, :as => :recordable, :dependent => :destroy
end

Может ли кто-нибудь указать мне правильное направление здесь?


person Jim Jeffers    schedule 23.01.2010    source источник
comment
Как вы назначаете line_items кредиту/дебету?   -  person Nazar    schedule 23.01.2010
comment
Это происходит автоматически через has_many :through. Поэтому, когда вы делаете Invoice.last.credits ‹‹ Credit.new, LineItem автоматически генерируется и создается с правильными recordable_id и invoice_id.   -  person Jim Jeffers    schedule 24.01.2010
comment
Разве :as не должно быть на has_many :line_items, а не на has_many :through ассоциациях?   -  person mckeed    schedule 26.01.2010
comment
Нет, потому что invoice_id — это поле в объекте line_item. Полиморфизм применим только к объектам дебета и кредита, которые используют :as в своих объявлениях :has_many.   -  person Jim Jeffers    schedule 26.01.2010


Ответы (2)


Вы объявляете неоднозначные ассоциации в своем классе LineItem.

В двух словах, belongs_to делает это в вашем классе:

  1. belongs_to :invoice создает метод invoice, который ищет в таблице invoices запись, на которую ссылается invoice_id
  2. belongs_to :recordable, :polymorphic => true создает метод recordable, который ищет в таблице recordable_type.underscore.pluralize запись, на которую ссылается recordable_id
  3. belongs_to :credit, :class_name => "Credit", :foreign_key => "recordable_id" создает метод credit, который ищет в таблице credits запись, на которую ссылается recordable_id. Обратите внимание, что recordable_type здесь игнорируется.
  4. то же самое относится к belongs_to :debit соответственно.

Поскольку ваша статья расходов может относиться только к кредиту или к дебету, нет смысла дополнительно объявлять эти ассоциации. Вы можете обратиться к ним через ассоциацию recordable.

person mikezter    schedule 28.01.2010

Invoice.last.credits ‹‹ Credit.new

Это правильный способ присваивания ассоциаций Я не понимаю, почему recordable_type не подхватывается.

Хватаюсь за соломинку, но пробовали ли вы:

Invoice.last.credits << Credit.create(:value => 1, :date => Time.now, ...)

Лично у меня были проблемы при использовании многотипных таблиц соединения «многие ко многим» в Rails, которые часто решались с помощью has_many_polymorphs плагин.

Извините, что это не дает прямого ответа на ваш вопрос.

person Nazar    schedule 24.01.2010
comment
Да, я закончил тем, что просто создал прямую связь, поскольку поведение приложения больше не нуждалось во многих отношениях счетов-фактур к дебетам. Я не уверен, почему он не поднимает его. В прошлом я делал точно такую ​​же настройку для разных объектов. Может быть, я наткнулся на защищенное имя, но я не могу думать об этом. Первоначально я использовал item_id и item_type, но даже после изменения на recordable_id и type он все равно не работал. Совсем запутался. - person Jim Jeffers; 25.01.2010