Conditional Dependency in Ruby Gemspec

Conditional ruby gem dependencies within a gemspec

To access rails version, we can use something like below (based on this answer):

require 'rubygems'

rails_gem = Gem::Specification.select {|z| z.name == "rails"}.max_by {|a| a.version}
p rails_gem.version.version
#=> "4.2.5"

Conditional Dependency in Ruby Gemspec

Yes, I would suggest a simple text requirement in spec.requirements. I would also recommend some sort of load-chaining when the gem first loads:

# in init.rb and/or rails/init.rb:
unless Object.const_defined?(:JSON)
begin
require 'json_pure'
rescue LoadError
begin
require 'json-ruby'
rescue LoadError
require 'json'
end
end
end
unless Object.const_defined?(:JSON)
raise "Could not load gem MyGem; did you install one of json_pur, json-ruby, or the C-based json library?"
end

How to create a Rails gem with conditional dependency installation

I wasn't able to really figure out the dependency injection for now. So I tried to take what @engineersmky suggested and created an install for the gems. So for right now I have this as my install generator

require 'generators/base_generator'

module MyGem
module Blueprinter
class InstallGenerator < BaseGenerator
source_root File.expand_path("../../../templates", __FILE__)

# Add blueprinter gem to gemfile after my_gem declaration and bundles the newly declared gem
def install_blueprinter
remove_other_supported_gems('ActiveModelSerializers', 'FastJsonapi')
puts 'Installing Blueprinter...'
insert_into_file('Gemfile',
"\ngem 'blueprinter'",
after: "gem 'dry_serialization', source: 'https://gem.fury.io/my_private_gems/'")
run 'bundle install'
end

def helper_include
copy_api_controller
gsub_file(API_CONTROLLER_PATH, /^\t*(include MyGem::.*)\n/, '')
puts 'Adding include statement to ApiController'
insert_into_file(API_CONTROLLER_PATH,
"\n\tinclude MyGem::Blueprinter",
after: 'class ApiController < ActionController::API'
)
end

end
end
end

Gets called with rails g my_gem::blueprinter::install
This creates an ApiController that inherits from ActionController::Base unless one already exists, inserts gem 'blueprinter' into the gemfile after my_gem's declaration, removes references to other serializer gems, then bundles to install the gem.

I like to separate my controllers into api and application to separate the concerns if I decide on a monolith app :D

Then you can use the dryed up methods that I'm creating in each file for each respective gem :D

Conditional gem dependencies

Hmm,

I believe one can code multiple dependencies because I've noticed gems which seemed to do this. But I would you advise against doing this. No matter how simple the code you are inserting here is, when you consider that the user will be loading one gem which depends on another which depends on another, even a small glitch in the logic of one piece of code or another can make the whole dependency train a nightmare.

So, I'd leave your kludge as-is. Further, I'd suggest you have a tarball that users can download as well. I've had to manually extract the code inside of gems whose configuration code wouldn't let me install them.



Related Topics



Leave a reply



Submit