engems icon indicating copy to clipboard operation
engems copied to clipboard

Question about runtime dependencies inside engines .gemspec file

Open luccasmaso opened this issue 3 years ago • 3 comments

Hi,

The first step I'm trying to accomplish for now is just to have runtime dependencies shared by engines to be in one place. In order to do that, I've created a /gemfiles folder at root with *.gemfiles and then including them with eval_gemfile inside engines.

# gemfiles/http.gemfile

gem 'rest-client', '2.1.0'
# engines/authentication/Gemfile

source 'https://rubygems.org'

eval_gemfile '../../gemfiles/rails.gemfile'
eval_gemfile '../../gemfiles/http.gemfile'
...

The problem is that I need to require the rest-client at engines/authentication/lib/authentication.rb to make it available inside engine runtime:

require "authentication/version"
require "authentication/engine"

require "rest-client"

module Authentication
   ....
end

But, to make this work, I must define rest-client inside engine's .gemspec (spec.add_dependency). But if I do that, it looses the purpose of the eval_gemfile for sharing versions.

Sorry if I'm misunderstanding the concept.

Thanks.

luccasmaso avatar Mar 02 '21 04:03 luccasmaso

I must define rest-client inside engine's .gemspec (spec.add_dependency). But if I do that, it looses the purpose of the eval_gemfile for sharing versions.

.gemspec is for requirements, not freezing versions; you may have a relaxed spec for rest-client in your .gemspec (e.g., ~> 2.0).

Do you use the shared lock file strategy?

palkan avatar Mar 02 '21 11:03 palkan

Hi, sorry about long time since I've posted this.

.gemspec is for requirements, not freezing versions; you may have a relaxed spec for rest-client in your .gemspec (e.g., ~> 2.0).

Right, I've now properly set dependencies with the shared lock file strategy. The application now starts and everything loads as expected!

The only issue I've struggling to resolve/understand is around testing (with rspec). I'm using the latest script version that you've updated from @maiksimov sample repo. As far as I undertood, each component declared in the root Gemfile with:

component 'my_component', namespace: "engines"

will dynamically create a group (group component_group do) with it's name. That way, dummy app from engine should be able to load only dependencies related by configuring Bundler.require(:my_component) inside /config/application.rb

The error I'm getting when running rspec command from engine is that I can't figure out the cause. If I run with *Rails.groups it loads everything but works.

Screenshot 2021-03-22 at 22 22 01

Some things I didn't understand, that can be related:

  • Why it has eval_gemfile and gem declarations in first two lines? https://github.com/palkan/test-rails-project/blob/main/engines/test-engine/Gemfile.dev
  • Everytime I run rspec, a Gemfile.lock is generated inside the engine (I've configured /.bundle/config)

Appreciate with any help!

luccasmaso avatar Mar 23 '21 01:03 luccasmaso

Why it has eval_gemfile and gem declarations in first two lines?

The first one defines where to find local deps; the second uses .gemspec to get the dependencies. Without the first line, Bundler wouldn't know how to satisfy local deps.

Everytime I run rspec, a Gemfile.lock is generated inside the engine (I've configured /.bundle/config)

Do you run it with bundle exec?

The error I'm getting when running rspec command

This error doesn't seem to relevant; it looks like spec_helper.rb (or rails_helper.rb) is loaded twice 'cause Rails app to be initialized twice, which leads to this exception.

Try to wrap require "<...>/environment" with begin; rescue; exit; end to see the actual error (see https://github.com/palkan/engems/blob/6b824b182676dedc10ba88ea3aa5764e36f40e14/examples/generators/engine/templates/spec/rails_helper.rb.tt#L15-L37).

palkan avatar Mar 25 '21 11:03 palkan