How do I print an array in Rails? - ruby-on-rails

I am new to Rails and I am using Ruby version 1.9.3 and Rails version 3.0.0.
I want to print an array in Rails. How do I do that?
For example, we have to use print_r to print an array in PHP:
<?php
$a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x', 'y', 'z'));
print_r ($a);
?>
Output:
<pre>
Array
(
[a] => apple
[b] => banana
[c] => Array
(
[0] => x
[1] => y
[2] => z
)
)
</pre>
How do I print an array in Rails?

You can use inspect like:
#a = ['a', 'b']
p #a #['a', 'b']
Or:
p #a.inspect #"[\"a\", \"b\"]"

You need to use awesome_print gem.
require 'awesome_print'
hash = {:a=>1,:b=>2,:c => [1,2,3]}
ap hash
output:
{
:a => 1,
:b => 2,
:c => [
[0] 1,
[1] 2,
[2] 3
]
}

It depends on what you want to use the array for.
To blindly output an array in a view, which has to be in a view, you should use debug and inspect like this:
<%= #array.inspect() %>
<%= debug #array %>
However, if you want to iterate through an array, or do things like explode(), you'll be better suited using the Ruby array functions.

You've got a couple of options here. I'm assuming you're doing this in an ERB template.
This will convert the array to YAML and print it out surrounded in <pre> tags
<%= debug [1,2,3,4] %>
And this will print it out formatted in a readable Ruby syntax:
<pre><%= [1,2,3,4].inspect %></pre>
Check out "Debugging Rails Applications" for more info.

Related

add hash to hashes in ruby

final_sub_hash = {}
<% workers.each do |work| %>
<% sub_hash = {} %>
<% sub_hash = {:name => work['name'], :gender => work['gender']} %>
<% final_sub_hash.update(sub_hash) %>
<% end %>
What I am trying to do is append the values of sub_hash to final_sub_hash but I am not able to figure out how can I do that. Please help me find a solution.
hash.store(key, value) stores a key-value pair in hash.
Example:
hash #=> {"a"=>1, "b"=>2, "c"=>55}
hash["d"] = 30 #=> 30
hash #=> {"a"=>1, "b"=>2, "c"=>55, "d"=>30}
What you are trying to do is a list.
Example:
works = []
work.append(hash) #=> [ {"a"=>1, "b"=>2, "c"=>55, "d"=>30} ]
I arrived here from a search for how to add a hash to a hash. In case anyone else wonders the same, here's a nice example
# Create a hash
h = {a: 1, b: 2}
# => {:a=>1, :b=>2}
# Add a hash to the existing hash
h.store(:c, {i: 10, ii: 20})
# > {:a=>1, :b=>2, :c=>{:i=>10, :ii=>20}}
The new key can be a symbol (like :c, as above), but it could also be a string:
h.store("c", {i: 10, ii: 20})
# => {:a=>1, :b=>2, "c"=>{:i=>10, :ii=>20}}

Ruby view csv data

