How do I set RSpec to an earlier version? - ruby

Is there a way to use an earlier version of RSpec without uninstalling the default version? If not, what's the safest way to replace the current version? The uninstall/reinstall instructions linked to in this SO answer seem to be gone.
I'm trying to learn testing with RSpec, and all the tutorials I've found seem to predate 3.0. I invariably get deprecation warnings (if I'm lucky) or errors when using their old expectation syntax. I've relied heavily on this article to set me straight, but the time I spend updating the syntax in the tutorials' examples keeps me from concentrating on the substance of the lessons.
The same SO answer I linked to mentioned a config option in Rails' environment.rb file, but I'm not using Rails for the current tutorial, just Ruby and (eventually) Sinatra. I'm wondering if I can just add that file to be project folder.
I did add a Gemfile with the RSpec 2.1:
source 'https://rubygems.org'
gem 'rspec', '~> 2.10.0'
gem 'guard'
gem 'guard-rspec'
gem 'terminal-notifier'
gem 'terminal-notifier-guard'
The 2.1 installed after running bundle install, but after running bundle exec init and running my specs with the old syntax, I still get the same deprecation warnings and errors.

Related

Ruby - Digest::Digest is deprecated; Use Digest

I've been getting this warning whenever I run my tests or start rails server.
When I run grep from .rvm folder I see the following:
grep -R 'Digest::Digest' .
./rubies/ruby-2.1.0/lib/ruby/2.1.0/openssl/digest.rb: warn('Digest::Digest is deprecated; Use Digest')
- additional references to openssl and ruby 2.1.0
So it looks like it's a Ruby 2.1.0 bug. Are there any fixes? There are no patches available yet as far as I can tell.
Whilst my app uses Fog and a bunch of other gems that have issues relating to this message, I'm using patched versions that don't have the bug. So I reckon Ruby is at fault here.
Borrowing the reply from this thread
OpenSSL::Digest::Digest has been discouraged to use from very ancient era such as Ruby 1.8 and finally was deprecated recently.
If you search for the error message, you will see that a lot of gems, including fog, were still using the deprecated syntax.
I assume it will take a while before all the gems will be updated. If you came across the deprecation in one of the libs you use, I encourage you to report it to the maintainer.
Here's a few examples
https://github.com/fog/fog/pull/2473
https://github.com/alexreisner/geocoder/pull/580
https://github.com/ruby/ruby/pull/446
It's likely your Rails app depends on a gem that is using that old syntax.
If you're using bundler, a good way to find out what is causing the problem is to grep through all the gems defined in your Gemfile:
# grep (ack or ag) the problem code
bundle show --paths | xargs grep -r Digest::Digest
# here was my output
~/.gem/ruby/2.1.0/gems/fog-1.15.0/lib/fog/cloudstack.rb: ##digest = OpenSSL::Digest::Digest.new('sha1')
~/.gem/ruby/2.1.0/gems/fog-1.15.0/lib/fog/core/hmac.rb: #digest = OpenSSL::Digest::Digest.new('sha1')
~/.gem/ruby/2.1.0/gems/fog-1.15.0/lib/fog/core/hmac.rb: #digest = OpenSSL::Digest::Digest.new('sha256')
# update appropriate gems (in my case fog)
gem install fog
bundle update fog
Also make sure you aren't locked on a gem version in your Gemfile.
# change
gem 'fog', '~> 1.15.0'
# to
gem 'fog', '~> 1.0'
# or omit the version if you are a cowboy/girl
Use OpenSSL::Digest instead of deprecated OpenSSL::Digest::Digest

ruby gem statement - what does it do?

I think I have a basic understanding of what require/include statements at the top of a ruby script are doing, like
require 'rspec'
These statements are easy to google and find relevant results. But sometimes I have seen a gem statement like
gem 'rspec'
What does this line do?
In ruby code, gem(gem_name, *requirements) defined in Kernel tells Ruby to load a specific version of gem_name. That's useful when you have installed more than one version of the same gem.
For example, if you have installed two versions of rspec, say 2.12.0 and 2.13.0, you can call gem before require to use specific version. Note that gem should come before the require call.
gem 'rspec', '=2.12.0'
require 'rspec'
A gem 'gem_name' without version uses the latest version on your machine, and that's unnecessary. You can call require without gem to get the same behavior.
And besides, in Bundler::Dsl, gem is used to tell bundler to prepare/install specific version of ruby gems. You'll see that in Gemfile
The original behaviour of require, before Rubygems, was to search all the directories listed in the $LOAD_FILES variable for the file, and to load the first one it finds that matches. If no matching file was found, require would raise a LoadError.
Rubygems changes this process. With Rubygems, require will search the existing $LOAD_PATH as before, but if there is no matching file found then Rubygems will search the installed gems on your machine for a match. If a gem is found that contains a matching file, that gem is activated, and then the $LOAD_PATH search is repeated. The main effect of activating a gem is that the gems lib directory is added to your load path. In this way the second search of the load path will find the file being required.
Normally this will mean that the latest version of a gem that you have installed gets activated. Sometimes you will want to use a different version of a gem, and to do that you can use the gem method. The gem method activates a gem, and you can specify the version you want, but doesn’t require any files. When you later require the files you want, you’ll get them from the gem version you specified.
In Ruby, gems are packages with functionality that can be used out of the box (as libraries in other Programming languages).
The gems that you use with your Ruby Project can easily be managed with a tool called "bundler", just google it. The snippet of code you posted is part of the spec file that bundler uses to install and update all the libraries that you specify for your project.
If you are developing a Ruby on Rails, using gems an managing them with bundler is very common and so to say best practice.
Gems are just great because there are so many useful libraries that extend default functionality, eg of rails, and that you can use out of the box!
For a list of gems, visit rubygems.org

Bundler, when attempting to update or install, will hang forever

When attempting to run bundle install or bundle update, bundler will perpetually hang, and not complete its function. The only time that it will finish is when I specify a gem to update.
For example:
bundle update
Will hang forever unless I use it like this:
bundle update activerecord
Then it will complete as normal.
Any assistance would be appreciated.
This problem is due to a missing dependency, or worse a dependency-of-a-dependency. It's common when you don't use rubygems.org as your gemserver (an enterprise environment).
Common patterns:
You don't have that gem installed
You don't have the dependencies of that gem installed
You don't have that gem installed without its dependencies
Easiest Technique
create a new gemset, and re-bundle. This fixes the problem many times.
If you can't do that for production reasons, and you don't have an app history from which to reflect on when the problem gem was added, then:
Easier Technique
Having learned a bit since writing this answer, I thought I'd pass on this excellent article for how to run bundler with verbose debug output
export DEBUG_RESOLVER=1
bundle 2> debug_output.txt 1> stdio.txt &
This will dump all the debugging (err) output to debug_output.txt and the normal screen stuff to stdio.txt.
You'll want to dump 1> as well because every time bundler dumps a line to 2(stderr) it will put a crlf into 1. So Either dump 1 or background the job. I do both so I can work in the same terminal.
I usually follow it up with:
tail stdio.txt
to be sure things have started, then:
tail -n 10000 -f debug_output.txt
To search with /FAIL] through the file for failed attempts to install a dependency. Find a couple of them that are the same and you've generally located your culprit. The stderr works for bundle install or bundle update.
Debug Your Private Gemserver Technique
I needed to use this process-of-elimination method to determine that my (enterprise) gemserver index had become corrupted
comment out all gems
run bundle update to confirm the empty-set works
un-comment one gem and bundle update
GOTO 3 until you hit the problem
research its dependencies
When you are done
Unset the ENV var with
unset DEBUG_RESOLVER
You can try the --verbose flag too to get more output, but it's really archaic and not very helpful. Really the only way to do this from what I can see is:
Uncomment one gem at a time until it stops working, then try to figure out what the heck is going.
Remove version enforcement one gem at a time (if any) to see if that fixes it.
Remove the offending gem if you can (use a different gem) or lock in versions that do work.
For me, after running:
sudo bundle update --verbose
it kept hanging here:
Query Gemcutter Dependency Endpoint API: tenderlove-frex
Fetching from: http://rubygems.org/api/v1/dependencies?gems=tenderlove-frex
HTTP Success
Query List: []
Not at all helpful. I ended up figuring out that the conflict was between two gems. The following would hang forever:
source 'http://rubygems.org'
gem 'rails', '~> 3'
gem 'airbrake'
I removed the rails version:
source 'http://rubygems.org'
gem 'rails'
gem 'airbrake'
Then it worked, but I noticed in my Gemfile.lock that it was using Rails 2.3.X. So airbrake seemed to be dependent on Rails 2, but I wanted 3. I couldn't find anywhere that airbrake had this Rails 2.x dependency so not sure why it ended up like that. Why bundler can't output something more meaningful is beyond me.
This worked though:
source 'http://rubygems.org'
gem 'rails', '~> 3'
gem 'airbrake', '~> 3'
I really think there is something wrong with Bundler, but not sure.
Bundler may not be hanging. I just experienced a 7 minute time to bundle a relatively small Gemfile, and that is on the fastest possible SSD Macbook Pro with a 50 Gb download connection.
When deploying onto AWS instances, be sure your security group allows outbound HTTP and/or HTTPS connections - I encountered this problem because I had restricted the security group too much.

