Adding a gem dynamically from within a rake task - ruby

I am trying to use the mongo gem for a data migration rake task. I don't want to add it to the Gemfile for the whole project just so it can be used from this single rake task. How do I dynamically add mongo to the bundle for just that rake task?
I have tried using Bundler::Injector::inject, but then I need to bundle install. If I run that from within the task, the bundler has already initialized, so the require 'mongo' still fails. Should I do something to reload the bundler or is there actually a clean way to do this?

Add it to your Gemfile with :require => false:
gem "mongo", :require => false
This will allow bundler to install it and set up the load path, but it won't actually load the gem.
In your rake task, just require "mongo" to load it when you need it.

Related

"Rake cannot load such file" error in Sinatra app

I am building a Sinatra app and trying to use ActiveRecord. Rake is not recognizing my controller file and returning rake aborted! LoadError: cannot load such file whenever I run any rake task. Here are my gems:
source "https://rubygems.org"
ruby "2.7.2"
gem 'sinatra'
gem 'thin'
gem 'shotgun'
gem 'require_all'
gem 'activerecord'
gem 'sinatra-activerecord'
gem 'sqlite3'
gem 'rake', '~> 13.0.6'
And here's the Rakefile:
# Rakefile
require 'sinatra/activerecord/rake'
require_relative './app/test_controller.rb'
Any ideas? In the Rakefile, I've tried require_relative for ./app, /app, ../app, etc. Also, I'm on a bit of a time crunch, so if I can't sort this out quickly do I need Rake to use ActiveRecord?
TL/DR:
remove require_relative './app/test_controller.rb' from your Rakefile.
Details:
Rake is a tool that lets us define and run commands from the command line (e.g. rake db:migrate). Activerecord comes bundled with a few rake tasks (like generating a migration file, running one, dumping/loading your database schema, etc) that make it much easier to work with.
Rake tasks are just ruby, so to run a Rake task successfully it will need to load any classes/files it depends on (which is typically handled independently by each rake task). If you're going to write your own rake tasks you'll want to ensure that the tasks require the relevant files. Loading your app (or sinatra controllers) in a base Rakefile wouldn't generally be advised as it wouldn't always be needed.
The exception to this would be if you needed to load some kind of 'boot' or 'config' file in order to setup your database connections/configuration so that the activerecord rake tasks could successfully connect to your database.

rake neo4j:install[community-latest] - The `neo4j-rake_tasks` gem is no longer a dependency of the `neo4j-core` gem

I am following this instruction, "Getting Started with Neo4j and Ruby", https://neo4j.com/developer/ruby-course/.
Here is how you would setup your asset portal Rails app:
rails new asset_portal -m http://neo4jrb.io/neo4j/neo4j.rb -O
cd asset_portal
rake neo4j:install[community-latest]
rake neo4j:start
But after I run
rake neo4j:install[community-latest]
I got this note
The `neo4j-rake_tasks` gem is no longer a dependency of the `neo4j-core` gem.
If you would like to use the rake tasks, you will need to explicitly include the `neo4j-rake_tasks` gem in your project.
Please note that the `neo4j-rake_tasks` gem is only for development and test environments (NOT for production).
Be sure to require the `neo4j-rake_tasks` gem AFTER the `neo4j-core` and `neo4j` gems.
For more details see the Neo4j.rb documentation
What can I do now to make this statement, rake neo4j:install[community-latest], work?
Thanks!
only add the flowing snippet
gem 'neo4j-rake_tasks'
bundle install
Hopefully would solve your problem.
I need to add the following lines to GemFile
gem 'neo4j-core'
gem 'neo4j-rake_tasks'
And then run the commands
bundle install
rake neo4j:install[community-latest]
rake neo4j:start

Install *gem file with bundle

I try to develop a gem. I include it in my rails application through Gemfile with :path option for testing purpose, but there are some errors that appear when I build it and release to rubygems that does not appear when gem included from local path. How can I install gem from *gem file (made with rake build command) in rails or any bundle driven application for testing?
This will give you the best help: http://guides.rubygems.org/make-your-own-gem/
But in summary you need to build your gem from the .gemspec then using irb require your gem to test it out.
Example:
gem build hola.gemspec
% irb
require 'hola'
=> true

Bundler: how to use without rails?

