Помощните методи за монтирани на релси двигатели не са намерени при маршрутизиране от основното приложение

Имам модул като монтируем двигател, монтиран към основно приложение чрез

mount MyEngine::Engine, :at => '/myengine'

Имам всичко в пространството на имената в negine и двигателят има свои собствени изгледи в engine/app/views/myengine/

Всичко работи добре, когато стартирам rails сървър и след това се опитам да осъществя достъп

localhost:3000/myengine

първо, след това отидете в корена на основното приложение и се върнете към двигателя чрез връзка в индексния изглед на основното приложение

Въпреки това, когато стартирам сървъра, отида на localhost:3000 и оттам щракнете върху връзката към модула на двигателя, той се опитва да извлече правилно изгледите, но методите, съдържащи се в помощниците на двигателя, предизвикват грешка при извикване, тъй като те са недефинирани.

На релси съм 4


person Ahmadposten    schedule 23.06.2015    source източник


Отговори (3)


Използвах eager_load, за да заредя монтируемия двигател, той е инициализиран в основното приложение и сега всичко изглежда работи.

Myengine::Engine.eager_load!

person Ahmadposten    schedule 13.08.2015

И аз се натъкнах на този проблем. Бях дефинирал ApplicationController в моя двигател и виждах NoMethodErrors, когато се опитах да използвам помощни методи в един от контролерите на моя двигател.

Проблемът

Кодът изглеждаше нещо подобно:

в my_engine/app/controllers/my_engine/application_controller.rb

module MyEngine
  class ApplicationController < ActionController::Base
    helper ApplicationHelper
  end
end

в my_engine/app/controllers/my_engine/projects_controller.rb

module MyEngine
  class ProjectsController < ApplicationController
    def new
      # some action code here
    end
  end
end

в my_engine/app/helpers/my_engine/application_helper.rb

module MyEngine
  module ApplicationHelper
    def translations_include_tag
      javascript_include_tag "translations-#{I18n.locale}.js"
    end
  end
end

Ако отида до маршрут в приложението за хост релси, след което щракна върху връзка, която води до my_engine/projects/new, ще получа NoMethodError, че translations_include_tag не съществува.

Обяснението

Мисля, че това се случваше, защото приложението имаше два класа с едно и също име: ApplicationController в MyEngine и ApplicationController в хост приложението. Когато се посети първият маршрут извън двигателя, Rails автоматично зарежда ApplicationController от хост приложението. Това означава, че Rails свързва ApplicationController на основното приложение с името "ApplicationController". Когато навигирате до my_engine/projects/new, Rails зарежда лениво ProjectsController, което също наследява от ApplicationController. Rails/ruby смята, че имате предвид същия ApplicationController, който вече е заредил, така че в действителност ProjectsController в крайна сметка наследява от ApplicationController на хост приложението вместо този в двигателя. Тъй като методът translations_include_tag не е дефиниран в ApplicationController на хост приложението, ruby ​​повдига NoMethodError, когато изгледът се опитва да го извика.

Решението

Успях да коригирам проблема, като изрично наследих от ApplicationController на MyEngine:

в my_engine/app/controllers/my_engine/projects_controller.rb

module MyEngine
  # changed from just plain 'ol ApplicationController
  class ProjectsController < ::MyEngine::ApplicationController
    def new
      # some action code here
    end
  end
end

След коригиране на проблема с наследяването, NoMethodError изчезна.

Приетият отговор казва да се използва нетърпеливо зареждане, което също ще реши проблема, защото принуждава ApplicationController на двигателя да се зарежда първо. Тъй като ApplicationController на двигателя е с пространство от имена вътре в MyEngine, пълното му име е MyEngine::ApplicationController, което не е в конфликт с ApplicationController на основното приложение, тъй като имената на константите са различни.

person Cameron    schedule 11.02.2019

Трябва изрично да включите помощниците във вашия lib/engine.rb файл:

initializer 'your-gem-name.setup_helpers' do |app|
    app.config.to_prepare do
      ActionController::Base.send :include, HelperModuleName
    end
  end
end
person Yury Lebedev    schedule 23.06.2015
comment
Същият проблем, бих искал също да подчертая, че проблемът възниква само когато се опитам да осъществя достъп до модула след първи достъп до основното приложение, но когато първо осъществя достъп до модула, след това всичко изглежда нормално и мога да навигирам правилно. - person Ahmadposten; 23.06.2015
comment
има ли шанс във вашето приложение да има модул със същото име? - person Yury Lebedev; 23.06.2015
comment
не, няма друг модул със същото или близко до него име - person Ahmadposten; 23.06.2015