Where should I place code which generates Excel spreadsheet? - ruby-on-rails

I am using spreadsheet gem to generate native Excel file. This is not CSV, XML file. Ordinary Ruby code is used to create the file. The generated Excel file (kept in StringIO) is forwarded to a client using send_data method. I need send_data method because of its parameters like disposition.
The data for the Excel is retrieved in controller method just like for ordinary HTML, JS requests. However I placed the code to generate the spreadsheet in controller protected method. Not in a view as I should.
Is there an elegant solution to above problem compliant with MVC design pattern?
Update: There is no popular and accepted by all solution to above problem but at least I know all possible ideas.

The lib directory is meant as a place for code that isn't strictly part of the MVC structure, but will be needed by multiple models, views, or controllers. It can be brought in with a require when needed.
However, if you only need the code in a single controller, you'd be just as well off putting it into that controller's helper. That way it's auto-loaded and at your fingertips. Plus, it makes sense: it's code to help a specific controller.
Either way, don't leave it in your controller or try to wedge it into your view.

Create an excel library in your lib folder in which you include your xls generation routine as well as a method that overrides ActionController's render method.
In a model that should be rendered as xls implement a method called to_excel method which generates a hash that you can provide to your xls routine.
Doing it this way, you'll get something really "Railsy". In your controller you'll just call
render :xls => #model

i just did this today for my app hope this helps for an excel o/p ; never used any plugin
controller:
def export
pr = Program.find(session[:pr_id])
headers['Content-Type']="application/vnd.ms-excel"
headers['Content-Dispositon']='attachment;filename="report.xls"'
#voucherdatas = Voucherdata.find_all_by_pr_name(pr.pr_name)
end
view: export.html.erb
manager
"reports/voucherdatas", :object =>#voucherdatas %>
routes.rb
map.resources :reports ,:collection =>{:export =>:get}
whereever u want the link give
link_to "Export As Excel", export_reports_url, :popup=>true

Related

Call a Ruby on Rails helper method from a JavaScript js.erb file

Is it possible to call a ruby helper method from within a js.erb file?
I have a helper in application_helper.rb called solve which makes a API call to a third party service, and they only have a ruby client.
The js.erb file isn't being run on the client side, it is being called from within a controller method and run server side as it is PhantomJS.
I call the JS file from the controller
Phantomjs.run('phantom.js.erb', url)
Then within the PhantomJS js.erb file I have tried
var response = '<%= solve(variable) %>'
which just sets the variable as the string <%= solve(variable) %>
I have also tried
var response = <%= solve(variable) %>
but that just seems to make the application hang and become unresponsive.
I have seen other questions similar to this. In those questions they are asking if it is possible to call it from client side JS which I know you need to use an ajax request to do so.
Is this possible?
Try this:
var content = '#{solve()}'
Need a bit more context for this question, but I'll try my best to answer:
Essentially, you wouldn't be able to access your application_helper methods outside of any .erb files. (ie. if you have application.js or any other js file in your pipeline and you are trying to <%= solve %> from there it wouldn't work - mainly because it isn't an .erb file)
There are a lot of ways and architecture to go about solving this, but here are two simple ones:
If you put the JS you want to evaluate inline on the same page as your partial/html.erb page by using <script> //JS ERB CODE GOES HERE </script> It will actually evaluate properly since it is inside of an erb file. However, this is generally looked upon as unclean...
What you probably want to do is pass the value (presumably) you want that comes from the "solve" application_helper in a 'data' attribute on the html element that it affects. By utilizing "unobtrusive javascript" in this way, you simply pass the value through markup and then in your JS you can get the variable by using jQuery code like this. Here's an example:
<%= link_to "test_link", root_path, :data => {:solve => solve } %>
Of course it doesn't have to be a link, any HTML element will do, and then in your jQuery:
$("#test_link").data("solve");
will return to you whatever output comes out of your "solve" method in the application_helper.
it can possible but there are different ways to do it. one way is define the method in helper_method in your controller and call it from your view. and another way is use the gon gem to access some controller value in your javascript. please check what is best for you please check the below links for more help
http://apidock.com/rails/ActionController/Helpers/ClassMethods/helper_method
https://github.com/gazay/gon
http://railscasts.com/episodes/324-passing-data-to-javascript

Using the lib folder for application parts in rails

