I am bumping into an issue in my Rails app where a .csv export of data from a table is not formatting correctly.
First of all, here is the code that generates the .csv export...
report_controller.erb
class Admin::ReportController < ApplicationController
def index
#report = Report.all
respond_to do |format|
format.html
format.csv do
headers['Content-Disposition'] = "attachment;
filename=\"report-summary.csv\""
headers['Content-Type'] ||= 'text/csv'
end
end
end
end
index.csv.erb
<%- headers = ["Report Id", "Datetime", "Latitude", "Longitude", "Report Type"] -%>
<%= CSV.generate_line headers -%>
<%- #report.each do |report| -%>
<%- row = [report.id, report.datetime, report.latitude, report.longitude, report.report_type.report_type] -%>
<%= CSV.generate_line row -%>
<%- end -%>
As I was building this out, everything was working fine, until I got to the last column in the table, 'Report Type'. Here's what happens when that gets added:
Notice how that first entry has the HTML " leading and trailing? But the next one doesn't? And how the first one is distributed across additional headerless columns? And how the last one doesn't have the " but does have & in the middle (for an ampersand, of course)?
All of these values are stored as text in a ReportType table and they come through as strings in Rails and, as far as I can tell, there is absolutely nothing different about their data types anywhere, yet they are behaving differently when pulled out of the table.
If I take 'Report Type' out of the export, see how lovely my table is?
No skipped lines or anything!
It seems to me that these HTML characters - especially the leading and trailing double quotes - are causing at least some of the trouble here. I tried using .gsub('"', '') to remove them, but this has no effect.
Has anyone encountered this before or have any insight here?
Thanks to #tadman for pointing me in the right direction on this - I changed this line:
<%= CSV.generate_line row -%>
by adding raw like so:
<%=raw CSV.generate_line row -%>
And that did the trick. Whew!
Still, if anyone has other solutions for this, I would like to hear them.
Related
I have a rails project which is exporting some csv data into excel. On some instances excel is outputting special characters.
ex.
test 1 & test 2 & test 2
reads in excel as
test 1 & test 2 & test 2Â
My default CSV encoding is set to UTF-8 and I have played around with a number of other encoding settings although none of them have seemed to solve this issue.
Here is where the csv gets generated.
<% headers = default_headers %>
<%= CSV.generate_line(headers).strip %>
<% #activities.each do |activity| %>
<% has_permission = #_controller.is_activity_permissioned_to_user?(activity, current_user) %>
<% row = activity_generate_csv_row_data(activity, headers, has_permission, preferences) %>
<%= CSV.generate_line(row).gsub(/\A""/,'').strip.html_safe %>
<% end %>
and in my controller.
format.csv {
headers['Content-Disposition'] = "attachment; filename=\"
{report_name}.csv\""
headers['Content-Type'] ||= 'text/csv'
}
Every solution i've tried has failed. I really just can't figure out how to fix this.
Try to concatenate a Byte Order Mark string with your CSV string, like:
BOM = "\uFEFF"
def some_csv_string_generating_func
...
return BOM + a_csv_string
end
This will make Excel show the CSV file correctly.
Also, I would advice against having all the CSV generation logic/code on the view, but on a helper class/module or the like.
I want to implement a search functionality in my Rails app by using the pg_search gem. I've set up everything like it says in the documentation. Then I've set up a search controller with a show action:
def show
#pg_search_documents = PgSearch.multisearch(search_params)
end
The search itself works but I have a really annoying problem in my view. Whatever I do, it always outputs an array of PgSearch::Document objects. Even when I only write this in my view:
<%= #pg_search_documents.each do |document| %>
<% end %>
I get this (I've shortened it):
[#<PgSearch::Document id: 2, content: "…", searchable_id: 28, searchable_type: "Vessel">, #<PgSearch::Document id: 3, content: "…", searchable_id: 27, searchable_type: "Vessel">]
I know that pg_search sets up a polymorphic association which I've never dealt with before — could that be the problem?
Thanks in advance
<%= #pg_search_documents.each do |document| %>
<% end %>
This is a classic error, one I remember being puzzled over when I first started learning Rails. The mistake is using <%= %> with each. The return value of each is the array that you're iterating over (in this case, #pg_search_documents), and by using <%=, you're telling Rails to create a string from that array and insert it into your view. That generally isn't what you want: you want the view to be generated by the code inside the block you're passing to each.
Use <% #pg_search_documents.each do |document| %> instead (omitting the =) and you'll avoid the dump of the array's content.
You may also need to use .searchable as #blelump suggests, but I wanted to answer the other half of your question, as it's a common pitfall.
To get back to the original source model, searchable call is needed on these search result records, e.g:
<% #pg_search_documents.each do |document| %>
<%= document.searchable %>
<% end %>
You can also switch back to the source model within your controller, e.g:
#pg_search_documents = PgSearch.multisearch(search_params).collect(&:searchable)
Then, the #pg_search_documents will contain Vessel elements.
I am trying to create a search function in Rails 4. I have it implemented properly and it is displaying the result I want, however it is also returning and displaying the entire database query - All columns from table including password digest etc. I have done this before but haven't run into an issue like this. Would like to know if I am doing something wrong.
here is my controller:
def index
if params[:search]
#pro = Admin.search(params[:search])
else
#pro = Admin.all
end
end
Admin Model:
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
And here is my views:
<%= #pro.each do |ind| %>
<ul>
<li><%= ind.name %></li>
</ul>
<% end %>
in Chrome, I see the returned name of the individual from the search, as I would like, plus meta data such as id: 1, admin_id: 2, name "", email: "", password_digest: "" etc. in an array format. This is what's stumping me, not sure why it's displaying this.
When I inspect the page in chrome, the array is just pasted right under the tags.
It goes away when I remove the entire .each method on #pro. Any insight anyone can provide is appreciated.
The line in view should be <% #pro.each do |ind| %>. If you're doing <%= %> the result is the actual #pro array, which is why you're getting it pasted under the tags.
I have an application that allows users to enter a string, I parse it, store it in the database for historical purposes, and return some messages.
In the controller, this is how I build the messages
#messages << name + " was not created"
In the view, this is the line that it's crashing on
<% #messages.each do |msg| %>
<li> <b><%= msg %></b></li> <--- this line
<% end %>
Doing a search on the issue resulted in several solutions and explanations of why the problem occurs.
I am properly handling encoding in several places:
My application by default converts things to UTF8.
When I type in chinese characters and I render the specific token in the controller, it displays what I typed in.
When I render the concatenated string above, it displays the correct string
The database is set to UTF-8 encoding
Other pages are able to render the text correctly (they fetch from the database and display it directly without any sort of string manipulation on my part)
The issue disappears when I comment out "this line" in the View, but I don't understand what is wrong with it.
If I write this, following another suggestion, it works
<li> <b><%= msg.force_encoding("utf-8") %></b></li>
But I don't like it, since I shouldn't be having to "force" any encodings when ideally everything going in should be UTF-8 or properly converted to UTF-8, and the views can assume everything they are rendering is proper UTF-8.
I suspect that the problem is the way I am concatenating the string:
#messages << name + " was not created"
If I do a force encoding like this
#messages.size.times do |i|
#messages[i] = #messages[i].force_encoding("UTF-8")
end
That also works.
What is the proper way to concantenate strings?
What is the proper way to concantenate strings?
Using #mb_chars everywhere seems to solve such kind of issues:
#messages << name.mb_chars + " was not created"
And
<% #messages.each do |msg| %>
<li><b><%= msg.mb_chars %></b></li>
<% end %>
When i indent code in a mailer-view, i see the indentation in the sent (plain text-)mail, too. Is there a way to avoid this without writing my code without indentation…?
I have faced the same issue previously, but at that time I chose not to indent the code.
Perhaps you could make a helper method that removes indentation (assuming that you do not want indentation at all in your mail). Something like:
<% no_indentation do %>
Here goes my content.
<% if #show_extra %>
And this is some extra indented text
<% end %>
<% end %>
And then in a helper:
#some_helper.rb
module MyHelper
def no_indentation(&block)
#Capture the content of the block,
#and replace multiple spaces/tabs with a single space.
end
end
I have not tried this out myself, but it could be worth a try.