Implementing dry-run in ruby script - ruby

anybody know how to implement dry-run option in Ruby?
I need something like this, but only for ruby
https://serverfault.com/questions/147628/implementing-dry-run-in-bash-scripts
I've tried this, but part after else doesn't work:
DRY_RUN = true
def perform(*args)
command = args
if DRY_RUN
command.each{|x| puts x}
else
command.each {|x| x}
end
end
perform("puts 'Hello'")
Thanks for any idea in advance.
P.S I don't want use something like system("ruby -e \"puts 'Hello'\"")

This could help:
def perform(*commands)
commands.each { |x| DRY_RUN ? puts(x) : eval(x)}
end
It results in:
DRY_RUN = true
perform("puts 'Hello'")
puts 'Hello'
=> ["puts 'Hello'"]
DRY_RUN = false
perform("puts 'Hello'")
Hello
=> ["puts 'Hello'"]

Related

How do I remove the original string when using each_char?

My code is:
def LetterChanges(str)
str.each_char {|x| print x.next!}
end
LetterChanges("hello")
Which returns:
"ifmmp" => "hello"
How do I get it to only return "ifmmp"? Any help would be greatly appreciated.
"hello".gsub(/./, &:next)
# => "ifmmp"
def LetterChanges(str)
str.chars.map(&:next).join("")
end
LetterChanges("hello")
# => "ifmmp"
or
def LetterChanges(str)
str.size.times{|i| str[i] = str[i].next }
str
end
LetterChanges("hello")
# => "ifmmp"
puts str;
This should do it for you.
The solution is easy:
def LetterChanges(str)
puts str.chars.map(&:next).join
end
but I'd suggest you to refactor it to let puts out. This way you don't hardcode the print of the value and you just make it return the string so that the user of the method can do whatever he wants with that value:
def LetterChanges(str)
str.chars.map(&:next).join
end
and then you can just do:
puts LetterChanges("hello")
# => "ifmmp"

How do I use regular expressions in Ruby?

I don't know how to implement regular expressions in Ruby. I tried this code, but it always returns true:
firstName = "Stepen123"
res = Validation_firstName(firstName)
puts res
def Validation_firstName(firstName)
reg = /[a-zA-z][^0-9]/
if reg.match(firstName)
return true
else
return false
end
end
I am not sure what I did wrong.
You can rewrite your method like this:
def validation_firstname(first_name)
!!first_name[/^[a-z]+$/i]
end
def validation_firstname(first_name)
first_name.scan(/\d+/).empty?
end
p validation_firstname("Stepen123") #=> false
p validation_firstname("Stepen") #=> true

Return a single value from a nested each block, trying to use 'return'

def get_type
x = [{:type=>'A', :patterns=>['foo.*']}, {:type=>'B', :patterns=>['bar.*']}]
name = 'foo.txt'
result = x.each { |item|
item[:patterns].each { |regex|
puts "Checking #{regex} against #{name}"
if !name.match(regex).nil?
puts "Found match: #{item[:type]}"
return item[:type]
end
}
}
end
result = get_type
puts "result: #{result}"
Expected output:
Checking foo.* against foo.txt
Found match: A
result: A
However, all I see is:
Checking foo.* against foo.txt
Found match: A
My current work around is this:
def get_type
x = [{:type=>'A', :patterns=>['foo.*']}, {:type=>'B', :patterns=>['bar.*']}]
name = 'foo.txt'
result = []
x.each { |item|
item[:patterns].each { |regex|
puts "Checking #{regex} against #{name}"
if !name.match(regex).nil?
puts "Found match: #{item[:type]}"
result << item[:type]
end
}
}
result[0] unless result.empty?
end
Why doesn't the first approach work? or maybe it is 'working', I just don't understand why I'm not getting what I'd expect.
May I suggest a refactor? your code looks kind of clunky because you are using each loops (imperative) when you in fact need a map+first (functional). As Ruby enumerables are not lazy this would be inefficient, so people usually build the abstraction Enumerable#map_detect (or find_yield, or find_first, or map_first):
def get_type_using_map_detect(name)
xs = [{:type => 'A', :patterns => ['foo.*']}, {:type => 'B', :patterns => ['bar.*']}]
xs.map_detect do |item|
item[:patterns].map_detect do |regex|
item[:type] if name.match(regex)
end
end
end
This is a possible implementation of the method:
module Enumerable
# Like Enumerable#map but return only the first non-nil value
def map_detect
self.each do |item|
if result = (yield item)
return result
end
end
nil
end
end
Works fine for me. Are you actually invoking it with
result = get_type puts "result: #{result}"
? Because that shouldn't work at all, though I'm assuming there's a linefeed that got eaten when you posted this.

Compare the Content, Not the Results, of Procs

