How to use RSpec expectations in irb - ruby

I'd want to use [1,2,3].should include(1) in irb. I tried:
~$ irb
1.9.3p362 :001 > require 'rspec/expectations'
=> true
1.9.3p362 :002 > include RSpec::Matchers
=> Object
1.9.3p362 :003 > [1,2,3].should include(1)
TypeError: wrong argument type Fixnum (expected Module)
from (irb):3:in `include'
from (irb):3
from /home/andrey/.rvm/rubies/ruby-1.9.3-p362/bin/irb:16:in `<main>'
But it doesn't work though it's a valid case. How can I use [1,2,3].should include(1)?

You are close, but calling include on top-level you will be calling Module#include. To get around it you need to remove the original include method so that RSpec's include gets called instead.
First let's figure out where the system include comes from:
> method :include
=> #<Method: main.include>
Ok. It looks like it's defined in main. This is the Ruby top-level object. So let's rename and remove the original include:
> class << self; alias_method :inc, :include; remove_method :include; end
Now we can get down to business:
> require 'rspec'
> inc RSpec::Matchers
> [1,2,3].should include(1)
=> true

Related

Figure out where a method was defined

If I follow the following part of this article:
Figure out where a method was defined
object = Object.new
puts object.method(:blank?).source_location
=> ["/gems/activesupport-5.0.0.beta1/lib/active_support/core_ext/object/blank.rb", 14]
I should be able to find the definition of the blank? method, however when I try this code within irb with ruby 2.0.0 I get this error message:
➜ ~ irb
irb(main):001:0> object = Object.new
=> #<Object:0x007fc84882f088>
irb(main):002:0> puts object.method(:blank?).source_location
NameError: undefined method `blank?' for class `Object'
from (irb):2:in `method'
from (irb):2
from /usr/bin/irb:12:in `<main>'
Did I miss anything?
Thank you.
.blank? method does not exist for a Object type. I know for sure it exists for a String method if I include the active_support lib
irb(main):001:0> String.new.method(:blank?).source_location
=> ["/home/xeon/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/core_ext/object/blank.rb", 116]
If you include activesupport-5.0.0.beta1 then it will work for you. (Looking at the source path of the article you have posted)

Ruby: Get a method's class or module name

