Рейки 3.1: Додаток двигуна проти монтажу


120

Чи може хтось допомогти мені зрозуміти відмінності між Rails Engine та програмою Mountable? У Rails 3.1 ви можете створити будь-який із командою "rails new plugin _ __ ".

rails plugin new forum --full        # Engine
rails plugin new forum --mountable   # Mountable App

Коли ви хочете використовувати один проти іншого? Я знаю, ви можете упакувати Двигун як дорогоцінний камінь, для одного. Хіба це не так для гірських додатків? Які ще існують відмінності?

Відповіді:


143

Я помітив таке:

Повний двигун

З повноцінним двигуном батьківська програма успадковує маршрути від двигуна. Не потрібно нічого вказувати parent_app/config/routes.rb. Вказання дорогоцінного каміння в Gemfile достатньо, щоб батьківське додаток успадкувало моделі, маршрути тощо. Маршрути двигуна вказані як:

# my_engine/config/routes.rb 
Rails.application.routes.draw do 
  # whatever 
end 

Немає простору імен моделей, контролерів тощо. Вони одразу доступні батьківській програмі.

Монтажний двигун

Простір імен двигуна за замовчуванням виділено:

# my_engine/lib/my_engine/engine.rb
module MyEngine 
  class Engine < Rails::Engine 
    isolate_namespace MyEngine 
  end 
end

За допомогою монтируемого двигуна маршрути мають простір імен, і батьківська програма може поєднати цю функціональність за одним маршрутом:

# my_engine/config/routes.rb 
MyEngine::Engine.routes.draw do 
  #whatever 
end 

# parent_app/config/routes.rb 
ParentApp::Application.routes.draw do 
    mount MyEngine::Engine => "/engine", :as => "namespaced" 
end 

Моделі, контролери та ін. Ізольовані від батьківського додатку, хоча помічники можуть бути спільними.

Це основні відмінності, які я помітив. Можливо, є й інші? Я просив сюди , але ще не отримав відповіді.

Моє враження, що оскільки повноцінний двигун не ізолює себе від батьківського додатка, його найкраще використовувати як окремий додаток, що прилягає до батьківського додатку. Я вважаю, можуть трапитися сутички з іменами.

Вбудований двигун може використовуватися в ситуаціях, коли ви хочете уникнути конфліктів імен і згрупувати двигун за одним певним маршрутом у батьківській програмі. Наприклад, я працюю над створенням свого першого двигуна, призначеного для обслуговування клієнтів. Батьківська програма може поєднати її функціональність під одним маршрутом, наприклад:

mount Cornerstone::Engine => "/cornerstone", :as => "help" 

Якщо я не буду в своїх припущеннях, хтось, будь ласка, дасть мені знати, і я виправлю цю відповідь. Я зробив невелику статтю на цю тему тут Ура!


1
Чи можна монтувати моторний двигун будь-коли на маршрутизованому / встановленому в корені батьківського додатку?
Slick23

3
@JustinM ви можете спробувати mount MyEngine::Engine => "/". Це працює на ресурси, можливо, це стосується і двигунів.
Бенуа Гаррет

2
@astjohn Чудовий підсумок ваших блогів. Але хіба не було б навпаки? Буде повний двигун "неповним" і потрібен батьківський додаток для роботи, тоді як гірський двигун може працювати автономно, оскільки він "ізольований" від батьківського додатка?
Тео Шоліадіс

39

Обидва варіанти генерують двигун . Різниця полягає в тому --mountable, що створить двигун в ізольованому просторі імен, тоді як--full створить двигун, який розділяє простір імен основного додатка.

Відмінності проявлятимуться трьома способами:

1) Файл класу двигунів викликає isolate_namespace:

lib / my_full_engine / engine.rb:

module MyFullEngine
  class Engine < Rails::Engine
  end
end

lib / my_mountable_engine / engine.rb:

module MyMountableEngine
  class Engine < Rails::Engine
    isolate_namespace MyMountableEngine # --mountable option inserted this line
  end
end

2) Файл двигуна config/routes.rbбуде простір імен:

Повний двигун:

Rails.application.routes.draw do
end

Встановлений двигун:

MyMountableEngine::Engine.routes.draw do
end

3) Структура файлів для контролерів, помічників, представлень та ресурсів буде розділена на імена:

