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
Should the Gemspec be packaged with a Ruby Gem?
There is no need to pack a Gemspec with a Ruby gem, in a survey of the gems installed in one of my gem homes I noticed that in fact most gems don't include the gemspec file:
~/.rvm/gems/ruby-2.3.7/gems $ find . -name \*.gemspec | wc -l
95
~/.rvm/gems/ruby-2.3.7@happy-backend/gems $ ls | wc -l
318
Why would you want to not pack it?
- It saves a few bytes in your GEM
Why pack it?
- It allows for easy unpacking and repackaging of a gem
- Why not? the gem spec is uploaded to the gem server anyway, so there are no secrets there and if the 'user' really wants it its going to be on the
$GEM_HOME/specifications
folder
Related Topics
Overriding Model in Gem, Adding Callback and Methods
Pass Command Line Argument to Vagrant Shell Script Provisioner
Activerecord::Associationtypemismatch in Controller#Create on Dropdown Select for a Rails Self Join
Rails Cancan and State MAChine - Authorizing States
How to "Extract" Values from a Multidimensional Array in a Smart Way
Why Are My Rspec Tests Failing, But My App Is Working
Closures and for Loops in Ruby
How to Set Correct Ruby Version in Gem Environment
Rails Routing - Custom Routes for Resources
Error Building Ruby in Sublime Text Editor
Activerecord_Postgis_Adapter: Undefined Method 'Point' for Nil:Nilclass
How to Include Ё in [А-Я] Regexp Char Interval
What's Does the [5.0] in Rails 5's Activerecord::Migration Mean
Call Next on Ruby Loop from External Method
Ruby 'Range.Last' Does Not Give the Last Value. Why
When Passing Objects as Parameters, Are They Passed by Reference