ActiveSupport::Concern отсутствует супер

У меня есть класс GoodsTransaction:

require Rails.root.join('lib','two_parties_transaction.rb')

class GoodsTransaction < Transaction

  include TwoPartiesTransaction

  def counterparty(org, loop = false)

    res = #Some logic
    res || super(org)
  end
end

который включает модуль TwoPartiesTransaction:

module TwoPartiesTransaction
  extend ActiveSupport::Concern

  included do
    def counterparty(org)
       #Some logic
    end
  end
end

и запуск контрагента терпит неудачу:

muichkine@ubuntu:~/src/white$ rails c
Faraday::Builder is now Faraday::RackBuilder.
Loading development environment (Rails 4.0.0)
2.0.0p247 :001 > tr = GoodsTransaction.new
=> #<GoodsTransaction _id: 5264e2eb75627540dd000000, e(end_date): nil, p(span): nil, s(start_date): nil, u(span_unit): nil, _type: "GoodsTransaction", a(autobook): nil, c(forced_close): nil, d(public_id): nil, k(autobook_period): nil, l(label): nil, n(autobook_number): nil, t(autobook_until): nil, contact_ids: nil, parent_id: nil, fc(creditor): nil, fd(debtor): nil> 
2.0.0p247 :002 > tr.counterparty(nil)
NoMethodError: super: no superclass method `counterparty' for   #<GoodsTransaction:0x000000090fe1d8>
from /home/muichkine/src/white/app/models/transactions/goods_transaction.rb:148:in `counterparty'

Что я делаю такого, что пропускает метод super coutnerparty?


person muichkine    schedule 21.10.2013    source источник


Ответы (1)


Для включения методов экземпляра из модуля в класс вам не нужно использовать ActiveSupport::Concern. Вы можете просто сделать

module TwoPartiesTransaction
  def counterparty(org)
     # ...
  end
end

Вы по-прежнему можете использовать ActiveSupport::Concern, если вам это нужно по другим причинам, а именно для выполнения кода на уровне класса (например, scope и т. д.) или добавления методов класса во включаемый класс. Дополнительные сведения о ActiveSupport::Concern см. в документации по API.

person Patrick Oscity    schedule 21.10.2013
comment
Из документации, на которую вы указываете, я понимаю, что 1/ClassMethods расширены и не включены в базовый класс, а это не то, на что я смотрю. 2/В документации вообще не говорится об обязательности ClassMethods, поскольку они размещают код непосредственно внутри блока indluded do. Я ошибаюсь в этом?! - person muichkine; 21.10.2013
comment
1) Я согласен, что это сбивает с толку, но extend добавит методы экземпляра модуля в качестве методов класса. Разве это не то, чего ты хочешь? 2) я отредактировал свой ответ, возможно, это немного проясняет его. - person Patrick Oscity; 21.10.2013
comment
Если вам нужны методы модуля в качестве методов экземпляра в классе, включая модуль, просто используйте простые методы в модуле (а не во вложенных ClassMethods) - person Patrick Oscity; 21.10.2013
comment
Что ж, 1/ мне действительно нужны методы экземпляра, поэтому я согласен, что помещать их в ClassMethods не имеет смысла. 2/В вашем коде не используется включенный блок do, который, насколько я понимаю, является основным принципом ActiveSupport::Concern. 3/Размещение кода непосредственно внутри модуля без включения do вызывает ошибки, поскольку код оценивается во время загрузки, а не во время включения. - person muichkine; 21.10.2013
comment
Хорошо, теперь ответ на ваш вопрос довольно прост. Пожалуйста, смотрите мое редактирование. - person Patrick Oscity; 21.10.2013
comment
Хорошо я понял. Вот полный ответ для всех. Код, вставленный внутрь включения, фактически добавляется в базовый класс. Итак, если базовый класс реализует метод с той же сигнатурой, он заменяется, следовательно, суперметода действительно нет. Следует только писать во включенном коде, который требует зависимостей, таких как код ActiveRecord / MongoID. Обычные методы ruby ​​должны быть написаны так, как написал p11y: снаружи включен блок do. - person muichkine; 21.10.2013