How to export a HTML file in Rails? - ruby-on-rails

I am trying to export links that are in my database into a HTML Netscape Bookmark File using Markio.
This following Ruby code is from Markio. I'm not sure how to get it to work with Rails so I can export links from my database to a file the user can download.
builder = Markio::Builder.new
builder.bookmarks << Markio::Bookmark.create({
:title => "Google",
:href => "http://google.com"
})
file_contents = builder.build_string
File.open('/path/to/bookmarks.html', 'w') { |f| f.write file_contents }
This is what I have so far in my Rails app. I am most likely going about it completely wrong because I only know how to do it with CSV and Excel. Each Link in my Rails database has a title and a url.
If I navigate to links/export in my browser it should download a file but I get the error "uninitialized constant Markio::Link".
This is my Links controller:
def export
#links = Link.all
respond_to do |format|
format.html { send_data #links.to_csv }
end
end
This is my Links model:
def self.to_csv(options = {})
builder = Markio::Builder.new
builder.bookmarks << Markio::Link.create({
:title => title,
:href => url
})
file_contents = builder.build_string
File.open('/path/to/bookmarks.html', 'w') { |f| f.write
file_contents }
end

Shouldn't Markio::Link be Markio::Bookmark? I don't see a Link object in their API.

Related

rails http response to Donwload excel file

i saw this code in github
require "csv"
csv_str = CSV.generate do |csv|
csv << ["awesome", "csv"]
end
result = IO.popen("secure-spreadsheet --password secret", "r+") do |io|
io.write(csv_str)
io.close_write
io.read
end
File.open("output.xlsx", "w") { |f| f.write(result) }
this code store a Excel file(output.xlsx) in my project file.
how can i convert this "store file scenario" in to "download the file in the browser"?
In your config/initializers/mime_types.rb register the xlsx mime_type(It is not available in Rails by default) :
Mime::Type.register "application/xlsx", :xlsx
Assuming your code that does the excel generation works and is in a controller method(private) named excel_file (I think its better to extract to a service/lib class):
def excel_file
csv_str = CSV.generate do |csv|
csv << ["awesome", "csv"]
end
IO.popen("secure-spreadsheet --password secret", "r+") do |io|
io.write(csv_str)
io.close_write
io.read
end
end
In your controller action you should be able to do something like this
def download_excel
respond_to do |format|
format.xlsx { send_data excel_file, type: 'application/xlsx; header=present', disposition: "attachment", filename: "output.xlsx" }
end
end
( ActionController#send_data "sends the given binary data to the browser". Read more via that link)
If you have a view, you can have a download link
<%= link_to "Download", your_download_path(format: "xlsx") %>
Users should be able to download the excel file via the link

How to create a file on users machine instead of creating in server and then to download using rails

I am working on to allow download an excel file with the below code:
login = Etc.getlogin
#dataFile = "C:/rails/#{login}data.csv"
csv1=CSV.open(#dataFile, 'w') do |csv|
$data.each do |eachrow|
csv << [eachrow.name+"#gmail.com"]
end
end
send_file(#dataFile, :filename => "#{login}data", :type => "application/csv")
Using the above code, I am able to create a file and write the data.
Instead of this, how do i write the data in csv and get downloaded into users machine instead of saving in local/server.
What you can do is generate a string with the CSV library, using CSV::generate instead of CSV::open.
Controller:
class DataController < ApplicationController
def download
respond_to do |format|
format.csv { send_csv_download }
end
end
private
def send_csv_download
string = CSV.generate do |csv|
#data.each { |row| csv << ["#{row.name}#gmail.com"] }
end
send_data string, filename: 'foo.csv', type: :csv
end
end
config/routes.rb:
get '/download', to: 'data#download'
View:
<%= link_to 'Download CSV', download_path(format: :csv) %>
Note: Obviously, I have no idea where you get your #data from, since it isn't specified in your question.

rails export csv return empty in production which works fine locally

I tried to export a csv file in my Rails app.
It works fine locally and if will return a csv file with data. However when push to production, it return a csv file which is empty.
Is there any possible reason about this problem?
View:
<%= link_to "Export Places", {controller: "admin/neighborhoods", action: "export_csv", format: "csv"}, 'data-no-turbolink' => true, :class => "button" %>
Route:
get 'admin_neighborhoods_export' => 'admin/neighborhoods#export_csv'
Controller:
def export_csv
#neighborhoods = Neighborhood.order(:created_at)
time = Time.now.strftime("%Y%m%d%H%M%S").to_s
respond_to do |format|
format.html
format.csv do
headers['Content-Disposition'] = "attachment; filename=\"places_export_#{time}.csv\""
headers['Content-Type'] ||= 'text/csv'
send_data(Neighborhood.to_csv(#neighborhoods), :type => "text/csv", :filename => "places_export_#{time}.csv")
end
end
end
Modal:
def self.to_csv(neighborhoods)
CSV.generate(headers: true) do |csv|
nbh_columns = []
nbh_columns.concat(column_names)
nbh_columns.concat(["maponics_neighborhood", "maponics_city", "maponics_state"])
csv << nbh_columns
neighborhoods.each do |neighborhood|
values = []
values.concat(neighborhood.attributes.values_at(*column_names))
if neighborhood.gid.present?
nbh_maponic = NeighborhoodBoundariesMaponics.find(neighborhood.gid)
values.concat([nbh_maponic.neighborhd, nbh_maponic.city, nbh_maponic.state])
else
values.concat(["", "", ""])
end
csv << values
end
end
end
Have found the reason.
There is a bad data in production db. So one error happens when I use 'find' to search a row in db.
NeighborhoodBoundariesMaponics.find(neighborhood.gid)
Now I change to use 'where' and it works.

Rails download file from show action?

I have an uploader which allows you to upload documents. What I want to do is trigger a download for the document when you view its show action. The url would be something like:
/documents/16
This document could be .txt, or .doc.
So far, my show action looks like this:
def show
#document = Document.find(params[:id])
respond_with(#document) do |format|
format.html do
render layout: false, text: #document.name
end
end
end
How would I go about achieving this?
Take a look at the send_data method:
Sends the given binary data to the browser. This method is similar to render :text => data, but also allows you to specify whether the browser should display the response as a file attachment (i.e. in a download dialog) or as inline data. You may also set the content type, the apparent file name, and other things.
So, I think in your case it should be something like this:
def show
#document = Document.find(params[:id])
send_data #document.file.read, filename: #document.name
end
I created a new method in my controller for downloading a file. It looks like this. Stored_File is the name of the archived file and has a field called stored_file which is the name of the file. Using Carrierwave, if a user has the access/permissions to download the file, the URL will display and then send the file to the user using send_file.
Controller
def download
head(:not_found) and return if (stored_file = StoredFile.find_by_id(params[:id])).nil?
case SEND_FILE_METHOD
when :apache then send_file_options[:x_sendfile] = true
when :nginx then head(:x_accel_redirect => path.gsub(Rails.root, ''), :content_type => send_file_options[:type]) and return
end
path = "/#{stored_file.stored_file}"
send_file path, :x_sendfile=>true
end
View
<%= link_to "Download", File.basename(f.stored_file.url) %>
Routes
match ":id/:basename.:extension.download", :controller => "stored_files", :action => "download", :conditions => { :method => :get }

How to parse the contents of a uploaded file in RoR

I am new to Rails.
In my project where users have to upload a file, I store it
then I have to parse the file contents and show it in new form.
I have successfully done the file uploading portion,
now how should I read the contents of it?
Try something like this:
upload = params[:your_upload_form_element]
content = upload.is_a?(StringIO) ? upload.read : File.read(upload.local_path)
Very small files can be passed as strings instead of uploaded files, therefore you should check for that and handle it accordingly.
You can open files and read their contents in Ruby using the File class, as this simple example demonstrates:
# Open a file in read-only mode and print each line to the console
file = File.open('afile.txt', 'r') do |f|
f.each do |line|
puts line
end
end
Complete Example
Take, for example, uploading an import file containing contacts. You don't need to store this import file, just process it and discard it.
Routes
routes.rb
resources :contacts do
collection do
get 'import/new', to: :new_import # import_new_contacts_path
post :import, on: :collection # import_contacts_path
end
end
Form
views/contacts/new_import.html.erb
<%= form_for #contacts, url: import_contacts_path, html: { multipart: true } do |f| %>
<%= f.file_field :import_file %>
<% end %>
Controller
controllers/contacts_controller.rb
def new_import
end
def import
begin
Contact.import( params[:contacts][:import_file] )
flash[:success] = "<strong>Contacts Imported!</strong>"
redirect_to contacts_path
rescue => exception
flash[:error] = "There was a problem importing that contacts file.<br>
<strong>#{exception.message}</strong><br>"
redirect_to import_new_contacts_path
end
end
Contact Model
models/contact.rb
def import import_file
File.foreach( import_file.path ).with_index do |line, index|
# Process each line.
# For any errors just raise an error with a message like this:
# raise "There is a duplicate in row #{index + 1}."
# And your controller will redirect the user and show a flash message.
end
end
Hope that helps others!
JP

Resources