How to get "key" from params? - ruby-on-rails

<%= params[:select] %> # key=qwerty secret=qwerty token=qwerty token_secret=qwerty
Please tell me how I can get "key" ? I do not understand:
<%= params{[:select[:key]]} %> # {"tweet"=>"", "select"=>"key=qwerty secret=qwerty token=qwerty token_secret=qwerty", "controller"=>"twitter_postings", "action"=>"index"}

You can access to the select key and over its value to split the content, getting the first one you have "key":
params = {
"tweet"=>"",
"select"=>"key=qwerty secret=qwerty token=qwerty token_secret=qwerty",
"controller"=>"twitter_postings",
"action"=>"index"
}
p params['select'].split.first
# "key=qwerty"
You can also turn it into a hash if it's easier for you:
select_hash = params['select'].split.each_with_object(Hash.new(0)) do |element, hash|
key, value = element.split('=')
hash[key] = value
end
p select_hash['key']
# "qwerty

Hope this will helping you.
params = {
"tweet"=>"",
"select"=>"key=qwerty secret=qwerty token=qwerty token_secret=qwerty",
"controller"=>"twitter_postings",
"action"=>"index"
}
for getting key value (qwerty) from this params following query will helping you.
params["select"].split.first.split("=").second
# => "qwerty"
steps: 1
params["select"].split
# => ["key=qwerty", "secret=qwerty", "token=qwerty", "token_secret=qwerty"]
find the value and split them
steps: 2
params["select"].split.first.split("=")
# => ["key", "qwerty"]
pick first value and split again with =
steps: 3
params["select"].split.first.split("=").second
# => "qwerty"
finally pick the second value.

Related

Ruby creating a new hash from an array of key, value