there are some problems with Ruby on Rails I couldn't solve even spending hours and hours trying. I hope you guys can help me. The four questions are marked with Q1-Q4 at beginning of line.
I have an element in the view that I need more than once. For this reason there should be a separate module in the lib folder (so I can use it in an other project too).
What I need:
- A helper method that I can call automatically from any view.
- Since it requires more html stuff, I want to use an html file, which I render in the helper-method.
- Pass parameters to a javascript file.
- If the element is used, the JavaScript file must be included
- If the element is used, the CSS file must be included
Since it isn't easy to understand what I mean, I'll explain it again with a simple example (it's just an example, so don't think to much about its sence): Helper for creating a combo box with a view-helper or alternatively with a javascript method.
Clearly, I need
(html) - a text input field placed on top of a drop down box
(js) - a function that displays the selected item of the drop-down box in the text box.
(css) - the style of the text box positioned in front of the drop down.
(settings) - a settings file that initializes the element so that I can use it everywhere automatically.
The folder structure which I imagine:
lib
combo_box
combo_box_helper.rb
_combo_box.html.erb
combo_box.js
combo_box.css
At the combo_box-helper.rb I have 2 Methods:
combo_box_field(drop_down_content)
The method gives back a combobox using the partial. The array entries are available in the drop down box.
combo_box_js(drop_down_content)
The method must be called when a combo box is to be created using javascript. To make changes to the combobox only once, the element should also be created with the partial and passed to javascript.
Here appear the first problem:
Q1: At the first call (and only on the first call) of any method, it have to include the js and css file. What is the common way to do this?
Q2: How can I render a partial that is located in the lib folder and not in the app/view folder?
Q3: What is the common way to pass parameters to javascript?
My first try:
module ComboBoxHelper
def combo_box_field(drop_down_content)
output = check_first_call
output + render(:partial => 'combo_box', :locals => {:content => drop_down_content})
end
def
output = check_first_call
output + "<div class='hidden' data-combobox = '" + render(:partial => 'combo_box', :locals => {:content => drop_down_content}) + "'></div>"
end
def check_first_call
if #already_called
""
else
#already_called = true
javascript_include_tag("combo_box.js") + stylesheet_link_tag("combo_box.css")
end
end
end
Problems:
render-method doesn't work (it searches in app/view for the partial)
the call of check_first_call is ugly. especially as it returns a string.
the includes of javascript and css don't work (the files aren't in the asset pipeline)
The content of the .html.erb and .css files is self-explanatory.
Interesting part of the javascript file is my attempt to access parameters passed by Ruby on Rails:
$('div.hidden[data-combobox]').data("combobox")
If these problems are solved, only one thing is important:
How do I initialize the module correctly, so I use it automatically everywhere.
My first try:
I create a file at the folder config/initializers/init_combo_box with that code:
require_dependency 'combo_box/combo_box_helper'
ActiveSupport.on_load(:action_view) do
include ComboBoxHelper
end
Q4: Is this the common way? Do I have something to add to solve one of the above problems (for example the add the js- and css-files to the asset pipeline)?
Thanks for your help.

Where to put reusable HTML code in rails?

I'm writing a rails app that allows users to delete records of various sorts. After pressing a delete button, I'd like to show a confirm dialog using bootstrap. I'd like to use this same dialog in several of my views, so I'll need to include the same HTML snippet in most of my pages.
I'm new to rails and I'm still learning the conventions. Can anyone suggest the best (or standard) place to put the dialog code? Should it be a partial in views/layouts/_confirm_delete_dialog.html.erb, should it go inside application.html.erb, or should I put it somewhere else?
Thanks in advance for your advice,
D.
Within your Views folder, you can create a general folder (called whatever you want). If you have a variable that you need to pass through to the general layout, you can definitely do so, but you will want to make sure that the information that you're passing through doesn't cause conflicts with the fields pulled from the model. For example, if you have two models and one has a public field but the other doesn't then you will not want to have a generic message that is using the public field. However, something like the created_at or updated_at would be okay.
You would use a code similar to,
<%= render 'general/simple_message', :f => f %>
In your views folder, you would have a directory called general and a file called _simple_message.html.erb.

how do i dynamically change my format rendering engine in rails?

My default templating engine is haml, but I would to sometimes change it to erb if i specify a specific parameter?
For example, I am pasting in some html code and would just like to test the code without HAML complaining about its format.
Any idea how to do this?
do something like:
if params[:render_erb]
render 'file.html.erb'
else
render 'file.html.haml'
end
and call the action with ?render_erb=true
or
render "file.html.#{params[:render]}" ir params[:render]
and call it ?render=haml or ?render=erb (or nothing and it will use the default
at the end of the controller's action that you are using
Am I wrong that you simply need to save file as your_file.html.erb instead of your_file.html.haml?
You can use different templates in the same application, and you can use different template engines for views, partials, and layouts, but as far as I know you can't duck in and out of multiple template engines within the same template file.
If you just want to drop some code in using a different template language, then I'd put it in a separate partial. That certainly seems easiest in this particular case.

Where should I put XML Builder code?

I am creating a method to generate an XML document via Ruby Builder.
Where should I put the method that created the XML markup? Should it be a method on the model?
I plan to have the XML document pull from multiple models via associations, so I think I need to have it in the controller or a helper, but I would like some in put on the best place.
If it's practical for you, I'd put it in your views folder. This lets you follow the traditional pattern of "load stuff in the controller; render stuff in the view," and has the extra perk of keeping what's probably a messy and very specific method in its own file and out of the way.
Now, I'm not sure if there's a Ruby Builder template format, but you could always just wrap your code in <%= ... %> and treat it like a regular ERB file - should work about the same.
Hope that helps!

Resources