Extract values from a string in Ruby - ruby-on-rails

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"

Related

Is there a shorthand way to check for presence before assigning a variable in ruby?

is there a shorter way to do this (considering a is already set to some value):
a = b if b.present?
I may have come across a way to do this before, but don't remember.
Just a = b if b.present? on its own is functionally equivalent to:
if b.present?
a = b
else
a = nil
end
so you could use Object#presence:
presence()
Returns the receiver if it's present otherwise returns nil. object.presence is equivalent to
object.present? ? object : nil
like this:
a = b.presence
If a already has a value and you're really saying:
a = something_interesting
a = b if b.present?
then you could say:
a = b.presence || something_interesting
if b is some complex expression that you want to evaluate just once, you could use
a = b.presence || a
you could do this
a = b if !b.nil?
or
a = b if b
or
a = b if b != nil
The thing about present? is it protects you against the trap of empty arrays, hashs, and other collections. So these will work if you are not concerned about an empty collection.
You can use ||= operator, but it depends on of what you want your code to do. This operator assigns the value of b to a if b is not nil.For example, if a = 5 and perform the following operation a ||= b value of b will be assigned to a only if b is not nil, but if a was not previously declared value of a will be nil for this code a ||= b.
EXAMPLES:
irb(main):001:0> b = nil
=> nil
irb(main):002:0> a ||= b
=> nil
irb(main):003:0> b = 5
=> 5
irb(main):004:0> a ||= b
=> 5
irb(main):005:0> a ||= nil
=> 5
||= operator is what you are looking for. It checks if the operand is nil or present before assigning a value. If present doesn't assign, if nil or undefined will assign the value.
[1] pry(main)> a
NameError: undefined local variable or method `a' for main:Object
from (pry):1:in `__pry__'
[2] pry(main)> a ||= 100
=> 100
[3] pry(main)> a = nil
=> nil
[4] pry(main)> a ||= 100
=> 100
[5] pry(main)> a ||= 200
=> 100

How can I access an array inside a hash?