I have a project using cucumber outside of rails. How can I load the gems with the versions specified in my gemfile?
Digging through the Bundler website:
Create Gemfile (run bundle init to create skeleton Gemfile)
bundle install
In your app:
# Only needed for ruby 1.8.x
require 'rubygems'
# The part that activates bundler in your app
require 'bundler/setup'
# require your gems as usual
require 'some_gem'
# ...or require all the gems in one statement
Bundler.require
Could be worth checking out:
Bundler.io - Using Bundler in Your Appplication
Bundler.io - Bundler.setup and Bundler.require
Are bundle exec and require 'bundler/setup' equivalent?
I just learned about a way to make Bundler automatically require dependencies from a Gemfile. Add this code at the beginning of a Ruby program that has a Gemfile:
require 'rubygems'
require 'bundler/setup'
Bundler.require
With Bundler.require there's no need to explicitly require the gems/libraries enumerated in the Gemfile.
This solution is from http://technotales.wordpress.com/2010/08/22/bundler-without-rails/
To be honest I'm not sure if the require rubygems part is needed either.
Here's the simplest and most straightforward approach:
bundler init will create the Gemfile for you
Specify gems in the Gemfile.
Add the following to your main Ruby file
require 'bundler/setup'
Bundler.require
Run bundler install to install the gems.
More information can (now) be found at http://bundler.io.
Casper has a pretty good answer (despite some passive aggressiveness) but I think the missing piece for you is bundle exec. When you run the $ rails ... commands on the command line, Rails uses bundler to load those dependencies/gems. Rake, for example, doesn't by default so in order to run rake test using an older version of cucumber than what is on your system, you have to use bundle exec rake test. It's a good habit to get into always using $ bundle exec ... when you're using Bundler — it's explicit, you're always sure you're using the right gems, and it ensures you don't forget to add a dependency to your Gemfile (i.e. you push to another server or another developer and they are having issues because you didn't note the need for something you use but they don't).

Ruby: What does 'require: false' in Gemfile mean?

Does this:
gem 'whenever', require: false
mean that the gem needs to be installed, or does it mean it is not required?
This means install the gem, but do not call require when you start Bundler. So you will need to manually call
require "whenever"
if you want to use the library.
If you were to do
gem "whenever", require: "whereever"
then bundler would download the gem named whenever, but would call
require "whereever"
This is often used if the name of library to require is different than the name of the gem.
You use :require => false when you want the gem to be installed but not "required".
So in the example you gave:
gem 'whenever', :require => false
when someone runs bundle install the whenever gem would be installed as with gem install whenever. Whenever is used to create cron jobs by running a rake task but isn't usually used from within the rails (or other framework if not rails) application.
So you can use :require => false for anything that you need to run from the command line but don't need within your code.
require: false tells Bundler.require not to require that specific gem: the gem must be required explicitly via require 'gem'.
This option does not affect:
bundle install: the gem will get installed regardless
the require search path setup by bundler.
Bundler adds things to the path when you do either of:
Bundle.setup
which is called by require bundler/setup
which is called by bundle exec
Example
Gemfile
source 'https://rubygems.org'
gem 'haml'
gem 'faker', require: false
main.rb
# Fail because we haven't done Bundler.require yet.
# bundle exec does not automatically require anything for us,
# it only puts them in the require path.
begin Haml; rescue NameError; else raise; end
begin Faker; rescue NameError; else raise; end
# The Bundler object is automatically required on `bundle exec`.
Bundler.require
Haml
# Not required because of the require: false on the Gemfile.
# THIS is what `require: false` does.
begin Faker; rescue NameError; else raise; end
# Faker is in the path because Bundle.setup is done automatically
# when we use `bundle exec`. This is not affected by `require: false`.
require 'faker'
Faker
Then the following won't raise exceptions:
bundle install --path=.bundle
bundle exec ruby main.rb
On GitHub for you to play with it.
Rails usage
As explained in the initialization tutorial, the default Rails template runs on startup:
config/boot.rb
config/application.rb
config/boot.rb contains:
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
which does the require 'bundler/setup' and sets up the require path.
config/application.rb does:
Bundler.require(:default, Rails.env)
which actually requires the gems.
Whenever you specify a Gem in your Gemfile and run bundle install, bundler will go and install specified gem and load code for that Gem in you app by putting require 'whenever' this way bundler will load code for all of your Gems in your Rails app, and you can call any method from any Gem without any pain, like you do most of the time.
but Gems like whenever, faker or capistrano are something which you do not need in your app code you need whenever code in your schedule.rb file to manage crons and capistrano code in deploy.rb file to customize deployment recipe so you need not to load code for these gems in your app code
and wherever you want to call any method from these Gems you can manually require thsese gems by yourself by putting require "whenever" . so you put :require => false in your Gemfile for these Gems, this way bundler will install that Gem but not load code for that Gem itself, you can do it whenever you want by simply putting like require 'whenever' in your case.
Analogy to Explain
## Gemfile
gem "university_degree", require: false
gem "dealing_with_boss"
"dealing_with_boss" - loaded into memory and ready to go.
degree gem - not "needed"....you need to manually require it, in order to use it.
In order to require gems in your Gemfile, you will need to call Bundler.require.
You can prevent bundler from requiring the gem with require: false, but it will still install and maintain the gem. Check this out for a more detailed explanation.

Resources