Sinatra Display CSV entries - ruby

How do I display data from a csv file into a Sinatra-App?
Sinatra:
csv = CSV.read(data.csv)
csv.each do |entry|
#output = "#{entry[1]},#{entry[4]}:#{entry[0]}"
end
Erb:
<%= #data %>
Which displays only the last row of the csv file.

Problem
With this code :
csv = CSV.read(data.csv)
csv.each do |entry|
#output = "#{entry[1]},#{entry[4]}:#{entry[0]}"
end
You iterate over all csv rows.
For each row, the block defines the #output variable.
After the first csv line, the code just keeps on overriding the #output_variable.
Possible solution
You need map, not each.
csv = CSV.read(data.csv)
#data = csv.map do |entry|
"#{entry[1]},#{entry[4]}:#{entry[0]}"
end
You can then use
<%= #data %>
in your views. #data is now an array of strings, with one string for each csv row.

You probably want to move the for loop to the template file.
In sinatra
#csv_data = CSV.read(data.csv)
In erb
<% #csv_data.each do |entry| %>
<%= entry[1] %>,<%= entry[4] %>:<%= entry[0] %>
<% end %>

Related

Ruby CSV separates numbers by a comma and is not escaping it

When I generate a csv file in Ruby, the Ruby CSV library is separating out the numbers based on its thousands comma. For example numbers such $5.00 stay in their own cell, while numbers like $257,000,415.81 will instead be surrounded in double quotes and get split up on the thousands comma into the next cell. example ("$257 | 000 | 415.81"). The csv parses the number correctly as long as it is not the first value. How do I get the csv library to properly format the number in the same cell? The program i'm using to open the csv file is Microsoft Excel.
Here is a screen shot of how the text looks in excel.
http://i.stack.imgur.com/8EMs0.png
And here is a screen shot of how I would like the text to look.
http://i.stack.imgur.com/opjrR.png
Below is the code for the csv.
<%= CSV.generate_line(["Balance"]).strip %>
<% #accounts.each do |acct| %>
<% row = [
(number_to_currency acct.balance, :unit => "$")
] %>
<%= CSV.generate_line(row).strip.html_safe %>
<% end %>
This should work to create the CSV file correctly:
CSV.open('filename.csv', 'w') do |csv|
#accounts.each do |acct|
csv << [ number_to_currency(acct.balance, unit: '$') ]
end
end

Ruby - trying to make hashtags within string into links