Using Ruby 1.9.2
Problem
Compare the content, not the results, of two procs. I understand the results can't be tested because of the halting problem but that's OK; I don't want to test the results anyway.
For instance
proc {#x == "x"} == proc {#x == "x"} => false # doh!
That returns false because the objects inside the procs are not the same.
My clunky solution
I have a work around solution that kinda sorta does what I want but it doesn't really test that the proc is "equal" to what I put in it. In my specific case the format of my procs will always be boolean tests on instance variables like this:
{#x == "x" && #y != "y" || #z == String}
I wrote a method that builds classes dynamically and creates instance variables set to specified values:
def create_proc_tester(property_value_hash)
new_class = Class.new.new
new_class.class.class_eval do
define_method(:xql?) { |&block| instance_eval &block }
end
property_value_hash.each do |key, value|
new_class.instance_variable_set("##{key}", value)
end
new_class
end
Which could be used something like this:
class Foo
attr_accessor :block
end
foo = Foo.new
foo.block = proc {#x == "x" && #y != "y" || #z == String}
tester = create_proc_tester(:x => "x", :y => "y", :z => Fixnum)
puts "Test #1: #{tester.xql? &foo.block}"
tester = create_proc_tester(:x => "x", :y => "x", :z => String)
puts "Test #2: #{tester.xql? &foo.block}"
> Test #1: false
> Test #2: true
.
.
That's all great and wonderful but I want to know if there is a better, more meta, way to do this that actually tests the contents of the proc not just a work around that solves my specific problem; something that could be used to test any proc.
I was thinking there might be a way to use the Ruby parser to get something to compare but I have no idea how. I'm researching it now but thought I'd try to see if anyone here has done this before and knows how. That might be a dead-end though because of the dynamic nature of Ruby but that's where I'm looking now.
If you're using Ruby 1.9, you may be able to use the sourcify gem.
$ irb
> require 'sourcify'
=> true
> a = proc {#x == "x"}
=> #<Proc:0x9ba4240#(irb):2>
> b = proc {#x == %{x}}
=> #<Proc:0x9ba23f0#(irb):3>
> a == b
=> false
> a.to_source == b.to_source
=> true
> RUBY_VERSION
=> "1.9.2"
We also ran into the ParseTree/Ruby 1.9 incompatibility problem at my company.
$ sudo gem install ruby2ruby ParseTree
require 'parse_tree'
require 'ruby2ruby'
require 'parse_tree_extensions'
# All of these are the same:
proc { puts 'a' }.to_ruby # => "proc { puts(\"a\") }"
lambda { puts "a" }.to_ruby # => "proc { puts(\"a\") }"
Proc.new { puts %{a} }.to_ruby # => "proc { puts(\"a\") }"
# If you need to do this with classes:
class Bar; define_method(:foo) { 'a' }; end
puts Ruby2Ruby.new.process(Unifier.new.process(ParseTree.translate(Bar)))
# will print this:
# class Bar < Object
# def foo
# "a"
# end
# end

Is this a reasonable use for &&= in Ruby?

In SO question 2068165 one answer raised the idea of using something like this:
params[:task][:completed_at] &&= Time.parse(params[:task][:completed_at])
as a DRYer way of saying
params[:task][:completed_at] = Time.parse(params[:task][:completed_at]) if params[:task][:completed_at]
where the params Hash would be coming from a (Rails/ActionView) form.
It's a kind of corollary to the well-known ||= idiom, setting the value if the LHS is not nil/false.
Is using &&= like this actually a recognised Ruby idiom that I've somehow missed or have I just forgotten a more commonly-used idiom? It is getting rather late...
It ought to be. If nothing else, params[:task] is only evaluated once when using the &&= form.
To clarify:
params[:task][:completed_at] = params[:task][:completed_at] && ...
calls [](:task) on params twice, [](:completed_at) and []=(:completed_at) once each on params[:task].
params[:task][:completed_at] &&= ...
calls [](:task) on params once, and its value is stashed away for both the [](:completed_at) and []=(:completed_at) calls.
Actual example describing what I'm trying to illustrate (based on Marc-Andre's example code; much thanks):
class X
def get
puts "get"
#hash ||= {}
end
end
irb(main):008:0> x = X.new
=> #<X:0x7f43c496b130>
irb(main):009:0> x.get
get
=> {}
irb(main):010:0> x.get[:foo] = 'foo'
get
=> "foo"
irb(main):011:0> x.get[:foo]
get
=> "foo"
irb(main):012:0> x.get[:foo] &&= 'bar'
get
=> "bar"
irb(main):013:0> x.get[:foo] = x.get[:foo] && 'bar'
get
get
=> "bar"
Note that using the "expanded" form causes "get" to be printed out twice, but using the compact form causes it to only be printed once.
Using &&=, in the case of LHS is false, it is only being read once, but not being set. This should make it clearer ...
class Test
def initialize(value)
#v = value
end
def v=(value)
puts "set"
#v = value
end
def v
puts "get=>#{#v}"
#v
end
end
t = Test.new(true)
t.v = t.v && true
puts '----'
t.v &&= true
puts '----'
t = Test.new(false) # lets make LHS false
t.v = t.v && true
puts '----'
t = Test.new(false) # lets make LHS false
t.v &&= true
The result:
get=>true
set
----
get=>true
set
----
get=>false
set
----
get=>false

Resources