створити додаток / контролери / my_mountable_engine /application_controller.rb
створити додаток / помічники / my_mountable_engine /application_helper.rb
створити додаток / пошти створити додаток / моделі
створити додаток / види / макети / my_mountable_engine /application.html.erb
створити додаток / активи / образи / my_mountable_gine
створити додаток / активи / таблиці стилів / my_mountable_engine /application.css
створити додаток / активи / javascripts / my_mountable_engine /application.js
створити config / routes.rb створити lib / my_mountable_engine.rb
створити lib / task / my_mountable_engine.rake
створити lib / my_mountable .rb
створити lib / my_mountable_engine / engine.rb


Пояснення

Вигляд використання --fullопції, здається, дуже обмежений. Особисто я не можу придумати жодної вагомої причини, чому ви хочете відокремити свій код в двигуні, не виділяючи простору імен. Це, по суті, просто дасть вам два щільно поєднані програми, що обмінюються однаковими файловими структурами та всі конфлікти та витоки коду. що тягне за собою.

Кожна частина документації , яку я бачив демонструє --mountableваріант, і на самому справі поточний керівництво краю настійно рекомендує вам включити isolate namespace- що те ж саме , як кажуть використання --mountableбільш --full.

Нарешті, є термінологічна плутанина: На жаль, rails plugin -hпоказано такі описи:

[--фул] # Створіть рельсовий двигун із доданим пакетом Rails для тестування
[--mountable] # Створення ізольованого додатка, що монтується

Це створює враження, що ви використовуєте --fullдля створення "двигуна" та --mountableдля створення ще чогось, що називається "монтується додаток", адже насправді вони обидва двигуна - один з просторами імен, а один - ні. Це неодмінно призведе до плутанини, оскільки користувачі, які прагнуть створити двигун, ймовірно, припускають, що --fullце більш релевантний варіант.

Висновок

  • rails plugin new something --full= Двигун у просторі імен додатка. (Чому б ти?)
  • rails plugin new something --mountable= Двигун із власним простором імен. (Awesome)

Список літератури


9
Є одна вагома причина для використання --full: якщо у вас є частини веб-сайту рейок, ви хочете бути інтегрованими (не в ізольованому просторі імен) і все ще ділитися між різними проектами рейок. Крім того, це може бути і простіше, ніж це: можливо, ваш дорогоцінний камінь не так багато додає, але ви хочете вміти підключити його правильно.
nathanvda

2
@nathanvda - Правильно, але я думаю, що якщо ви ділитесь чимось у кількох проектах, це дійсно має бути просторовим, оскільки ви в основному використовуєте це як плагін
Yarin

Я думаю, ви можете скористатися - повністю, якщо ви хочете ізолювати ваші файли, простір імен для ваших сайтів викликів, коли ви це робите, Admin::AdminService.some_actionале не потрібно змінювати маршрути, якщо інші додатки на стороні клієнта, наприклад програма Ember, використовують маршрути, пов’язані з кодом, який ви хочуть ізолювати. - Повністю здається проміжним кроком, який може бути легше здійснити.
Jwan622

Зараз я працюю над міжнародною програмою, яка повинна керуватися специфічними для кожної країни нормами, але все ж відкриває той же інтерфейс у світі. У мене є один екземпляр "Core" для кожної країни, не потрібно обробляти все відразу. "Двигуни країни" не мають сенсу самостійно, тому зв'язок із "основним" додатком не є проблемою. Однак я не хочу, щоб вони знаходилися у власному просторі імен, оскільки основна програма не повинна знати, у якій країні вона працює. Я відчуваю, що "повноцінний" механізм - це більше схоже на те, щоб організовувати свої файли та заняття модульним способом, але все одно зберігати "моноліт" на місці.
Манкалас

17

мені було цікаво те саме і, отже, опинився тут. мені здається, що попередні відповіді в основному охоплюють питання, але я вважав, що також може допомогти наступне:

# generate plugins (NOTE: using same name each time to minimize differences)
# -----------------------------------------------------------------------------

$ rails plugin new test-plugin -T
$ mv test-plugin{,.01}

$ rails plugin new test-plugin -T --mountable
$ mv test-plugin{,.02}

$ rails plugin new test-plugin -T --full
$ mv test-plugin{,.03}

$ rails plugin new test-plugin -T --full --mountable
$ mv test-plugin{,.04}




# compare "stock" (01) with "mountable" (02)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.01 test-plugin.02

Only in test-plugin.02: app
Only in test-plugin.02: config
Only in test-plugin.02/lib/test-plugin: engine.rb
diff -r test-plugin.01/lib/test-plugin.rb test-plugin.02/lib/test-plugin.rb
0a1,2
> require "test-plugin/engine"
> 
Only in test-plugin.02: script
diff -r test-plugin.01/test-plugin.gemspec test-plugin.02/test-plugin.gemspec
18a19
>   # s.add_dependency "jquery-rails"