I am trying to make the hashtags within a string into links.
e.g. I'd like a string that's currently: "I'm a string which contains a #hashtag" to transform into: "I'm a string which contains #hashtag"
The code that I have at the moment is as follows:
<% #messages.each do |message| %>
<% string = message.content %>
<% hashtaglinks = string.scan(/#(\d*)/).flatten %>
<% hashtaglinks.each do |tag| %>
<li><%= string = string.gsub(/##{tag}\b/, link_to("google", "##{tag}") %><li>
<% end %>
<% end %>
I've been trying (in vain) for several hours to get this to work, reading through many similar stackoverflow threads- but frustration has got the better of me, and as a beginner rubyist, I'd be really appreciate it if someone could please help me out!
The code in my 'server.rb' is as follows:
get '/' do
#messages = Message.all
erb :index
end
post '/messages' do
content = params["content"]
hashtags = params["content"].scan(/#\w+/).flatten.map{|hashtag|
Hashtag.first_or_create(:text => hashtag)}
Message.create(:content => content, :hashtags => hashtags)
redirect to('/')
end
get '/hashtags/:text' do
hashtag = Hashtag.first(:text => params[:text])
#messages = hashtag ? hashtag.messages : []
erb :index
end
helpers do
def link_to(url,text=url,opts={})
attributes = ""
opts.each { |key,value| attributes << key.to_s << "=\"" << value << "\" "}
"<a href=\"#{url}\" #{attributes}>#{text}</a>"
end
end
Here is the code to get you started. This should replace (in-place) the hashtags in the string with the links:
<% string.gsub!(/#\w+/) do |tag| %>
<% link_to("##{tag}", url_you_want_to_replace_hashtag_with) %>
<% end %>
You may need to use html_safe on the string to display it afterwards.
The regex doesn't account for more complex cases, like what do you do in case of ##tag0 or #tag1#tag2. Should tag0 and tag2 be considered hashtags? Also, you may want to change \w to something like [a-zA-Z0-9] if you want to limit the tags to alphanumerics and digits only.

JSON will not display

I have a Sinatra application that should get image URLs from a JSON file and put them into HTML <img> tags.
I can parse through the JSON just fine when I print it to the command line, but when I use ERB to place the data, it won't show.
I put it in <ul> tags and got only the bullet points for every image in the JSON file.
Here is my code:
app.rb:
get "/" do
file = open("./images.json")
json = file.read
#parsed = JSON.parse(json)
erb :roar
##parsed.each do |roar|
# p roar["url"]
#end
end
Roar.erb:
<ul>
<% #parsed.each do |shop| %>
<li> <%shop["url"] %> </li>
<% end %>
</ul>
Are you not just missing an "=" here :
<li> <%= shop["url"] %> </li>
Just some comments on the code in general:
Don't use:
file = open("./images.json")
json = file.read
#parsed = JSON.parse(json)
Instead, use:
json = File.open("./images.json") do |fi|
fi.read
end
#parsed = JSON.parse(json)
Or:
json = File.open("./images.json") { |fi| fi.read }
#parsed = JSON.parse(json)
Or:
json = File.read("./images.json")
#parsed = JSON.parse(json)
Or:
#parsed = JSON.parse(File.read("./images.json"))
The reasons are:
file = open("./images.json") opens the file but never closes it. That's not good form, and it's also not idiomatic Ruby. The first two replacements automatically close the opened file.
Using File.read returns the contents of the file just as opening it and reading in a separate step, only it's all in one step. The file is also automatically closed afterwards.

Ruby Each Loop Variable Substitution

I'm trying to set all the values to 0 but the 3rd line (send(x)) is giving me problems. Seems right to me, but doesn't work. x is the car and name of the columns in Power. Any tips?
<% #cars.each do |x| %>
<% #power = Power.find_by_user_id(#user) %>
<% #power.send(x) = 0 %>
<% #power.save %>
<% end %>
Assuming #cars contains column names of Power, you need to send the setter method (i.e. with an = at the end). You also need to ensure you're passing a symbol to send.
#cars.each do |x|
#power = Power.find_by_user_id(#user)
#power.send(:"#{x}=", 0)
#power.save
end
There's also not an obvious reason why you need to set or save #power in the loop, so it might be better as:
#power = Power.find_by_user_id(#user)
#cars.each do |x|
#power.send(:"#{x}=", 0)
end
#power.save

Word Count with Ruby

I am trying to figure out a way to count a words in a particular string that contains html.
Example String:
<p>Hello World</p>
Is there a way in Ruby to count the words in between the p tags? Or any tag for that matter?
Examples:
<p>Hello World</p>
<h2>Hello World</h2>
<li>Hello World</li>
Thanks in advance!
Edit (here is my working code)
Controller:
class DashboardController < ApplicationController
def index
#pages = Page.find(:all)
#word_count = []
end
end
View:
<% #pages.each do |page| %>
<% page.current_state.elements.each do |el| %>
<% #count = Hpricot(el.description).inner_text.split.uniq.size %>
<% #word_count << #count %>
<% end %>
<li><strong>Page Name: <%= page.slug %> (Word Count: <%= #word_count.inject(0){|sum,n| sum+n } %>)</strong></li>
<% end %>
Here's how you can do it:
require 'hpricot'
content = "<p>Hello World...."
doc = Hpricot(content)
doc.inner_text.split.uniq
Will give you:
[
[0] "Hello",
[1] "World"
]
(sidenote: the output is formatted with awesome_print that I warmly recommend)
Sure
Use Nokogiri to parse the HTML/XML and XPath to find the element and its text value.
Split on whitespace to count the words
You'll want to use something like Hpricot to remove the HTML, then it's just a case of counting words in plain text.
Here is an example of stripping the HTML: http://underpantsgnome.com/2007/01/20/hpricot-scrub/
First start with something able to parse HTML like Hpricot, then use simple regular expression to do what you want (you can merely split over spaces and then count for example)

Resources