opening Array in ruby on rails console v. irb - ruby-on-rails

I wish to make my code a little more readable by calling #rando on any array and retrieve a random element (rando because a rand() method already exists and I don't want there to be any confusion).
So I opened up the class and wrote a method:
class Array
def rando
self[ rand(length) ]
end
end
This seems far too straightforward.
When I open up irb, and type arr = %w(hi bye) and then arr.rando I get either hi or bye back. That's expected. However, in my rails console, when I do the same thing, I get ArgumentError: wrong number of arguments (1 for 0)
I've been tracing Array up the rails chain and can't figure it out. Any idea?
FWIW, I'm using rails 2.3.11 and ruby 1.8.7

Works fine in my case :
Loading development environment (Rails 3.0.3)
ruby-1.9.2-p180 :001 > class Array
ruby-1.9.2-p180 :002?> def rando
ruby-1.9.2-p180 :003?> self[ rand(length) ]
ruby-1.9.2-p180 :004?> end
ruby-1.9.2-p180 :005?> end
=> nil
ruby-1.9.2-p180 :006 > arr = %w(hi bye)
=> ["hi", "bye"]
ruby-1.9.2-p180 :007 > arr.rando
=> "bye"

Related

How do I write a function in rails console?

I am trying to write a function in the rails console, and in the example, this is how the function should look in terminal.
>> def string_message(str = '')
>> return "It's an empty string!" if str.empty?
>> return "The string is nonempty."
>> end
How do they create a new line while still making the console realize it is all of the lines create a function. Would it be accurate to write it as:
>> def string_message(str = '') \n\t return "It's an empty string!" if str.empty? \n\t blah blah \n\t
?
IRB, the ruby console in which rails console relies supports this out of the box.
Just type your function declaration, press the enter key, then input the body line by line, and finally type end.
You'll see text like this:
2.4.1 :001 > def say_hi(person)
2.4.1 :002?> puts "Hi #{person}"
2.4.1 :003?> end
=> :say_hi
2.4.1 :004 > say_hi("Nina")
Hi Nina
=> nil
2.4.1 :005 >
Notice how the ? indicates that IRB is waiting for more input before evaluating the expression.

simple_format changes the text itself

In Rails 3.0, the helper method simple_format changes the parameter itself.
I expected that it only returns the wrapped text.
2.0.0-p648 :001 > Rails.version
=> "3.0.20"
2.0.0-p648 :002 > s = "Hello"
=> "Hello"
2.0.0-p648 :003 > helper.simple_format(s)
=> "<p>Hello</p>"
2.0.0-p648 :004 > s
=> "<p>Hello</p>"
I checked with Rails 4.2 and it doesn't change the text.
Can someone please explain it?
Sam
The difference between implementations of this method in Rails 4.2 and Rails 3.0 is that in Rails 3.0 the passed string is modified (mutated by gsub!) and in Rails 4.2 it's not (it just returns a new modified string):
Rails 4.2:
2.4.0 :006 > s = "hello"
=> "hello"
2.4.0 :007 > simple_format s
=> "<p>hello</p>"
2.4.0 :008 > s
=> "hello"
The source code of different implementations can be found in the documentation

Difference between Ruby’s Hash and ActiveSupport’s HashWithIndifferentAccess

What is the difference between Ruby’s Hash and ActiveSupport’s HashWithIndifferentAccess? Which is the best for dynamic hashes?
Below is the simple example that will show you difference between simple ruby hash & a "ActiveSupport::HashWithIndifferentAccess"
HashWithIndifferentAccess allows us to access hash key as a symbol or string
Simple Ruby Hash
$ irb
2.2.1 :001 > hash = {a: 1, b:2}
=> {:a=>1, :b=>2}
2.2.1 :002 > hash[:a]
=> 1
2.2.1 :003 > hash["a"]
=> nil
ActiveSupport::HashWithIndifferentAccess
2.2.1 :006 > hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1, b:2)
NameError: uninitialized constant ActiveSupport
from (irb):6
from /home/synerzip/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
2.2.1 :007 > require 'active_support/core_ext/hash/indifferent_access'
=> true
2.2.1 :008 > hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1, b:2)
=> {"a"=>1, "b"=>2}
2.2.1 :009 > hash[:a]
=> 1
2.2.1 :010 > hash["a"]
=> 1
class HashWithIndifferentAccess is inherited from ruby "Hash" & above special behavior is added in it.
In Ruby Hash:
hash[:key]
hash["key"]
are different. In HashWithIndifferentAccess as the name suggests, you can access key either way.
Quoting official documentation to this:
Implements a hash where keys :foo and "foo" are considered to be the
same.
and
Internally symbols are mapped to strings when used as keys in the
entire writing interface (calling []=, merge, etc). This mapping
belongs to the public interface. For example, given:
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
You are
guaranteed that the key is returned as a string:
hash.keys # => ["a"]

Rails n elements before last

In Rails I often do this:
Model.last(5).first
This retrieves element last-5.
Is there a built-in way of doing this?
The more common way is offset()
Model.offset(5).last
Edit (for lazy people):
1.8.7 :001 > User.first.id
=> 1
1.8.7 :002 > User.last.id
=> 143455
1.8.7 :003 > User.offset(5).last.id
=> 143450

In Ruby on Rails, should we use content_for?(:foobar)?

This is for Rails 3, almost always I think a content_for?(:foo) is followed by content_for(:foo) (in haml):
%title= content_for?(:title_for_page) ? "#{content_for(:title_for_page)} - Our great website" : 'Our great website'
So instead of doing 2 lookups, isn't it better to just do 1 lookup and use longer code:
- title_for_page = content_for(:title_for_page) # is "" when not previously set
%title= title_for_page.blank? ? 'Our great website' : "#{title_for_page} - Our great website"
? But if content_for? is implemented as a hash, then maybe it is super quick anyway, comparable to the blank? anyways?
A one-liner to solve the problem:
- title_for_page = (c = content_for(:title_for_page)).blank? ? 'Our great website' : "#{c} - Our great website"
Only way to find out is to test :)
ruby-1.9.2-p136 :001 > h = {:mike => "test"}
=> {:mike=>"test"}
ruby-1.9.2-p136 :004 > Benchmark.ms do
ruby-1.9.2-p136 :005 > h[:mike].present?
ruby-1.9.2-p136 :006?> end
=> 0.029087066650390625
ruby-1.9.2-p136 :007 > Benchmark.ms do
ruby-1.9.2-p136 :008 > h[:mike].blank?
ruby-1.9.2-p136 :009?> end
=> 0.011205673217773438
I am using present?, as per the source of content_for?
Interesting that blank? is faster than present?, isn't it? Time to explore.
Lets look at the source code for present?:
Woah, it turns out present? just calls blank? and negates it.

Resources