# compare "stock" (01) with "full" (03)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.01 test-plugin.03
Only in test-plugin.03: app
Only in test-plugin.03: config
Only in test-plugin.03/lib/test-plugin: engine.rb
diff -r test-plugin.01/lib/test-plugin.rb test-plugin.03/lib/test-plugin.rb
0a1,2
> require "test-plugin/engine"
> 
Only in test-plugin.03: script
diff -r test-plugin.01/test-plugin.gemspec test-plugin.03/test-plugin.gemspec
18a19
>   # s.add_dependency "jquery-rails"




# compare "mountable" (02) with "full" (03)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.02 test-plugin.03

Only in test-plugin.03/app/assets/javascripts/test-plugin: .gitkeep
Only in test-plugin.02/app/assets/javascripts/test-plugin: application.js
Only in test-plugin.03/app/assets/stylesheets/test-plugin: .gitkeep
Only in test-plugin.02/app/assets/stylesheets/test-plugin: application.css
Only in test-plugin.03/app/controllers: .gitkeep
Only in test-plugin.02/app/controllers: test-plugin
Only in test-plugin.03/app/helpers: .gitkeep
Only in test-plugin.02/app/helpers: test-plugin
Only in test-plugin.03/app/mailers: .gitkeep
Only in test-plugin.03/app/models: .gitkeep
Only in test-plugin.03/app/views: .gitkeep
Only in test-plugin.02/app/views: layouts
diff -r test-plugin.02/config/routes.rb test-plugin.03/config/routes.rb
1c1
< TestPlugin::Engine.routes.draw do
---
> Rails.application.routes.draw do
diff -r test-plugin.02/lib/test-plugin/engine.rb test-plugin.03/lib/test-plugin/engine.rb
3d2
<     isolate_namespace TestPlugin




# compare "mountable" (02) with "full & mountable" (04)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.02 test-plugin.04

<no difference>




# compare "full" (03) with "full & mountable" (04)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.03 test-plugin.04

Only in test-plugin.03/app/assets/javascripts/test-plugin: .gitkeep
Only in test-plugin.04/app/assets/javascripts/test-plugin: application.js
Only in test-plugin.03/app/assets/stylesheets/test-plugin: .gitkeep
Only in test-plugin.04/app/assets/stylesheets/test-plugin: application.css
Only in test-plugin.03/app/controllers: .gitkeep
Only in test-plugin.04/app/controllers: test-plugin
Only in test-plugin.03/app/helpers: .gitkeep
Only in test-plugin.04/app/helpers: test-plugin
Only in test-plugin.03/app/mailers: .gitkeep
Only in test-plugin.03/app/models: .gitkeep
Only in test-plugin.03/app/views: .gitkeep
Only in test-plugin.04/app/views: layouts
diff -r test-plugin.03/config/routes.rb test-plugin.04/config/routes.rb
1c1
< Rails.application.routes.draw do
---
> TestPlugin::Engine.routes.draw do
diff -r test-plugin.03/lib/test-plugin/engine.rb test-plugin.04/lib/test-plugin/engine.rb
2a3
>     isolate_namespace TestPlugin

особливий інтерес (для мене) викликає той факт, що різниці між ними немає

rails plugin new test-plugin -T --mountable

і

rails plugin new test-plugin -T --full --mountable

Може, це тому, що --fullмає перевагу над --mountable?
Манкалас

8

Я розумію різницю в тому, що двигуни схожі на плагіни та додають функціональність існуючим програмам. Хоча програми для монтажу по суті є додатком, і вони можуть стояти окремо.

Отже, якщо ви хочете мати можливість запустити його самостійно або в іншому додатку, ви зробите додаток, який можна встановити. Якщо ви маєте намір зробити це доповненням до існуючих додатків, але не запущеним самим, ви зробите це двигуном.


2

Я вважаю, що різниця полягає в тому, що додаткове програмне забезпечення є ізольованим від хост-програми, тому вони не можуть ділитися класами - моделями, помічниками тощо. Це пов’язано з тим, що додаток Mountable є кінцевою точкою Rack (тобто додатком Rack сам по собі ).

Відмова: Я, як і більшість, тільки що почав грати з Rails 3.1.


Домовились. Одне, що здається дивним, це те, що за замовчуванням двигун надає папку "моделі", але додаток Mountable це не робить. Цікаво, чи "найкращою практикою" було б мати генератори, які створюють моделі для додатка, в тому числі, оскільки, здається, ви не хотіли б мати будь-яких міграцій у двигуні / монтувати
Jeremy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.