How to include a plugin/engine in a rails application? - ruby-on-rails

This is my first time interaction with a rails plugin and I'm unable to wrap my head around how this thing works. I'm going to make a rails plugin/engine. I want to include this plugin in my rails application(a different project), how can I do it? I found this which suggests to
At the root of this brand new engine's directory lives a plugin_name.gemspec file. When you include the engine into an application later on, you will do so with this line in the Rails application's Gemfile:
gem 'plugin_name', path: 'engines/plugin_name'
My question is that how exactly do I do it? I mean when I create a rails application I do not find any engines directory in the folder structure. And also which directories from the plugin project do I have to place in the engines/ directory?
I created a plugin by doing
rails plugin new plugin_name --mountable
and it generated following files/directories:
|-app/
|-bin/
|-config/
|-demo_project.gemspec
|-Gemfile
|-Gemfile.lock
|-lib/
|-MIT-LICENSE
|-Rakefile
|-README.md
|-test
|-dummy
|-(contains a rails application)
Now once I'm done with this plugin, how do I include this in another rails application? What directories do I need to put in engines/ in addition to including the plugin in the gemfile?
In addition to this I also want some info about what the following is indicating
Additionally, the --mountable option tells the generator to mount the engine inside the dummy testing application located at test/dummy by adding the following to the dummy application's routes file at test/dummy/config/routes.rb:
mount PluginName::Engine => "/plugin_name"
What does the mount point indicate and what will be it's role once the plugin is included in a rails application?

Rails engine is an isolated rails app, that is mounted inside main app. Two main reasons to create an engine are isolation of an application part (with possible intent to split the app into pieces) and code reuse (when you use same engine in several apps)
Technically it is a ruby gem, but often engines start (and live) as an isolated part of a larger app, without being completely extracted into own repository, gem publishing etc.
For example, if you have admin part of your app, you can make it an engine:
# in gemfile:
gem 'admin', path: 'engines/admin'
# routes:
mount Admin::Engine => '/admin'
# engine's routes:
resources :foo # => because of being in an engine this will be /admin/foo
directory structure can look like:
|-app/
|-bin/
|-...
|-config/
|-application.rb
|-routes.rb
|-engines/
|-admin_engine/
|-app/
|-controllers/admin/
|- foo_controller.rb
|-config/
|-routes.rb # <- this is engine's routes
|-lib/
|-admin/
|-engine.rb
|- admin.gemspec

Related

Gem shared between Rails and Sinatra applications

I'm writing a gem of my own which is shared between a Sinatra app and a Rails app.
The gem generates a logger which will write to a default location - "/log/[logger_name]" in the project root directory.
My problem is that I have no way of computing the project root directory which will be common between both apps.
Is there a way to compute the path which the project is running from, regardless of if it's a Rails or Sinatra app? Is there an elegant way to solve it without using a regex?
Since both Rails and Sinatra are based on Rack, I would try to get the project root directory with Rack::Directory.new('').root and join it with logger file's relative path.
project_root = Rack::Directory.new('').root
logger_path = Pathname.new(project_root).join('log/production.log')

Ember Engines inside Rails Engines via ember-cli-rails

We have a high modular rails5 app, which is splitted in rails engines over serveral repositories and integrated as ruby gems.
Now we want to introduce EmberJS by using ember-cli-rails. The main rails application contains the main ember application in the frontend directory while each of the rails engines contain an ember engine (via ember-engine) in a frontend directory.
How to mount the ember engines of the modules into the main ember engine?
Due the fact that I've found no other solution so far, I've created an initializer which symlinks the ember engine directories of all rails engines into the node_modules of the consuming ember engine in the consuming rails app:
# Get the node_modules dir
nm_dir = Rails.root.join('frontend', 'node_modules')
# Delete existing symlinks
Dir.new(nm_dir.to_s).each { |entry| FileUtils.rm_rf(entry) if entry =~ /^.+\-frontend$/ }
# MODULES contains an array of the rails engine gem names
MODULES.each do |module_name|
# Each module has a Manifest class, load that
manifest = load_manifest(module_name)
# Get the path to the frontend dir of the rails engine
source = Pathname.new(manifest.method(:setup).source_location[0].split('/lib/')[0]).join('frontend').to_s
# Symlink destination
destination = nm_dir.join("#{module_name}-frontend").to_s
# Symlink it
FileUtils.symlink source, destination, force: true
end
This approach is probably not very clean, but it seems to work.

Where to put source files for a Sinatra app mounted within a Rails app

I have a standalone Sinatra app with its complete directory structure, and I have a Rails app with its own directory structure. I want to mount the Sinatra app within my Rails app by adding a mount statement in my routes file.
Where should I put the source files for my Sinatra app within my Rails directory structure to follow "best practices"? Ideally, I would want to preserve the directory structure for my Sinatra app and all its layouts, etc.
There is really no specific place. I'd put it in /lib. You can also place it in its own folder in /app, but /app has special reloading and autoloading rules.
You can place it in /lib, require the Sinatra app and mount it in the routes.rb file.

Where should I save standalone non-ruby scripts in my Rails app?

This is a simple question, but I haven't been able to find an exact answer to it anywhere.
I have a standalone Python script which I am using in my Rails app. What is the appropriate folder I should save it in according to convention, so that I can push it to production (currently running it from my computer's desktop)? I think the answer is lib/assets but I want to make sure.
I don't think there is an exact answer for this question.
If it is a ruby script, it is usually placed in lib or bin.
From the rails folder descriptions in Getting Started with Rails guide:
bin/ Contains the rails script that starts your app and can contain
other scripts you use to setup, deploy or run your application.
lib/ Extended modules for your application.
You could put it in lib/assets folder as it reflects your understanding that it is an external asset used in the system.

Run engine RSpec/Cucumber tests in the client app

I have mountable rails engine Users:
users/
...
features/
...
specs/
dummy/
controllers/
models/
factories/
...
I have a client app MySite, which uses the Users engine:
my_site/
app/
...
features/
...
specs/
controllers/
models/
factories/
...
Gemfile
Gemfile:
gem "users", git: "..."
Is it possible to run engine rspec/cucumber tests in the MySite app instead of the mock?
If so, what is the best way?
You should not do this for two reasons:
The User engine is its own project. It should work in isolation in a certain way. Adding these tests to any project the User engine is included in does not make sense. Why not run all the specs of all the gems you include in your project as well?
If you have specific acceptance criteria for your application, add cucumbers for that to your project. That way, if you decide to ditch the User engine in the future with something else, you can still verify your application behaving as expected. If you'd included the cucumbers from the engine, then those criteria would have been lost as well.

Resources