I'm getting from csv file some data (also how to select first 20 in csv?), for example:
A B C
D E F
also method:
def common_uploader
require 'csv'
arr = CSV.read("/#{Rails.public_path}/uploads_prices/"+params[:file], {:encoding => "CP1251:UTF-8", :col_sep => ";", :row_sep => :auto, :headers => :none})
#csv = []
#csv << arr
end
so it is array of arrays...
But how can i view it normaly in haml view?
How can i view array of arrays?
i tried something like (also in each file i have different count of columns):
view:
= #csv.first.each do |a|
= a[:1]
Help me please to view csv data.
There are several ways you can read a set number of records, and you need to pick which to use based on the anticipated size of your data source.
Starting with a CSV file:
A1,A2,A3
B1,B2,B3
C1,C2,C3
D1,D2,D3
E1,E2,E3
F1,F2,F3
The simplest ways to read a fixed number of records would be one of these:
require 'csv'
array = CSV.read('test.csv')[0, 2]
Which returns an array of two sub-arrays:
[
[0] [
[0] "A1",
[1] "A2",
[2] "A3"
],
[1] [
[0] "B1",
[1] "B2",
[2] "B3"
]
]
An alternate is:
File.new('test.csv').readlines[0, 2].map{ |l| CSV.parse(l).flatten }
Which returns the same result, an array of two sub-arrays:
[
[0] [
[0] "A1",
[1] "A2",
[2] "A3"
],
[1] [
[0] "B1",
[1] "B2",
[2] "B3"
]
]
Both of these are fine for small input files, but will have problems if you are reading a few lines from a big input file. They will force Ruby to read the entire file into memory and create an intermediate array before slicing off the number of records you want. Where I work it's nothing for us to get gigabyte file sizes, so grabbing a small section of those files would make Ruby and the system do an inordinate amount of work building the intermediate array then throwing it away.
You are better off to only read the minimum number of records needed. Sometimes lines need to be skipped before reading; This demonstrates that idea, along with handling EOFError if the input file's EOF is encountered unexpectedly:
File.open('test.csv') do |fi|
array = []
begin
5.times { fi.readline }
2.times.each{ array += CSV.parse(fi.readline) }
rescue EOFError
end
end
Replace 5 with the number of records to skip, and 2 with the number to read. For that example I deliberately read off the end of the file to show how to skip lines, read some and then handle the EOF situation cleanly.
The data looks like:
[
[0] [
[0] "F1",
[1] "F2",
[2] "F3"
]
]
Because I'm using File.open with a block, the file is closed automatically after the block exists, avoiding leaving an open filehandle hanging around.
The HAML output section of your question isn't well defined at all, but this is one way to output the data:
array = []
File.open('test.csv') do |fi|
begin
0.times { fi.readline }
2.times.each{ array += CSV.parse(fi.readline) }
rescue EOFError
end
end
require 'haml'
engine = Haml::Engine.new(<<EOT)
%html
%body
%table
- array.each do |r|
%tr
- r.each do |c|
%td= c
EOT
puts engine.render(Object.new, :array => array)
Which results in this output of a simple HTML table:
<html>
<body>
<table>
<tr>
<td>A1</td>
<td>A2</td>
<td>A3</td>
</tr>
<tr>
<td>B1</td>
<td>B2</td>
<td>B3</td>
</tr>
</table>
</body>
</html>
EDIT:
and my test file: dl.dropbox.com/u/59666091/qnt_small.csv i want to see this 7 columns in browser (via haml view)
Using this as my test data:
a1,a2,a3,a4,a5,a6,a7
b1,b2,b3,b4,b5,b6,b7
c1,c2,c3,c4,c5,c6,c7
d1,d2,d3,d4,d5,d6,d7
e1,e2,e3,e4,e5,e6,e7
and this code:
require 'csv'
array = []
File.open('test.csv') do |fi|
begin
0.times { fi.readline }
2.times.each{ array += CSV.parse(fi.readline) }
rescue EOFError
end
end
require 'haml'
engine = Haml::Engine.new(<<EOT)
%html
%body
%table
- array.each do |r|
%tr
- r.each do |c|
%td= c
EOT
puts engine.render(Object.new, :array => array)
I get this output:
<html>
<body>
<table>
<tr>
<td>a1</td>
<td>a2</td>
<td>a3</td>
<td>a4</td>
<td>a5</td>
<td>a6</td>
<td>a7</td>
</tr>
<tr>
<td>b1</td>
<td>b2</td>
<td>b3</td>
<td>b4</td>
<td>b5</td>
<td>b6</td>
<td>b7</td>
</tr>
</table>
</body>
</html>
I made a minor change to move array outside the File.open block, nothing else is different.
You can do sth like that:
arr = CSV.read("/data.csv", {:encoding => "CP1251:UTF-8", :col_sep => ",", :row_sep => :auto, :headers => :none})
i = 0
arr.each do |row|
if i == 20
break
else
i += 1
end
# do sth
puts row
end
But I think it's not a beautiful solution.
Edit:
I don't understand why you put a instance of CSV into array, you wouldn't get a each row of csv file into array
require 'csv'
def parser
CSV.open('data.csv', 'r', ';') do |row|
puts row
end

