I have an each statement in a view:
<tr><% #quantity.each do |hash| %>
<td><%= hash.map { |key, value| "Channel: #{key} Quantity: #{value} units" } %>
</td><% end %></tr>
which is rendering on the webpage with square brackets and inverted commas, thus:
["Channel: 1 Quantity: 4675 units"]
["Channel: 2 Quantity: 2864 units"]
The array of hashes that it's looping round is this:
[{2=>2864}, {1=>4675}]
How do I stop the [" from showing up on the page?
Thanks!
map maps a hash into an array. The output is what it should be. Instead of using map, try:
#quantity.each do |hash|
hash.inspect
end
Should help.
Edit in response to your comment:
#quantity.each do |hash|
hash.each do |key, value|
"Key: #{key} Value: #{value}"
end
end
Related
I have an array of hashes generated by map
arr = current_order.order_items.map{|oi|[{name:oi.name,price:oi.price}]
[{:name=>"Jacket", :price=>300},
{:name=>"Bag", :price=>650 },
{:name=>"Suit", :price=>300}].to_s
i need to make a string from it like this
name: Jacket,price:300
name: Bag,price:650
name: Suit,price:300
What i did it gsub every needed element like gsub(':size=>','size:')
but it looks very ugly
Need more convenient solution for this
You could do something like:
Define a function on a hash to pretty print it for you.
map over the array to gain pretty printed strings for each.
def pretty_print(hash)
hash.map {|key, value| "#{key}: #{value}"}.join(', ')
end
arr.map {|hash| pretty_print(hash)}
If keys are predetermined:
arr.map { |item| "name:#{ item[:name] }, price:#{ item[:price] }" }.join("\n")
If not:
arr.map { |item| item.map { |k, v| "#{ k }:#{ v }" }.join(', ') }.join("\n")
I got this very confusing array of hashes as an API response.
http://jsfiddle.net/PP9N5/
( the full response is massive. Posting only a part of it but it covers all elements of the response)
How can I get to "airlines".
I tried this
<% #flight["air_search_result"]["onward_solutions"]["solution"].each do|h| %>
<strong><%=h["pricing_summary"]["total_fare"] %></strong> -
<% h["flights"]["flight"]["segments"]["segment"].each do |s| %>
<%= s['airline'] %>
<% end %> <br> <hr>
<% end %>
And I get this error
can't convert String into Integer
I did some modifications like
<%= h["flights"]["flight"]["segments"]["segment"].first["airline"] %>
Error received - can't convert String into Integer
and
<%= h["flights"]["flight"]["segments"]["segment"][0]["airline"] %>
Error received - undefined method '[]' for nil:NilClass
Isnt there a simple way, like I say to find a key "airline" and for that key it returns its value. I stumbled upon this link, though I dont get any error, I also dont get any result.
Thanks.
UPDATE
I did this
<% h["flights"]["flight"]["segments"]["segment"].each do |o,p| %>
<% if o=="airline" %> <%= p %> <% end %>
<% end %> <br> <hr>
<% end %>
I can get few values of airlines where inside segment there is no array.
For eg, i can get where departure_date_time is 2014-07-07T07:10:00, index = 5.
http://jsfiddle.net/PP9N5/1/ (scroll down)
Here is some code you can add which will extract all keys equal the parameter in any Hash within your Hash:
class Hash
def deep_find(query, &block)
flat_map do |key, value|
if key == query
yield value if block_given?
[value]
elsif value.is_a? Hash
value.deep_find(query, &block)
elsif value.is_a? Array
value.select { |i| i.is_a? Hash }.flat_map { |h| h.deep_find(query, &block) }
end
end
end
end
Example:
hash = {"h" => [{ 'x' => [1, 5] }, { 'x' => 2 }, { 'f' => { 'x' => [3, 4] } }], 'x' => 6 }
hash.deep_find('x') { |x| puts "#{x}" }
# [1, 5]
# 2
# [3, 4]
# 6
# => [[1, 5], 2, [3, 4], 6]
it's a tipical problem :D
Replace "=>" for ":" and render.
your_json = {.....}
your_json.gsub("=>", ":")
puts your_json
You can validate a JSON before to work it with http://jsonlint.com/.
Is there a way to loop through a specific array?
For example, user.org_names returns:
["NEW", "Gold", "HEALTH SPRING"] ["Text Illinois"] ["Star Gold"] ["NEW", "Star Gold"] ["NEW", "Star Gold", "HEALTH SPRING"] ["Star Gold"] ["Star Gold"] ["Text Illinois", "Star Text", "Star Gold"] ["Text Illinois", "HEALTH SPRING"] ["NEW", "Star Gold", "Star Text"]
Now, I want to loop only through the fourth array ["NEW", "Star Gold"].
Is that a possibility in Ruby? I couldn't find such a feature.
You can use the basic array notation [] with the index as argument to get the value:
user.org_names[3] # get the 4th element of the array returned
# returns nil if does not exists
In your case, if you want to loop on the 4th element:
fourth_element = user.org_names[3]
fourth_element.each do |element|
# use element
end if fourth_element.present?
This behaves the same as:
fourth_element = user.org_names[3]
if fourth_element.present?
fourth_element.each do |element|
# use element
end
end
if after the end
1.9.3p489 :006 > [1,2,3].each do |n|
1.9.3p489 :007 > puts n
1.9.3p489 :008?> end if false
=> nil
Basically the same as doing:
[1,2,3].each{ |n| puts n } if false
But using a do/end syntax and multi-line
You can do that this way
user.org_names[3].each do |element|
puts element
end
If this is an array of arrays, maybe you could get the fourth element (user.org_names[3]) of the array and loop through it like this:
<% i = 0 %>
<% user.org_names[3].each do |a| %>
<% a[i] %>
<% i+=1 %>
<% end %>
I have an array [["Company Name", "Field6"], ["Email", "Field5"]]
And from that array I am creating array of fields with values:
[
[{:label=>"Company Name", :value=>"gfdgfd"}],
[{:label=>"Email", :value=>"gfdgfd#gfd.pl"}]
]
using
fields = [["Company Name", "Field6"], ["Email", "Field5"]]
# first element in array is Label and second is param id
fields_with_values = fields.collect do |field|
[
label: field[0],
value: params[field[1]]
]
end
and then I want to pass that labels and values to erb template(something like):
# template.erb
<% fields_with_values.each do |field| %>
l: <%= field.label %>
v: <%= field.value %>
<% end %>
How will be the best way to collect these fields_with_values ? Maybe I should use Object.new
Convert to a hash instead.
fields = [["Company Name", "Field6"], ["Email", "Field5"]]
fields_with_values = Hash[*fields.flatten]
# => {"Company Name"=>"Field6", "Email"=>"Field5"}
In your view, parse the hash:
<% fields_with_values.each do |label, value| %>
l: <%= label %>
v: <%= params[value.intern] %>
<% end %>
Note that this will break if your input array is uneven, ie. a key without a value.
EDIT
As mentioned in a comment below (+1), duplicate keys will not work. Fields that have the same label as another field are no good.
fields = [["Company Name", "Field6"], ["Email", "Field5"]]
# first element in array is Label and second is param id
fields_with_values = fields.collect do |label, param_id|
# It looks like there is no need for a nested array here, so just return a Hash
{
label: label,
value: params[param_id]
}
end
#=> [{:label=>"Company Name", :value=>"gfdgfd"}, {:label=>"Email", :value=>"gfdgfd#gfd.pl"}]
It looks like you are trying to use dot syntax to get values out of a Ruby Hash similar to how you would use dot syntax for a JavaScript object (e.g. field.label). Unfortunately this doesn't work for Ruby. I wish it did because it looks very clean. For the Ruby Hash you must use an index, which is a symbol in this case: field[:label]. Your ERB code will look something like this:
# template.erb
<% fields_with_values.each do |field| %>
l: <%= field[:label] %>
v: <%= field[:value] %>
<% end %>
The easy most basic way would be:
class Foo
attr_accessors :label, :value
def initialize (label, value)
#label = label
#value = value
end
end
fields_with_values = fields.map do |field|
Foo.new(field[0], params[field[1]])
end
from here on you can make it more Ruby way with splat operator or create the objects on the fly, etc. etc.
l:
v:
I would do
fields_with_values = fields.collect do |field|
{label: field[0], value: params[field[1]}
end
And in the view
<% fields_with_values.each do |field| %>
l: <%= field[:label] %>
v: <%= field[:value] %>
<% end %>
However, lets say label is a company and value is an e-mail. If you have a class like
class Company < SomethingOrNothing
attr_accessible :name, email
# methods here
end
You could do
#companies = fields.collect do |field|
Company.new(name: field[0], email: field[1])
end
And then
<% #companies.each do |company| %>
l: <%= comapny.name %>
v: <%= company.email %>
<% end %>
However, most likely creating a new class just for that is over engineering, unless you will use this class over and over in your code.
I have this hash:
h
=> {"67676.mpa"=>{:link=>"pool/sdafdsaff", :size=>4556}}
> h.each do |key, value|
> puts key
> puts value
> end
67676.mpa
linkpool/sdafdsaffsize4556
How do I access the separate values in the value hash on the loop?
Value is a Hash to so you need iterate on it or you can get only values:-
h.each do |key, value|
puts key
value.each do |k,v|
puts k
puts v
end
end
or
h.each do |key, value|
puts key
value.values.each do |v|
puts v
end
end
You'll want to recurse through the hash, here's a recursive method:
def ihash(h)
h.each_pair do |k,v|
if v.is_a?(Hash)
puts "key: #{k} recursing..."
ihash(v)
else
# MODIFY HERE! Look for what you want to find in the hash here
puts "key: #{k} value: #{v}"
end
end
end
You can Then take any hash and pass it in:
h = {
"x" => "a",
"y" => {
"y1" => {
"y2" => "final"
},
"yy1" => "hello"
}
}
ihash(h)
I little improved Travis's answer, how about this gist:
https://gist.github.com/kjakub/be17d9439359d14e6f86
class Hash
def nested_each_pair
self.each_pair do |k,v|
if v.is_a?(Hash)
v.nested_each_pair {|k,v| yield k,v}
else
yield(k,v)
end
end
end
end
{"root"=>{:a=>"tom", :b=>{:c => 1, :x => 2}}}.nested_each_pair{|k,v|
puts k
puts v
}
The simplest way to separate out all three values in this case would be as follows:
h.each do |key, value|
puts key
puts value[:link]
puts value[:size]
end
You can access the values of a hash directly by calling hash.values. In this case you could do something like
> h = {"67676.mpa"=>{:link=>"pool/sdafdsaff", :size=>4556}}
> h.values.each do |key, value|
> puts "#{key} #{value}"
> end
link pool/sdafsaff
size 4556