How to create a new Ruby gem?

To create a new Ruby gem, should I use Jeweler or should I use Bundler's built-in gem skeleton to create a base gem? What are the differences that matter?
Use Bundler
From the command line:
bundle gem your_new_gem
This will create a directory called your_new_gem with just a basic set of files and directory structure that are now considered best-practice. It's quick, easy, and a great place to start.
Creating a Gem isn't that difficult and I would advise to try building a gem from scratch, without any tools. After you know what's involved (creating a gemspec, building and pushing it to rubygems.org), you can use tools to speed up the process. My guess is you won't because making a gem is hardly the trouble at all.
I would go with Jeweler. The Bundler skeleton is only going to give you the basics. Jeweler has alot more options to work with and many helpful rake tasks for versioning, pushing to github, creating the gemspec, building and installing.
If you are working with Rails 3 engines, I have a Jeweler fork (definitely a work-in-progress) that will generate the app skelaton and include the engine file. You just have to run the jeweler command with --rails3-engine as an option. Here is the fork if you are interested:
https://github.com/johnmcaliley/jeweler
I would recommend using the built-in bundler command.
bundle gem your_gem_name
There are some rules that you should follow when creating a gem. Such as naming conventions and versioning rules.
I recently wrote a post on creating gems in netguru's blog. I think you'll find what you need in there.
https://netguru.co/blog/posts/creating-a-gem-a-step-by-step-tutorial
Hope this helps.
Here's an alternative that's worth looking at: ore
Bundler gives you a single template for ruby gems, whereas ore has multiple built in templates, plus the ability to create your own. It also supports Git, SVN (urgh) and Mercurial.
You can build a gem in RubyMine too. File > New Project > New Gem. It is that easy. But I want to make some notes about this approach:
For debugging, RubyMine will use the Fast Debugger gem, ruby-debug-ide. I know that most people now are using Pry with Byebug, but ruby-debug-ide is an interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans and RubyMine.
Under Run > Edit Configurations > + > Ruby, I add a new debug configuration, according to the documentation here: https://www.jetbrains.com/help/ruby/run-debug-configuration-gem-command.html#1
Under Configuration, under 'Ruby Script', I add the path to the ruby gem file under lib: lib/my_gem.rb
Under Configuration, under 'Ruby SDK', I specify an RVM gemset I am using.
Under Bundler section, I check 'Run the script in context of bundler'. This would use bundle exec, which will read the dependencies in my Gemfile in my project's root. Now for gems, the Gemfile contains a method call "gemspec", which in turn reads the dependencies in dependencies in my_gem.gemspec. There, I have dependencies passed to the Gem::Specification.new block:
spec.add_development_dependency "bundler", "~> 1.7"
spec.add_development_dependency "rake", "~> 10.0"

