Elegant chained 'or's for tests on same variable in Ruby
Make an array and use .include?
if ["01","02","03","04","05"].include?(@thing)
If the values really are all consecutive, you can use a range like (1..5).include?
For strings, you can use:
if ("01".."05").include?(@thing)
Are there shorter ways to perform checks on the same variable?
Here's one way:
if %w[A B C].include? variable
or if you have an actual range of values:
if ('A'..'Z').include? variable
How to chain methods in ruby passing the output of one method to consecutive methods
You can leave the ()
def a s
"hello #{s}"
end
def b s
"hi #{s}"
end
puts b a "Tom"
If you have many methods :
puts [:a,:b].inject("Tom"){|result,method| self.send(method,result)}
If you want to use those methods with any object (including Classes) :
module Kernel
def chain_methods(start_value, *methods)
methods.inject(start_value){|result,method| self.send(method,result)}
end
end
class D
def a s
"hello #{s}"
end
def b s
"hi #{s}"
end
end
class E
class << self
def a s
"hello #{s}"
end
def b s
"hi #{s}"
end
end
end
# Example with instance methods
puts D.new.chain_methods("Tom", :a, :b)
# Example with class methods
puts E.chain_methods("Tom", :a, :b)
# Thanks mudasobwa :
E.chain_methods("Tom", :a, :b, :puts)
Is there a more elegant way of writing a while loop in Ruby where the array size is not known?
Assuming your goal is to create an array of odd numbers up to a limit, you can use a range with a step.
limit = 20
array = (1..limit).step(2).to_a
EDIT
If you want to be able to descend as well as ascend you can use step
.
#Ascending
start = 1
limit = 20
array = start.step(limit, 2).to_a
#Descending
start = 20
limit = 1
array = start.step(limit, -2).to_a
.? (existence) operator in ruby?
Easiest thing to do is use the andand gem, although there are some other, pretty trivially-implemented options, like this, or this, or etc.
Method chaining - why is it a good practice, or not?
I agree that this is subjective. For the most part I avoid method chaining, but recently I also found a case where it was just the right thing - I had a method which accepted something like 10 parameters, and needed more, but for the most time you only had to specify a few. With overrides this became very cumbersome very fast. Instead I opted for the chaining approach:
MyObject.Start()
.SpecifySomeParameter(asdasd)
.SpecifySomeOtherParameter(asdasd)
.Execute();
The method chaining approach was optional, but it made writing code easier (especially with IntelliSense). Mind you that this is one isolated case though, and is not a general practice in my code.
The point is - in 99% cases you can probably do just as well or even better without method chaining. But there is the 1% where this is the best approach.
Accessing elements of nested hashes in ruby
The way I usually do this these days is:
h = Hash.new { |h,k| h[k] = {} }
This will give you a hash that creates a new hash as the entry for a missing key, but returns nil for the second level of key:
h['foo'] -> {}
h['foo']['bar'] -> nil
You can nest this to add multiple layers that can be addressed this way:
h = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = {} } }
h['bar'] -> {}
h['tar']['zar'] -> {}
h['scar']['far']['mar'] -> nil
You can also chain indefinitely by using the default_proc
method:
h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
h['bar'] -> {}
h['tar']['star']['par'] -> {}
The above code creates a hash whose default proc creates a new Hash with the same default proc. So, a hash created as a default value when a lookup for an unseen key occurs will have the same default behavior.
EDIT: More details
Ruby hashes allow you to control how default values are created when a lookup occurs for a new key. When specified, this behavior is encapsulated as a Proc
object and is reachable via the default_proc
and default_proc=
methods. The default proc can also be specified by passing a block to Hash.new
.
Let's break this code down a little. This is not idiomatic ruby, but it's easier to break it out into multiple lines:
1. recursive_hash = Hash.new do |h, k|
2. h[k] = Hash.new(&h.default_proc)
3. end
Line 1 declares a variable recursive_hash
to be a new Hash
and begins a block to be recursive_hash
's default_proc
. The block is passed two objects: h
, which is the Hash
instance the key lookup is being performed on, and k
, the key being looked up.
Line 2 sets the default value in the hash to a new Hash
instance. The default behavior for this hash is supplied by passing a Proc
created from the default_proc
of the hash the lookup is occurring in; ie, the default proc the block itself is defining.
Here's an example from an IRB session:
irb(main):011:0> recursive_hash = Hash.new do |h,k|
irb(main):012:1* h[k] = Hash.new(&h.default_proc)
irb(main):013:1> end
=> {}
irb(main):014:0> recursive_hash[:foo]
=> {}
irb(main):015:0> recursive_hash
=> {:foo=>{}}
When the hash at recursive_hash[:foo]
was created, its default_proc
was supplied by recursive_hash
's default_proc
. This has two effects:
- The default behavior for
recursive_hash[:foo]
is the same asrecursive_hash
. - The default behavior for hashes created by
recursive_hash[:foo]
'sdefault_proc
will be the same asrecursive_hash
.
So, continuing in IRB, we get the following:
irb(main):016:0> recursive_hash[:foo][:bar]
=> {}
irb(main):017:0> recursive_hash
=> {:foo=>{:bar=>{}}}
irb(main):018:0> recursive_hash[:foo][:bar][:zap]
=> {}
irb(main):019:0> recursive_hash
=> {:foo=>{:bar=>{:zap=>{}}}}
rspec test model for minimum and maximum values
To test if all valid values are covered you can write something like:
it "should allow valid values" do
(1..24).to_a.each do |v|
should allow_value(v).for(:hours)
end
You can also implement boundary testing. For each boundary one can test at, above and below any boundary to ensure that the conditional logic works as expected as posted by David Chelimsky-2.
So you would have 6 tests in total for the 2 boundaries.
Related Topics
Error: While Executing Gem ... (Zlib::Gzipfile::Error) Not in Gzip Format
Travis Reports Odd Message of Corrupted Gemfile.Lock
Dry Way to Assign Hash Values to an Object
Using Rbenv Doesn't Work with Sudo
Ruby Array to JSON and Rails JSON Rendering
Assign/Replace Params Hash in Rails
How to Customize the Table Builder Plugin for a Week Calendar
Check If an Array Is Subset of Another Array in Ruby
Form_For Error Messages in Ruby on Rails
Sinatra Clears Session on Post
Where Should My Non-Model/Non-Controller Code Live
Heroku App Crash H10 - Bash: Bin/Rails: No Such File or Directory
How to Overwrite a Printed Line in the Shell with Ruby
Differencebetween 'Try' and '&.' (Safe Navigation Operator) in Ruby