Is this:
require 'bundler'
Bundler.setup
accomplishing the same as:
require 'bundler/setup'
As far as I understand, bundler/setup requires all groups automatically, while this isn't the case with require 'bundler'. So considering this fact, does that mean the above 2 snippets of code accomplish the same thing?
The answer is found in the source code of bundler/setup:
require 'bundler/shared_helpers'
if Bundler::SharedHelpers.in_bundle?
require 'bundler'
if STDOUT.tty?
begin
Bundler.setup
rescue Bundler::BundlerError => e
...
end
else
Bundler.setup
end
...
end
The method in_bundle? seems to be checking if Bundler is being run inside itself (for testing purposes, as far as I could make out), and to verify that Gemfile exists.
So yes, for general use, both of your pieces of code are equivalent.
The advantage of the bundler/setup version, is that you can run Ruby from the command line like this:
ruby -rbundler/setup ... some_ruby_script.rb
Which will automatically make your script run under Bundler, even if the script itself might not be Bundler-aware, which is pretty much the same as what bundle exec does too.
Related
This is bizarre because I am relatively certain that minitest is an independent testing framework from rspec.
In any case, what is happening is that when I run.
rspec at my rails root directory, I get this error:
Could not find minitest-4.7.5 in any of the sources
However in my Gemfile I have the following:
gem 'minitest', '~> 4.7.5'
I have tried running bundle update and bundle install to no avail. Also I feel weird even adding the gem file as I only added it after I got the error but had no intention of using the gem to begin with.
For reference here is my spec_helper.rb file.
require 'rubygems'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
Hard to know w/o more information, it's likely something else is bringing it in if you aren't... Do this:
Revert to a clean state in your repository
Remove minutest from Gemfile
Run bundle (not update)
Look in your Gemfile.lock and see what is depending upon minitest
Post the information here if the answer doesn't become clear.
You may also want re-run rails generate rspec:install, that spec_helper.rb you posted looks pretty thin.
It turns out I just needed to run bundle exec rspec to run my tests.
I have created a program that I need to run constantly. It currently lives at scripts/mailman. I start it by doing this:
sudo bundle exec rails runner script/mailman &
It seams to stop after I logout of the server. Here is the contents of my mailman program:
#!/usr/bin/env ruby
require "rubygems"
require "bundler/setup"
require "mailman"
require "rb-inotify"
Mailman.config.logger = Logger.new("/var/log/mailman.log")
Mailman.config.maildir = '/var/mail'
require File.dirname(__FILE__) + "/../../config/application"
Rails.application.require_environment!
Mailman::Application.run do
default do
begin
Bin.receive_mail(message)
end
end
end
What is a good way to start this program automatically and keep it running always? I am running this on Ubuntu.
Use the 'daemons' gem as suggested here:
Make a Ruby program a daemon?
Seems also to be very popular on RubyToolbox
https://www.ruby-toolbox.com/categories/daemonizing
I've found that the daemons gem works well for this.
Assuming your posted code lives in script/mailman.rb, you can make a file script/mailman_ctl:
#!/usr/bin/env ruby
require 'rubygems'
require 'daemons'
Daemons.run('mailman.rb')
I typically give the options {:backtrace => true, :monitor => true} to the Daemons.run call, so that I have a better idea of what happened if the process ever dies.
This is a really basic ruby gems question. I'm familiar with writing simple ruby scripts like this:
#!/usr/bin/ruby
require 'time'
t = Time.at(123)
puts t
Now I'd like to use my own ruby gem in my script. In my rails project I can simply require 'my_gem'. However this doesn't work in a stand-alone script. What's the best/proper way to use my own gem in a stand-alone ruby script?
You should be able to simply require it directly in recent versions of Ruby.
# optional, also allows you to specify version
gem 'chronic', '~>0.6'
# just require and use it
require 'chronic'
puts Chronic::VERSION # yields "0.6.7" for me
If you are still on Ruby 1.8 (which does not require RubyGems by default), you will have to explicitly put this line above your attempt to load the gem:
require 'rubygems'
Alternatively, you can invoke the Ruby interpreter with the flag -rubygems which will have the same effect.
See also:
http://docs.rubygems.org/read/chapter/3#page70
http://docs.rubygems.org/read/chapter/4
You could use something like this. It will install the gem if it's not already installed:
def load_gem(name, version=nil)
# needed if your ruby version is less than 1.9
require 'rubygems'
begin
gem name, version
rescue LoadError
version = "--version '#{version}'" unless version.nil?
system("gem install #{name} #{version}")
Gem.clear_paths
retry
end
require name
end
load_gem 'your_gem'
It is to be noted that bundler itself can deal with this. It's particularly interesting since bundler ships with Ruby by default since version 2.6, and you don't need to install it manually anymore.
The idea is:
to require bundler/inline at the top of your script,
to use the gemfile method, and declare the gems you need inside a block, like you'd do in a Gemfile,
after the end of this section, your gems are available!
For instance:
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'rainbow'
end
# From here on, rainbow is available so I can
# print colored text into my terminal
require 'rainbow'
puts Rainbow('This will be printed in red').red
The official documentation can be found on bundler website: bundler in a single file ruby script
Installing gems with something like the following should work. Be mindful of whether gems should be installed as part of system ruby or a user's.
#!/usr/bin/env ruby
require 'rubygems'
def install_gem(name, version=Gem::Requirement.default)
begin
gem name, version
rescue LoadError
print "ruby gem '#{name}' not found, " <<
"would you like to install it (y/N)? : "
answer = gets
if answer[0].downcase.include? "y"
Gem.install name, version
else
exit(1)
end
end
end
# any of the following will work...
install_gem 'activesupport'
install_gem 'activesupport', '= 4.2.5'
install_gem 'activesupport', '~> 4.2.5'
# require as normal (since not all gems install & require with same name) ...
require 'active_support/all'
...
I'm not sure if I understood your question right, but perhaps you don't have a gem, even if you write it (you are a beginner, so perhaps you misunderstood the concept of gems).
Just to be sure: You have a gemspec for your gem? If not, then you have no gem, but a single script.
When you want your own script inside another script, you may just do:
require 'my_script'
With ruby 1.8 this works fine, if my_script.rb is in the same folder as your main script. With ruby 1.9+ you can use:
require_relative 'my_script'
There is no need of a gem in this case.
I'm trying to run individual tests through ruby test/unit/mytest.rb, but I always get a "no such file to load - test_helper" error. Google brought up a few suggestions, but none of them worked for me. I'm running Rails 3.0, Ruby 1.9.2 (through RVM) on Ubuntu 10.10
Here's what I've tried so far - any suggestions really appreciated
Changed the "require test_helper" to "require File.dirname(FILE) + "/../test_helper"
" in test/unit/mytest_test.rb. It brings back " no such file to load -- test/unit/../test_helper"
Tried running rvm test/unit/mytest_test.rb Same as above
Tried running ruby -I test/unit/mytest_test.rb. No messages to the terminal. After about 5 minutes waiting for something to happen, ctrl+c'd out of it
Any suggestions very appreciated - I'm stumped.
ruby 1.9.2 removed ".", the current directory, from the load path. I have to do this to get it to work:
require 'test_helper'
and call it like:
ruby -I. unit/person_test.rb
I was fighting this thing myself today and i dislike the big require with whole path to file and stuff...
In my case it was fault of Rakefile..
so now it looks like this:
require "bundler/gem_tasks"
require "rake/testtask"
Rake::TestTask.new do |t|
t.libs << "lib"
t.libs << "test" # here is the test_helper
t.pattern = "test/**/*_test.rb"
end
task default: :test
I know its old and has answer marked accepted, but maybe this will also help someone :)
have a nice day
I've added the following to the top of my test files.
require File.expand_path("../../test_helper", __FILE__)
This restores the previous behavior and allows the call to be simply:
ruby test/unit/person_test.rb
Maybe you should run your test cases in this way:
$ rake test
There is no need to change the "require" statement from generated code if you use rake.
Tested with Ruby 1.9.3 and Rails 3.2.8
If you are creating a gem or engine, running rake test in the test dummy application directory will cause this error. Running rake test in the root of the gem will avoid this.
Rails 1.9 no longer includes the current directory in the LOAD_PATH, which causes this problem. You have a few options.
call the test with the -I option from the app dir:
ruby -I test test/functional/test_foo.rb
and use a require with no path:
require "test_helper.rb"
use a full path in the require. Either
require 'pathname'
require Pathname.new(FILE).realpath.dirname.join('/../test_helper.rb')
or
require (File.dirname(File.realdirpath(__FILE__)) + '/../test_helper.rb')
What do you do when you want to use a gem for development/testing that you don't want to force other devs to use? Right now I have
begin
require 'redgreen'
rescue LoadError
end
in test_helper.rb and no gem config, but that seems like a clumsy approach, albeit a functional one. I'd like to do something like the following:
config.gem "redgreen", :optional => true
Any other suggestions? Or should I just vendor those pretty superficial gems...?
EDIT
To be clear, I am only talking about those specific gems, like redgreen, which aren't actually used in the functional code, but only in the coding process. There is no need to vendor these at all, except to avoid the conditional require.
Gems that are specific to your development environment should be installed in your gemset or local gems, but not in the Gemfile.
A classic example is the ruby-debug-base19x which Rubymine needs for debugging. This is installed in your local gemset, but not in the Gemfile because not all coders use Rubymine.
[EDIT]
Indeed, everything is run in the context of the bundle, and outside gems are not reachable. There do exist some workarounds indeed. Most of them are dirty :)
I found a lot of good solutions in this bundler issue.
The nicest solution was to add this to your .irbrc :
# Add all gems in the global gemset to the $LOAD_PATH so they can be used even
# in places like 'rails console'.
if defined?(::Bundler)
global_gemset = ENV['GEM_PATH'].split(':').grep(/ruby.*#global/).first
if global_gemset
all_global_gem_paths = Dir.glob("#{global_gemset}/gems/*")
all_global_gem_paths.each do |p|
gem_path = "#{p}/lib"
$LOAD_PATH << gem_path
end
end
end
require 'irb/completion'
require 'rubygems'
require 'wirble'
Wirble.init
Wirble.colorize
If you then install wirble to the global gemset, it can then be found.
Original source: https://gist.github.com/794915
Hope this helps.
I answered a similar question of my own here
User-level bundler Gemfile
One way to do this is to create different environments:
group :scott do
end
Then
bundle --with-env=scott
Ok, I think I've come up with something. Basically, the idea is to only execute a secondary Gemfile when a Rails app is executing. To do this we add two things:
First, we alter the rails script a little:
# in ./script/rails
Kernel::IN_RAILS_APP = true
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'
Second, we tell bundler to pull in the secondary Gemfile if we're in a rails app and a secondary file exists:
# Gemfile
if Kernel.const_defined?(:IN_RAILS_APP)
local_gemfile = File.dirname(__FILE__) + "/Gemfile.local"
if File.exists?(local_gemfile)
puts 'using local gemfile'
self.instance_eval(Bundler.read_file(local_gemfile))
end
end
Now you can add a Gemfile.local to your project and run specific gems on a per-machine basis. bundle install works normally since the IN_RAILS_APP constant doesn't exist.
** Make sure to add Gemfile.local to your .gitignore.
In my opinions this is what environments are for. Fortunately there is also a way provided to do it with what is in your Gemfile, this is also how rails use it: groups
Pretty much use the environments the same way rails use it. Here is what you could find in your Gemfile:
group :test do
# Pretty printed test output
gem 'turn', :require => false
end
And here is what you can find in your config/application.rb
Bundler.require(:default, Rails.env) if defined?(Bundler)
All you would need to do is to change your local environment settings and the others working with you won't be affected unless they decide to. Everything gets committed and nothing gets lost.
Here some links :
http://yehudakatz.com/2010/05/09/the-how-and-why-of-bundler-groups/
http://gembundler.com/groups.html
If you want it to be optional, it's better to freeze the gem as a plugin. However, it's not a good idea to use different gems than the rest of a development team, as it creates some inconsistencies in the codebase that can be hard to track down later. I would say add it to config.gem, and just tell the other developers to do:
rake gems:install
And you're done.
This is how I tackled the same problem under Rails 3.1. In my Gemfile:
if File.exists? './tmp/eric_dev_gems'
gem 'redgreen'
gem 'awesome_print'
gem 'wirble'
gem 'wirb'
gem 'hirb'
end
Create a file in ./tmp/ (or in some folder which is in your .gitignore) of your choosing. I used eric_dev_gems. This should be ignored by git, and will only exist on your system unless one of your teammates decides he wants to create that file too.
I solved it by putting this in my gem file:
$gem_names ||= ENV['GEM_PATH'].split(':').map{|g| Dir.glob("#{g}/gems/*").map{|p|p.split('/gems/').last}}.flatten
gem 'redgreen' if $gem_names.any?{|n| n=~/redgreen/ }
That way the gem will only be used if you manually installed it on your system.
This works well but has the downside that it puts the gem name in the Gemfile.lock. This is of little consequence because the gem does not get installed with bundle install but it does make your lock file a bit messy and can cause the lock file to change a bit from one developer to the next.
If that is an issue for you another option is to keep the gemfile clean and require the gem by its full path, or you can add the path for just that gem. Like this:
$gem_paths ||= ENV['GEM_PATH'].split(':').map{|g| Dir.glob("#{g}/gems/*")}.flatten
$gem_paths.grep(/redgreen/).each {|p|$LOAD_PATH << p+'/lib'}
require 'redgreen' rescue nil