Rails create file and render

2019-09-20 13:46发布

问题:

In rails, is there a way (in a controller) to:

  1. create a file

  2. render a view or template to that file

  3. redirect_to or render another view

I've tried all kinds of constructions, but keep getting the same error: Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action.

Otherwise; is it possible to render a template or view to a file without displaying that template/view?

thnx!

code:

def get_report

# part 1: create and render file for use with phantomjs 

File.new('./vendor/assets/javascripts/graph_disk1.json','w') {|f| f.write(render "reports/disk", :layout => false)}
system `phantomjs ./vendor/assets/javascripts/highcharts-convert.js -infile ./vendor/assets/javascripts/graph_disk1.json -outfile ./app/assets/images/chart01.png -options ./vendor/assets/javascripts/resources.json`    

# part 2: create odf-report and use image created bij phantomjs/highcharts-convert

report = ODFReport::Report.new("#{Rails.root}/app/report_templates/PSC2_KalScanV0.odt") do |r|
  r.add_image :graphd1, "#{Rails.root}/app/assets/images/chart01.png" 
  send_data report.generate, type: 'application/vnd.oasis.opendocument.text',
                        disposition: 'attachment',
                          filename: 'report.odt'
  end

end

the 2 parts work each, but not when called liked this (in 1 action/controller).

回答1:

The solution is always easy once you've found it:

Instead of: f.write(render "reports/disk", :layout => false),

Use: f.write(render_to_string "reports/disk", :layout => false)

and voila, no more error



回答2:

it seems you tried to create custom routes with render different file other than rails way, let me give you sample case, for example you have client controller but then you want to create custom method and routes other than 7 standard rails way

rails generate controller clients

inside routes.rb

resources :clients do
  collection {
    get  :check_data  # this to get data 
    post :import_data # this to post data 
  }
}
# prease remove all other routes for client controller that usually generated with get

inside app/controllers/client_controller.rb create two method for route above

def check_data
  ...
  # the default view file is /views/clients/check_data.html.erb
  # but you may also type like this below to render other file
  # please note the first thing you must mention controllers name then the file name
  render "clients/noname.html.erb" 
end

def import_data
  ...
  #
  # here after client saved, it goes to other path instead of default 
  if @client.save
    redirect_to courses_path
  end
end