I'm trying to understand a mixin precedence situation. If I run foo.bar I'm trying to figure out exactly which bar will be executed. Here is a snipped irb session where I tried to find out where an array's assoc method is defined.
2.3.0 :032 > ray = ['cat', nil, 'dog']
=> ["cat", nil, "dog"]
2.3.0 :033 > ray.methods
=> [:fill, :assoc, :rassoc, :uniq, ...
2.3.0 :034 > ray.method("assoc").class_or_module_name
NoMethodError: undefined method `class_or_module_name' for #<Method: Array#assoc>
from (irb):34
from /Users/mark/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>'
2.3.0 :035 > ray.methods("assoc").class_or_module_name
NoMethodError: undefined method `class_or_module_name' for #<Array:0x007ffb8aa286a8>
from (irb):35
from /Users/mark/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>'
2.3.0 :036 > ray.methods("assoc")
=> [:fill, :assoc, :rassoc, :uniq, :uniq!, :compact, ...
If possible I would like to see the methods and their source location that lost precedence.
To find out which class or module defines a method (rather than what file), use Method#owner.
For example,
[].method(:last).owner #=> Array
[].method(:flat_map).owner #=> Enumerable
You'll actually find that a lot of the methods that Array could get from Enumerable, it actually defines itself (presumably to provide a more efficient implementation):
irb(main):018:0> Enumerable.instance_methods.select {|meth_name| [].method(meth_name).owner == Array }
=> [:to_a, :to_h, :sort, :count, :find_index, :select, :reject, :collect, :map, :first, :include?, :reverse_each, :zip, :take, :take_while, :drop, :drop_while, :cycle]
In general, to know where a method is defined you can use source_location(docs), e.g.
ray.method("assoc").source_location
although in this case it will return nil since assoc is a native method. It will work for other methods, e.g.
ray.methods.map{ |m| [m, ray.method(m).source_location] }
For native methods you can use Pry, e.g.
pry(main)> ? ray.assoc
From: array.c (C Method):
Owner: Array
Visibility: public
[...]
? is a shorthand for show-doc.

NameError: uninitialized constant Game

I have a file Word.rb
class Word
attr_accessor :word, :letters
def initialize (word)
##word = word
#letters = word.split('').map{|letter| {:letter => letter, :hidden => true} }
end
end
and another file Game.rb, which will use Word.rb
require_relative ('./Word.rb')
require 'pry'
class Game
attr_accessor :guesses, :guessed_letters, :words, :current_word
def initialize (words)
#guesses = 0
#guessed_letters = []
#words = words
#current_word = current_word
end
end
And I'm getting the following error:
NameError: uninitialized constant Game
When I try to create a instance of Game like this:
game = Game.new(['hello', 'sunshine', 'chipmunk', 'twitch'])
I just am not sure what I am doing wrong since I am requiring the Word.rb file that Game.rb will need. All files are on the same level, nothing is in a subdirectory. Interestingly, I do not get this error once I comment the require_relative line out (but of course, I need that file required). I have also tried not using require_relative and simply using require as well as a couple other varieties: parens/no parens, file extension/no file extension, etc. How do I properly require this file? I also have a lovely and robust array of words sitting in another file that I would like to require to be used and passed into Game.new().
Look What I did
$ mkdir test
$ cd test
$ gedit Word.rb
# and copied your content and saved
$ gedit Game.rb
# and copied you content and saved
$ irb
After IRB session run I did following
2.1.1 :001 > game = Game.new(['asd'])
NameError: uninitialized constant Game
from (irb):1
from /home/shiva/.rvm/rubies/ruby-2.1.1/bin/irb:11:in `<main>'
2.1.1 :002 > require 'game'
LoadError: cannot load such file -- game
2.1.1 :004 > require 'Game.rb'
LoadError: cannot load such file -- Game.rb
2.1.1 :005 > require './Game.rb'
=> true
2.1.1 :006 > game = Game.new(['shiva', 'bhusal'])
=> #<Game:0x00000003085428 #guesses=0, #guessed_letters=[], #words=["shiva", "bhusal"], #current_word=nil>
2.1.1 :007 >
Try like this

Why do I get "stack level too deep" from method_missing in irb 1.9.3?

Scenario:
-bash-3.2$ irb -f
ruby-1.9.3-p0 :001 > #v = {}
=> {}
ruby-1.9.3-p0 :002 > def method_missing(sym, *args); #v[sym]; end
=> nil
ruby-1.9.3-p0 :003 > a
(irb):2: stack level too deep (SystemStackError)
-bash-3.2$
I ran with -f to avoid loading any irbrc stuff.
I'm expecting to get nil when I input a. What's going on, and is there a workaround? I tried wrapping a with a begin/rescue Exception block but that didn't do anything.
This also happens with 1.9.2, but not 1.9.1.
More strange behavior:
-bash-3.2$ irb -f
irb(main):001:0> #v = {}
=> {}
irb(main):002:0> def method_missing(sym, *args); #v[sym]; end; 5.times { p a }
nil
nil
nil
nil
nil
=> 5
irb(main):003:0> a
(irb):2: stack level too deep (SystemStackError)
-bash-3.2$
This tells me that there's a bug in irb, or that some obscure bug in ruby is being triggered by irb. Also, after defining method_missing, even methods that exist like local_variables or eval cause the error.
Looks like defining it as a singleton method works:
def self.method_missing(sym, *args); #v[sym]; end
Defining it as a top-level method replaces BasicObject#method_missing, which probably affected some irb internals like Phrogz said.

How do I use an ActionView::Helper in a Ruby script, outside of Rails?

I am looking to use ActionView::Helpers::NumberHelper from a Ruby script.
What all do I need to require etc.?
~> irb
ruby-1.9.2-p180 :001 > require 'action_view'
=> true
ruby-1.9.2-p180 :002 > ActionView::Base.new.number_to_currency 43
=> "$43.00"
As of Rails 3.2.13, you can do the following:
class MyClass
include ActionView::Helpers::NumberHelper
def my_method
...
number_with_precision(number, precision: 2)
...
end
end
You might need to require 'action_view' too.
Edit: This answer is still valid in Rails 4.2.3.

Resources