String comparison like "abcDEF" == "*DEF" - ruby-on-rails

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

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] }

Extract values from a string in Ruby

How to get a value from a string e.g
search_params[:price] = "1460,4500"
How can I get the first number into one variable and second into a different variable?
Did you mean this??:
first_price, second_price = search_params[:price].split(',')
You can use split method
irb(main):002:0> price = "1460,4500"
=> "1460,4500"
irb(main):003:0> price.split(',')
=> ["1460", "4500"]
irb(main):004:0> a, b = price.split(',')
=> ["1460", "4500"]
irb(main):005:0> a
=> "1460"
irb(main):006:0> b
=> "4500"

Create key if it doesn't exist in nested hashes

I've been trying to figure out how to write this ruby code more eloquently. Does someone have a better solution?
a[:new] = {} if a[:new].nil?
a[:new].merge!( { new_key => new_value } )
is there a way to write this in a more elegant way? I come across this a lot when dealing with nested hashes that need to check whether an key exist and if not, create it.
Write it as below taking the help of Hash#to_h and NilClass#to_h
a[:new] = a[:new].to_h.merge( { new_key => new_value } )
Example :
hsh1[:a] # => nil
hsh1[:a] = hsh1[:a].to_h.merge({1=>2})
hsh1[:a] # => {1=>2}
hsh2 = {:a => {'k' => 2}}
hsh2[:a] # => {"k"=>2}
hsh2[:a] = hsh2[:a].to_h.merge({1=>2})
hsh2 # => {:a=>{"k"=>2, 1=>2}}
Do this at the beginning:
a = Hash.new{|h, k| h[k] = {}}
then, without caring whether a has a key :new or not, do
a[:new].merge!(new_key => new_value)
or
a[:new][new_key] = new_value

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

ror, how to make a regex dynamic?

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/

Resources