first_response = [
{"xId" => "123", "yId" => "321"},
{"xId" => "x", "yId" => "y" }
]
first_response.each do |resp|
x_id = resp['xId']
y_id = resp['yId']
puts x_id.to_s
puts y_id.to_s
end
This gives me outputs
123
321
x
y
output hash I want to create is
{123=>{321}, x=>{y}}
first service: I have an array of hash that has two different ids example:(x_id and y_id) (there would be multiple pairs like that in the response)
I want to create a hash that should contain the matching pair of x_id and y_ids that we get from the first service with x_id's as the key for all the pairs.
If you know every hash in first_response is going to contain exactly two key/value pairs, you can extract their values and then convert that result into a hash (see Enumerable#to_h):
first_response.to_h(&:values)
# {"123"=>"321", "x"=>"y"}
Looks like this approach works, but I am not completely sure if that is right
first_response = [{"xId"=>"123","yId"=> "321"}, {"xId"=>"x","yId"=> "y"}]
h = {}.tap do |element|
first_response.each do |resp|
x_id = resp['xId']
y_id = resp['yId']
element[x_id] = y_id
end
end
puts h.to_s
# {"123"=>"321", "x"=>"y"}

Ruby convert all values in a hash to string

I have the following snippet of code to fetch certain columns from the db:
#data = Topic.select("id,name").where("id in (?)",#question.question_topic.split(",")).map(&:attributes)
In the resulting Array of Hashes which is :
Current:
#data = [ { "id" => 2, "name" => "Sports" }]
To be changed to:
#data = [ { "id" => "2", "name" => "Sports" }]
I want to convert "id" to string from fixnum. Id is integer in the db. What is the cleanest way to do this?
Note: After using .map(&:attributes) it is not an active record relation.
You can do it with proper map usage:
topics = Topic.select("id,name").where("id in (?)",#question.question_topic.split(","))
#data = topics.map do |topic|
{
'id' => topic.id.to_s,
'name' => topic.name
}
end
What you're looking for is simply
#data.each { |obj| obj["id"] = obj["id"].to_s }
There isn't really a simpler way (I think that's straightforward enough anyway).
Going by the title which implies a different question - converting every value in the hash to a string you can do this:
#data.each do |obj|
obj.map do |k, v|
{k => v.to_s}
end
end
Just leaving that there anyway.
You can use Ruby's #inject here:
#data.map do |datum|
new_datum = datum.inject({}) do |converted_datum, (key, value)|
converted_datum[key] = value.to_s
converted_datum
end
end
This will work to convert all values to strings, regardless of the key.
If you are using Rails it can be even cleaner with Rails' #each_with_object:
#data.map do |datum|
datum.each_with_object({}) do |(key, value), converted_datum|
converted_datum[key] = value.to_s
end
end
This will iterate all the key names in the hash and replace the value with the #to_s version of the datum associated with the key. nil's converted to empty strings. Also, this assumes you don't have complex data within the hash like embedded arrays or other hashes.
def hash_values_to_string(hash)
hash.keys.each {|k| hash[k]=hash[k].to_s}; hash
end

Ruby Array conversion best way

What is the best way to achieve the following, I have following array of actions under ABC
ABC:-
ABC:Actions,
ABC:Actions:ADD-DATA,
ABC:Actions:TRANSFER-DATA,
ABC:Actions:EXPORT,
ABC:Actions:PRINT,
ABC:Detail,
ABC:Detail:OVERVIEW,
ABC:Detail:PRODUCT-DETAIL,
ABC:Detail:EVENT-LOG,
ABC:Detail:ORDERS
I want to format this as:
ABC =>{Actions=> [ADD-DATA,TRANSFER-DATA,EXPORT,PRINT], Detail => [Overview, Product-detail, event-log,orders]}
There's probably a ton of ways to do it but here's one:
a = ["ABC:Actions",
"ABC:Actions:ADD-DATA",
"ABC:Actions:TRANSFER-DATA",
"ABC:Actions:EXPORT",
"ABC:Actions:PRINT",
"ABC:Detail",
"ABC:Detail:OVERVIEW",
"ABC:Detail:PRODUCT-DETAIL",
"ABC:Detail:EVENT-LOG",
"ABC:Detail:ORDERS"]
a.map { |action| action.split(":") }.inject({}) do |m, s|
m[s.at(0)] ||= {}
m[s.at(0)][s.at(1)] ||= [] if s.at(1)
m[s.at(0)][s.at(1)] << s.at(2) if s.at(2)
m
end
The map call returns an array where each of the strings in the original array have been split into an array of elements that were separated by :. For example [["ABC","Actions","ADD-DATA"] ... ]
The inject call then builds up a hash by going through each of these "split" arrays. It creates a mapping for the first element, if one doesn't already exist, to an empty hash, e.g. "ABC" => {}. Then it creates a mapping in that hash for the second element, if one doesn't already exist, to an empty array, e.g. "ABC" => { "Detail" => [] }. Then it adds the third element to that array to give something like "ABC" => { "Detail" => ["OVERVIEW"] }. Then it goes onto the next "split" array and adds that to the hash too in the same way.
I will do this as below :
a = ["ABC:Actions",
"ABC:Actions:ADD-DATA",
"ABC:Actions:TRANSFER-DATA",
"ABC:Actions:EXPORT",
"ABC:Actions:PRINT",
"ABC:Detail",
"ABC:Detail:OVERVIEW",
"ABC:Detail:PRODUCT-DETAIL",
"ABC:Detail:EVENT-LOG",
"ABC:Detail:ORDERS"]
m = a.map{|i| i.split(":")[1..-1]}
# => [["Actions"],
# ["Actions", "ADD-DATA"],
# ["Actions", "TRANSFER-DATA"],
# ["Actions", "EXPORT"],
# ["Actions", "PRINT"],
# ["Detail"],
# ["Detail", "OVERVIEW"],
# ["Detail", "PRODUCT-DETAIL"],
# ["Detail", "EVENT-LOG"],
# ["Detail", "ORDERS"]]
m.each_with_object(Hash.new([])){|(i,j),ob| ob[i] = ob[i] + [j] unless j.nil? }
# => {"Actions"=>["ADD-DATA", "TRANSFER-DATA", "EXPORT", "PRINT"],
# "Detail"=>["OVERVIEW", "PRODUCT-DETAIL", "EVENT-LOG", "ORDERS"]}
It was just interesting to do it with group_by :)
a = ['ABC:Actions',
'ABC:Actions:ADD-DATA',
'ABC:Actions:TRANSFER-DATA',
'ABC:Actions:EXPORT',
'ABC:Actions:PRINT',
'ABC:Detail',
'ABC:Detail:OVERVIEW',
'ABC:Detail:PRODUCT-DETAIL',
'ABC:Detail:EVENT-LOG',
'ABC:Detail:ORDERS']
result = a.map { |action| action.split(":") }.group_by(&:shift)
result.each do |k1,v1|
result[k1] = v1.group_by(&:shift)
result[k1].each { |k2,v2| result[k1][k2] = v2.flatten }
end
p result
{"ABC"=>{"Actions"=>["ADD-DATA", "TRANSFER-DATA", "EXPORT", "PRINT"], "Detail"=>["OVERVIEW", "PRODUCT-DETAIL", "EVENT-LOG", "ORDERS"]}}