Rails print whitespace from controller

I'd like to debug a variable #num in my Rails controller, so I'm evaluating
<%= #num %>
in my Rails view. However, I cannot distinguish between #num being '', ' ', and ' ' (and other different types of whitespace) when it's printed in the HTML. Is there any way to print it out clearly?
If you want to be really sure:
<%= #num.inspect %>
When #num = ' ' this should render:
" "
#inspect is great when you want to a representation of some object as a string.
If this is a complex object or large array or deep hash, I often prefer #to_yaml for inspection which lays it out in a somewhat readable format.
# controller
#foo = {:a => [:bar, :baz], :b => 123, :c => 'omg'}
# view
<pre><%= #foo.to_yaml %></pre>
# visible output
---
:b: 123
:c: omg
:a:
- :bar
- :baz
<%=debug #num %>
Will format it in haml.
<%= #num.inspect %>
Will format it as "p" does.
See Debugging Rails Applications (rails guides)

How to parse key name with name(value) pairs into hash of key/value pairs with original value?

I have a large hash like this:
{"id"=>"1",
"contact_id"=>"15062422",
"status"=>"Complete",
"[question(12), option(24), piped_page(32]" => "Yes",
"[question(13), option(32)]" => "Robert",
"[question(14)]" => "Thing"}
I need to parse the keys that start with '[' to separate the name(value) pairs. The number of names (i.e. question, option, etc) in each key is variable but there are a known number of possibilities.
I'd like to convert each pair into a new has like this:
{:question => 12, :option => 24, :piped_page => 32, :value => "Yes"}
I've thought of using .to_s on each hash element and then doing a variety of string substitutions followed by eval, but the .to_s escapes the double quotes which really complicates things.
Any ideas?
You can use regex to solve it:
str = "[question(12), option(24), piped_page(32)]"
Hash[str.scan /(\w+)\((\w+)\)/]
=> {"question"=>"12", "option"=>"24", "piped_page"=>"32"}

Ruby on Rails: Interpreting a form input as an integer

I've got a form that allows the user to put together a hash.
The hashes desired end format would be something like this:
{1 => "a", 2 => "x", 3 => "m"}
I can build up something similar by having lots of inputs that have internal brackets in their names:
<%= hidden_field_tag "article[1]", :value => a %>
However, the end result is that builds a hash where all the keys are strings and not integers:
{"1" => "a", "2" => "x", "3" => "m"}
I'm currently fixing this by generating a new hash in the controller by looping over the input hash, and then assigning that to params. Is there a cleaner, DRYer way to do this?
Your params will always come in with string keys and values. The easiest way to fix this is to either write your own extension to Hash or simply inject as required:
numeric_keys = params['article'].inject({ }) do |h, (k, v)|
h[k.to_i] = v
h
end
Then you have a hash with the keys converted to integer values, as you like.
A simple extension might be:
class Hash
def remap_keys
inject({ }) do |h, (k, v)|
h[yield(k)] = v
h
end
end
end
This is much more generic and can be used along the lines of:
params['article'].remap_keys(&:to_i)
That depends a bit what you want to use it for. Maybe it is easier to just use strings as keys, and do the "conversion" when accessing the array (or not at all)?
It is also possible to build an array using something like
<%= hidden_field_tag "article[]", :value => "x" %>
this will return "article" as an array, and you can access it directly by index. However, there is no way to influence the position - the array will contain all values in order of appearance.
Lastly, you can make your own version of Hash or just modify the keys, as has been explained.

Resources