I have a hash within an array:
values = {}
values.merge!(name => {
"requested_amount" => #specific_last_pending_quota.requested_amount,
"granted" => #specific_last_pending_quota.granted,
"pending_final" => pending_final
})
#o_requests[request.receiving_organization][request.program_date][:data] = values
I send it to the view and then when I get it so:
= quota[:data].inspect
# {"theme"=>{"requested_amount"=>2, "granted"=>false, "pending_final"=>0}}
I want to fetch the object like this:
= quota[:data]["theme"].inspect
But I got this error
can't convert String into Integer
I guess quota[:data] may return array of hash
Try:
= quota[:data][0]["theme"]
Here I tried case to get same error and check:
> h[:data]
#=> [{"theme"=>{"requested_amount"=>2, "granted"=>false, "pending_final"=>0}}]
> h[:data]["theme"]
TypeError: no implicit conversion of String into Integer
from (irb):10:in `[]'
from (irb):10
from /home/ggami/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
> h[:data][0]["theme"]
#=> {"requested_amount"=>2, "granted"=>false, "pending_final"=>0}
Try convert it to proper hash I guess it should work fine.
values = {}
values.merge!(name => {:requested_amount => #specific_last_pending_quota.requested_amount, :granted => #specific_last_pending_quota.granted, :pending_final => pending_final})
#o_requests[request.receiving_organization][request.program_date][:data] = values

Set random Rails variable to not equal another random variable?

I have 2 instance variables in a Rails controller:
#stories = Post.tagged_with("test").all(:order => "RANDOM()", :limit => 1)
#stories2 = Post.tagged_with("test").where('post_id not in (?)', [#stories]).all(:order => "RANDOM()", :limit => 1)
I don't want the other instance variable to equal the other but they both have to be "random" (I know this technically isn't random). Is it possible to set a variable random except one value?
#stories, #stories2 = Post.tagged_with("test").all(order: "RANDOM()", limit: 2)
You could make the second query return 2, and do some logic to check for equivalency
#stories = Post.tagged_with("test").all(:order => "RANDOM()", :limit => 1)
#stories2 = Post.tagged_with("test").where('post_id not in (?)', [#stories]).all(:order => "RANDOM()", :limit => 1)
#stories2.delete_at(#stories[0] == #stories2[0] ? 0 : 1);
With the above code, if the single element from the first object is the same as that of the second, we delete it and use the other. If they are not the same, we delete the "extra" story we have in the second array. At the end, each instance variable will have one item in the array, and they will not be the same.

Why does string replace modifies the original variable value?

9.3 I'm getting a strange behaviour and I cannot understand why:
s = self.shopify_p
s.title
=> "Disco (Wholesale)"
Right now I'd like to have a new variable with the content of s.title without the " (Wholesale)" part.
So I do the following:
original_title = s.title
=> "Disco (Wholesale)"
original_title[" (Wholesale)"] = ""
=> ""
Now if I do:
original_title
=> "Disco"
Which is ok but the strange thing is that it seems that the last string replace affected even the original s variable:
s.title
=> "Disco"
I really cannot understand this...can you tell me what is happening here?
s.title should still be "Disco (Wholesale)"...or not?
It is the same because you're accessing the same object.
irb(main):006:0> x = "aaaa"
=> "aaaa"
irb(main):007:0> y = x
=> "aaaa"
irb(main):008:0> x.object_id
=> 70358166435920
irb(main):009:0> y.object_id
=> 70358166435920
irb(main):010:0>
What you could do instead is
original_title = s.title.gsub(" (Wholesale)","")
After original_title = s.title both original_title and s.title reference the same object.
To actually copy the string either use Object#dup:
original_title = s.title.dup
dup → an_object
Produces a shallow copy of obj…
or String.new:
original_title = String.new(s.title)
new(str="") → new_str
Returns a new string object containing a copy of str.
Variables in ruby reference the objects they point to rather than copying them by default. So, if you change the underlying object, any changes will show up in any variables that contain a reference to that object.
If a, b, c and d all point to the same object, changes to any will "change" (be visible through) all of them.
a b c
\ | /
Object
|
d
If you want to keep your original value you'll need to somehow create a new variable.
irb(main):001:0> a = "Foo"
=> "Foo"
irb(main):002:0> b = a
=> "Foo"
irb(main):003:0> a << " Bar"
=> "Foo Bar"
irb(main):004:0> b
=> "Foo Bar"
irb(main):005:0> a
=> "Foo Bar"
irb(main):006:0> a += " Baz"
=> "Foo Bar Baz"
irb(main):007:0> a
=> "Foo Bar Baz"
irb(main):008:0> b
=> "Foo Bar"
For your case #wlad's gsub (note that he didn't use gsub!) suggestion seems like a good one.
original_title = s.title.gsub(" (Wholesale)","")

Simplify Assignment in Ruby on Rails

I just want to assign the value of variable B to variable A only if B is not nil.
And I want to simplify the code as possible.
So I found the one.
A = B if B
But variable name is long such as data[:Symbol1][:Symbol2]... , anyhow same variable name is duplicated.
Can anybody help me with simplifying this code?
You might try the presence method.
Your code would look like
A = B.presence
Example of it in action:
[1] pry(main)> b = nil
=> nil
[2] pry(main)> a = b.presence
=> nil
[3] pry(main)> a
=> nil
[4] pry(main)> b = 'foo'
=> "foo"
[5] pry(main)> a = b.presence
=> "foo"
[6] pry(main)> a
=> "foo"
I'd say you need A = B || A.
The || operator evaluates and returns the first non-false operand. If B is "truthy", it will return B (and assign it to A). If B is false, A will just be assigned itself.
2 simple ways:
a = b.presence || a
Or
a = b || a

Resources