Kind of ugly- default value for non-existent hash key?

I'm working with an API that returns a hash to represent a product:
prod = API.getProduct(id)
prod["name"] => "Widget"
The problem arrises because not all products contain identical attribute pages, so I find myself doing a lot of one-off error catching- some products will have a key for size or color, some won't.
What's the easiest way to get to prod["non-existent attribute"] => "NA"?
As Dave Newton said, you can add the default value to the hash constructor:
hash = Hash.new { |hash, key| hash[key] = "NA" }
hash[:anything] == "NA" # => true
Or use the #default method:
hash = Hash.new
hash.default = "NA"
hash[:anything] == "NA" # => true
EDIT The quick syntax for setting the default value when initializing the hash is:
hash = Hash.new("NA")
hash[:anything] == "NA" # => true
Take a look at this: http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-default
You can use prod.default = "NA".

Ruby way to loop and check subsequent values against each other

I have an array that contains dates and values. An example of how it might look:
[
{'1/1/2010' => 'aa'},
{'1/1/2010' => 'bb'},
{'1/2/2010' => 'cc'},
{'1/2/2010' => 'dd'},
{'1/3/2010' => 'ee'}
]
Notice that some of the dates repeat. I'm trying to output this in a table format and I only want to show unique dates. So I loop through it with the following code to get my desired output.
prev_date = nil
#reading_schedule.reading_plans.each do |plan|
use_date = nil
if plan.assigned_date != prev_date
use_date = plan.assigned_date
end
prev_date = plan.assigned_date
plan.assigned_date = use_date
end
The resulting table will then look something like this
1/1/2010 aa
bb
1/2/2010 cc
dd
1/3/2010 ee
This work fine but I am new to ruby and was wondering if there was a better way to do this.
Enumerable.group_by is a good starting point:
require 'pp'
asdf = [
{'1/1/2010' => 'aa'},
{'1/1/2010' => 'bb'},
{'1/2/2010' => 'cc'},
{'1/2/2010' => 'dd'},
{'1/3/2010' => 'ee'}
]
pp asdf.group_by { |n| n.keys.first }.map{ |a,b| { a => b.map { |c| c.to_a.last.last } } }
# >> [{"1/1/2010"=>["aa", "bb"]}, {"1/2/2010"=>["cc", "dd"]}, {"1/3/2010"=>["ee"]}]
Which should be a data structure you can bend to your will.
I don't know as though it's better, but you could group the values by date using (e.g.) Enumerable#reduce (requires Ruby >= 1.8.7; before that, you have Enumerable#inject).
arr.reduce({}) { |memo, obj|
obj.each_pair { |key, value|
memo[key] = [] if ! memo.has_key?(key);
memo[key] << value
}
memo
}.sort
=> [["1/1/2010", ["aa", "bb"]], ["1/2/2010", ["cc", "dd"]], ["1/3/2010", ["ee"]]]
You could also use Array#each to similar effect.
This is totally a job for a hash.
Create a hash and use the date as the hashkey and an empty array as the hashvalue.
Then accumulate the values from the original array in the hashvalue array

Resources