Installing a gem from Github with Bundler

I am trying to use the instructions here to install a pre-released version of a gem with bundler.
The "bundle install" output lists the gem as getting installed, but "gem list" fails to find it.
My Gemfile:
source :gemcutter
gem 'sinatra', '1.1.0', :git => 'http://github.com/sinatra/sinatra.git'
gem 'RedCloth', '4.2.3'
Here is a gist with the rest of my sample code.
Has anyone gotten this scenario to work?
NOTE: I am also using RVM (on OS X). bundle show does list the gem (and dependencies) as existing, but I am not able to properly resolve them.
Thanks.
I would look at the load paths, and further debug from there, example:
...(master) $ irb
irb(main):001:0> $LOAD_PATH.count
=> 8
irb(main):004:0> require 'bundler/setup'
=> true
irb(main):005:0> $LOAD_PATH.count
=> 112
irb(main):006:0>
Bundler configures the load path for you, this means not all the gems are included on your load path by default.
Additionally, from the bundler git help:
Because Rubygems lacks the ability to handle gems from git, any gems installed from a git repository will not show up in gem list. They will, however, be available after running Bundler.setup.
Best regards, hope this helps
ED
Bundler might have installed it locally to your app. This could vary wildly, depending on OS and whether you are using RVM.
What is the output of bundle show sinatra?
In my case, sinatra was installed here:
/home/marshall/.rvm/gems/ruby-1.8.7-p302#3846859/bundler/gems/sinatra-9cfa74a7f352
Sinatra doesn't show in the gems list, but the server launches correctly if I execute rackup.
Gems installed via bundler on Engine Yard go to a different folder to isolate them.
it's usually /data/APP_NAME/shared/bundled_gems
To be sure, check your .bundle/config file on your APP folder at Engine Yard
It looks like there is an issue using Shotgun and Bundler (git repositories only).
If I use rackup to start up my app, all is well. I am going to investigate a little more and then file a bug with one (or both) of the projects.

Resources