ror, how to make a regex dynamic? - ruby-on-rails

given this:
if (params[:to].to_s =~ (/^r\+.*#site.com$/)) == nil
How can I make site.com dynamic to: #{SITE_CONFIG['mail_host']}
I tried
if (params[:to].to_s =~ (/^r\+.*##{SITE_CONFIG['mail_host']}$/)) == nil
Which did not work.. ideas?

In ruby you can create the regexp from a string representation using Regexp.new:
if (params[:to].to_s =~ Regexp.new("^r\\+.*##{Regexp.quote(SITE_CONFIG['mail_host'])}$")) == nil

Define "not work", regexes can contain interpolated strings:
pry(main)> foo = "wat"
=> "wat"
pry(main)> "ohai wat kthxbai" =~ /#{foo}/
=> 5
pry(main)> foo = "nar"
=> "nar"
pry(main)> "ohai wat kthxbai" =~ /#{foo}/
=> nil
pry(main)> /#{foo}/
=> /nar/

Related

Ruby access hash value by a variable

Let's consider this as our hash c = {:test => {:foo => true}}
Normally, if we would like to print value of foo, we would access the hash like this c[:test][:foo] but I would like to access it dynamically based on my variable.
Therefore, let's consider the following variable path = [[:test],[:foo]].
How do I access the value true now? I have tried c[path] but it just says nil. What am I missing?
You can make use of dig. You can check the doc of dig here Hash#dig
c = { :test => { :foo => true } }
c[:test][:foo]
#=> true
c.dig(:test, :foo)
#=> true
path = [:test, :foo]
c.dig(*path)
#=> true
You just need to pass the hierarchy
Note: The * before path in c.dig(*path) is reffered as splat operator
Old good recursive Ruby 1.9+ solution:
hash = {:test => {:foo => true}}
path = [[:test],[:foo]]
path.flatten.reduce(hash) { |h, p| h[p] }
#⇒ true
Or, as #Stefan suggested in comments:
path.reduce(hash) { |h, (p)| h[p] }
# or even
path.reduce(hash) { |h, p| h[p.first] }
More defensive:
path.flatten.reduce(hash) { |h, p| h.nil? ? nil : h[p] }

String comparison like "abcDEF" == "*DEF"

I am working on an rails app in which I need a comparison like:
url == "http://localhost:3000/admin/admin_login"
I am wondering that is there a way to compare like:
url == "*/admin/admin_login"
You can use a regexp.
irb(main):001:0> url = "http://localhost:3000/admin/admin_login"
=> "http://localhost:3000/admin/admin_login"
irb(main):002:0> url =~ /admin\/admin_login\z/
=> 22
irb(main):003:0> url =~ /foo\/something_else\z/
=> nil
irb(main):004:0> "http://localhost:3000/admin/admin_login/bar" =~ /admin\/admin_login\z/
=> nil
You can use String#include?:
url = "http://localhost:3000/admin/admin_login"
url.include?("/admin/admin_login")
=> true
Other way is use String#end_with?:
url.end_with?("/admin/admin_login")
=> true
This works if you want to check if url ends with this argument.
You can use include? or []
value="http://localhost:3000/admin/admin_login"
value["/admin/admin_login"]
=> "/admin/admin_login"
value["/admin/admin_login1"]
=> nil
value[/\/admin\/admin_login/]
=> "/admin/admin_login"
value.include?("/admin/admin_login")
=> true

Ruby Check condition if a string include multi-different strings?

I am newbie to Ruby. Are there any better ways to write this:
if (mystring.include? "string1") || (mystring.include? "string2") ||
(mystring.include? "string3")
Yes, as below :
if %w(string1 string2 string3).any? { |s| my_string.include? s }
# your code
end
Here is the documentation : Enumerable#any?
Passes each element of the collection to the given block. The method returns true if the block ever returns a value other than false or nil. If the block is not given, Ruby adds an implicit block of { |obj| obj } that will cause any? to return true if at least one of the collection members is not false or nil.
Here is another way ( more fastest) :
[13] pry(main)> ary = %w(string1 string2 string3)
=> ["string1", "string2", "string3"]
[14] pry(main)> Regexp.union(ary)
=> /string1|string2|string3/
[15] pry(main)> "abbcstring2"[Regexp.union(ary)]
=> "string2"
[16] pry(main)> "abbcstring"[Regexp.union(ary)]
=> nil
Just read Regexp::union and str[regexp] → new_str or nil .
Well, you could always use a regular expression here (risking another jwz quote :)
if mystring =~ /string1|string2|string3/
...
end

Inspect in Ruby

When I use this code:
x = []
x << 1
if (x[0].inspect == 1)
puts "OLLAAA"
end
It outputs nothing, but it should because x[0].inspect is == to 1. But if I change == to != I get output "OLLAAA", or when if is changed to unless. Any ideas?
Fixnum#inspect is an alias for to_s - you need to compare against "1"
Why are you so sure x[0].inspect == 1? Object::inspect returns a string.
$ irb
2.0.0-p247 :001 > x = []
=> []
2.0.0-p247 :002 > x << 1
=> [1]
2.0.0-p247 :003 > x[0].inspect == 1
=> false
If you change == to !=, obviously you flip the logic, so it prints. The exact same thing is happening for if to unless.
Because of below :
x[0].inspect # => "1"
x[0].inspect gives string instance,which is not equal to Fixnum instance 1. Thus x[0].inspect == 1 evaluates to false,and you didn't get the output. Now when you use !=,hope you got the point why you did get the output.
Fixnum#inpect call actually does Fixnum#to_s. See below :
12.method(:inspect) # => #<Method: Fixnum#to_s>
as mentioned above, inspect return a string. You can solve your problem with
if (x[0].inspect.to_i == 1)
puts "Hey I am an integer :)"
end

How to compare two Hashes so to return true if both Hashes have same keys/values?

I am using Ruby on Rails 3.2.2 and Ruby 1.9.3. I would like to compare two Hashes (A and B) so to return true if a Hash (A) include all keys/values of the other Hash (B).
For example, given I have
params.inspect
# => { "action"=>"...", "controller"=>"...", "key_param1"=>"value_param1", , "key_param2"=>"value_param2", "key_param3"=>"value_param3", ... }
my_hash1.inspect
# => { "key_param1"=>"value_param1", "key_param2"=>"value_param2" }
my_hash2.inspect
# => { "key_param4"=>"value_param4", "key_param1"=>"value_param1" }
my_hash3.inspect
# => {}
Then I am looking for a method (or something like that) in order to make
params.has_same_keys_and_values_as?(my_hash1)
# => true
params.has_same_keys_and_values_as?(my_hash2)
# => false
params.has_same_keys_and_values_as?(my_hash3)
# => true
Assuming that Hash#keys and Hash#values return values in the same order:
params.values_at(*my_hash.keys) == my_hash.values
I think you can use:
a.slice(*b.keys) == b
where a and b are your hashes. note that slice is a rails method and not ruby.
in plain ruby you can write:
a.keep_if{|k, v| b[k]} == b
class Hash
def >=(b)
eq = true
b.each { |k, v| eq &= !(self.include? k) ? false : ( ( ((self[k]&&v).is_a? Hash) && !((v||self[k]).empty?) ) ? self[k]>=v : true)}
return eq
end
end
params = { "action"=>"...", "controller"=>"...", "key_param1"=>"value_param1", "key_param2"=>"value_param2", "key_param3"=>"value_param3" }
my_hash1 = { "key_param1"=>"value_param1", "key_param2"=>"value_param2" }
my_hash2 = { "key_param4"=>"value_param4", "key_param1"=>"value_param1" }
my_hash3 = {}
p params >= my_hash1 #true
p params >= my_hash2 #false
p params >= my_hash3 #true
It'll work with "deep" hashes as well:
b = {1 => {2 => {} }, 4 => {} }
a = {1 => {2 => {3 => {} }}, 4 => {}, 5 => "123" }
p a >= b #true
p b >= a #false
P.S.
Whether one hash includes another hash
EDIT: This is assuming that the values/keys are not in the same order in both hashes.
You could iterate over each key in hash1 and use has_key? on hash2. Keep in mind this is naive solution that could be slow for large datasets.
Checkout has_key? and has_value? here: http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-has_key-3F
You could loop as follows:
hash1.each_key { |key|
if hash2.has_key?(key)
do whatever
endif
}
better way, there's an active support method for this, hash.diff, wrap it with .empty? to check if they are the same
{:one => 1}.diff({:one => 1}).empty?
=> true
{:one => 1}.diff({:one => 2}).empty?
=> false
http://as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Diff.html

Resources