Rails AJAX insert partial into div - ruby-on-rails-3

I have a lot of data in a model that needs many forms to edit. What I've done is create a page that takes options like ?id=something&otheroption=something else and renders the correct edit form based on those inputs. Now, I am trying to create the actual edit page. The plan is for the user to select the "id" and "otheroption" from a drop down, and then an AJAX call will update a DIV with the correct form.
What I need to to is put this into a partial in someway where I can send an AJAX request to, have rails process the options, render the partial, and return the AJAX request. How do I do that with JQuery?

What I do is create a controller action with a js response that then renders a partial. As an example:
HTML
<div id="div_id"></div>
Controller
def ajax_responder
#data = query
respond_to do |format|
format.js
end
end
JS partial
jQuery("#div_id").html("<%= escape_javascript(render "html_partial") %>");
HTML Partial
whatever your html partial with data would be
This may suck mightily... I am open to feedback.

Related

How can I call a controller/view action from a mailer?

In my rails application I've created a business daily report. There is some non-trivial logic for showing it (all kind of customizable parameters that are used for filtering in the model, a controller that calls that model and some non-trivial view for it, for example, some of the columns are row-spanning over several rows).
Now I wish to send this report nightly (with fixed parameters), in addition to the user ability to generate a customize report in my web site. Of course, I wish not to re-write/duplicate my work, including the view.
My question is how can I call the controller action from my mailer so that it will be as if the page was requested by a user (without sending a get request as a browser, which I wish to avoid, of course)?
In answer to your question is if you are generating some sort of pdf report then go with using the wicke_pdf gem does exactly that generates pdfs. To send a report on a nightly basis the best thing for this is to implement some sort of cron job that runs at a particular time which you can do using the whenever gem. You can do something like:
schedule.rb
every :day, :at => '12:00am'
runner User.send_report
end
With this at hand you can see that you call the send_report method sits inside the User model class as shown below:
User.rb
class User < ActiveRecord::Base
def self.send_report
ReportMailer.report_pdf(#user).deliver
end
end
Inside send_report we call the mailer being ReportMailer which is the name of the class for our mailer and the method being report_pdf and pass in the user. BUT remember this is an example I have here I am not sure the exact specified information you want in a report.
Mailer
class ReportMailer< ActionMailer::Base
default :from => DEFAULT_FROM
def report_pdf(user)
#user = user
mail(:subject => "Overtime", :to => user.email) do |format|
format.text # renders report.text.erb for body of email
format.pdf do
attachments["report.pdf"] = WickedPdf.new.pdf_from_string(
render_to_string(:pdf => "report",:template => 'report/index.pdf.erb',
:layouts => "pdf.html"))
end
end
end
end
Inside the mailer there are a variety of things going on but the most important part is inside the format.pdf block that uses a variety of wicked_pdf methods (this is assuming that you are using wicked_pdf btw. Inside the block you create a new WickedPDF pdf object and render it to a string. Then provide it with the name of the report, the template and the layout. It is important that you create a template. This usually will where the report will be displaying from. The file type is a .pdf.erb this means that when this view or report is generated in the view the embedded ruby tags are being parsed in and the output is going to be a pdf format.
UserController
def report
#user = User.scoped
if params[:format] == 'pdf'
#Do some stuff here
User.send_report(#users)
end
respond_to do |format|
format.html
format.pdf do
render :pdf => "#{Date.today.strftime('%B')} Report",
:header => {:html => {:template => 'layouts/pdf.html.erb'}}
end
end
end
The key thing you asked that I picked up on.
how can I call the controller action from my mailer
In the controller simply collate a scope of Users, then check the format is a pdf, providing it is do some stuff. Then it will run the method send_report which I earlier highlighted in the user model class (Btw in your words this is the controller calling the model). Then inside the respond block for this there is a format.pdf so that you can generate the pdf. Once again note that you need a template for the core design of the pdf, which is similar to how rails generates an application.html.erb in the layouts. However here we have a pdf.html.erb defined. So that this can be called anywhere again in your application should you want to generate another pdf in your application somewhere else.
Think I've provided a substantial amount of information to set you off in the right direction.

Rails 3 form actions and methods

I have made a resource.
resources :dashboards
I have a partial file which contains a form and I want to use this partial (as the form elements won't change) to update and create. So here is what I have:
Controller
class DashboardsController < ApplicationController
def new
#dashboard = Dashboard.new
end
end
View
/dashboards/new.html.erb
<%= render :partial => "form", :locals => { :dashboard => #dashboard } %>
Partial Form
/dashboards/_form.html.erb
<%= form_for(#dashboard) do |form| %>
.....
<% end %>
Ruby Guide
The Ruby Guide states:
The Article model is directly available to users of the application, so — following the best practices for developing with Rails — you should declare it a resource. When dealing with RESTful resources, calls to form_for can get significantly easier if you rely on record identification. In short, you can just pass the model instance and have Rails figure out model name and the rest. For example:
## Creating a new article
# long-style:
form_for(#article, :url => articles_path)
# same thing, short-style (record identification gets used):
form_for(#article)
## Editing an existing article
# long-style:
form_for(#article, :url => article_path(#article), :html => { :method => "put" })
# short-style:
form_for(#article)
Result
I thought I have followed the Rails Guide correctly. Because I made #dashboard a resource. I could just pass it into the form and have it handle the action, method and the rest. Instead I'm getting this:
<form accept-charset="UTF-8" action="/dashboards" class="new_dashboard" id="new_dashboard_" method="post">
According to the docs. Shouldn't the action of my form now be "/dashboards/new" because we are on the new action? And should it be passing an extra field declaring the method to be put when I use the same code in the /edit action??
My result is always the same no matter what. The form never changes.
What am I doing wrong?
EDIT
Here is my router info from rake routes
GET /dashboards(.:format) dashboards#index
POST /dashboards(.:format) dashboards#create
GET /dashboards/new(.:format) dashboards#new
GET /dashboards/:id/edit(.:format) dashboards#edit
GET /dashboards/:id(.:format) dashboards#show
PUT /dashboards/:id(.:format) dashboards#update
DELETE /dashboards/:id(.:format) dashboards#destroy
You are correct that you should be able to "pass #dashboard into the form and have it handle the action, method and the rest." The issue here is what new is in the context of RESTful actions.
When you declare a set of resources with resources :dashboards, you are creating a set of routes which map requests to controller actions:
GET /dashboards index
GET /dashboards/new new
POST /dashboards create
GET /dashboards/:id show
GET /dashboards/:id/edit edit
PUT /dashboards/:id update
DELETE /dashboards/:id destroy
You can check this if you run rake routes.
The issue here is that the new action is defined as a GET request to the path /dashboards/new, i.e. this is the route for the form itself. The URL in the action attribute of the actual form is something else: this is where the form will post the data to with a POST request, which on the server (rails) side will map to the create controller action.
When you use the form helper with form_for(dashboard), a form is created with a route corresponding to what dashboard is: if it is a new record (i.e. it does not yet exist in the database), then the form action will be create (and point to /dashboards), whereas if it already exists it will point to the actual URL for the record (e.g. /dashboards/123). This is what makes the form helpers so useful.
So, to sum up, /dashboards is the correct URL, not for the new action but for the create action, which the form helper uses because dashboard is a new record. new is the route to the page where the form resides, i.e. /dashboards/new.
Hope that makes sense.
p.s. as a side note, you shouldn't be accessing #dashboard in the partial if you are passing it in as a local (:locals => { :dashboard => #dashboard }). Just use dashboard.

rails 3 single table inheritance with multiple forms

I have set up a rails application that uses single table inheritance but I need to have a distinct form for my child classes. The application keeps a collection of indicators of security compromise, such as malicious IP addresses. So I have a class called Indicator which holds most of the information. However, if the indicator is a malware hash I need to collect additional information. So I created another class called MalwareIndicator which inherits from Indicator. Everything is working fine with that.
I wanted my routes to be restful and look nice so I have this in my config/routes.rb file
resources :indicators
resources :malware, :controller => "indicators", :type => "MalwareIndicator"
That works very nicely. I have all these routes that point back to my single controller. But then in the controller I'm not sure how to handle multiple forms. For example, if someone goes to malware/new the Indicators#New function is called and it is able to figure out that the user wants to create a MalwareIndicator. So what must my respond_to block look like in order to send the user to the correct form? Right now it still sends the user to the new indicator form.
def new
if params[:type] == "MalwareIndicator"
#indicator = MalwareIndicator.new
else
#indicator = Indicator.new
end
#pagename = "New Indicator(s)"
respond_to do |format|
format.html # new.html.erb
format.json { render json: #indicator }
end
end
I feel like I'm pretty close. On the other hand, I might be doing everything wrong so if anyone wants to slap me and say "quit being a dumbass" I would be grateful for that as well.
I usually try to avoid STI because there are only troubles with that (image third indcator with different attributes and fourth and fifth with more fields and before you realize you end up with huge table where most columns are unused). To answer your question: you can create different new views for different classes and respond like that:
respond_to do |format|
format.html { render action: "new_#{#indicator.class.to_s.underscore}" }
format.json { render json: #indicator }
end
that should render new_indicator.html.erb or new_malware_indicator.html.erb depends on #indicator class.
I handled it in the view itself. The route entry for malware causes the controller to receive a type parameter and the controller uses that to create an instance of the correct class. In the new.html.erb file I put this at the end:
<%= render :partial => #indicator.class.to_s.downcase %>
So if a MalwareIndicator was created by the controller then #indicator.class.to_s.downcase will return malwareindicator. I have a partial file called _malwareindicator.html.erb which has the correct form in it.
So if I have to create another descendant of the Indicator class I can add another resources entry to the routes file and create a partial called _whateverindicator.html.erb and it should work out OK.

Displaying raw file content as Github

How could I display the raw file content as done in GitHub when displaying the file after clicking a "view raw" link?
E.g. I wanted to diplay *.html file's source but rails takes html in params[:format] and renders in its own way.
How could I achieve this?
Here's how I got this to work, though I am not exactly sure how you would want to use this in your application. Consider this a proof of concept that hopefully helps you achieve your goal.
Let's say you want to render the raw contents of the index action for your products controller if someone requests the "text" format:
def index
#products = Product.all
#raw = render_to_string('products/index.html', :content_type => 'text/html')
respond_to do |format|
format.html
format.text do
render :text => #raw, :content_type => 'text/plain'
end
end
end
This obviously isn't ideal since you're stuffing the "raw" version of the view in a variable even if someone requests the normal html format, but putting it in the format.text block screws up the content type for the partials inside index.html.erb. Again, this is just a proof of concept I came up with.
At any rate, now when you hit:
/products.txt
You will get the raw HTML of the page. And if you hit:
/products
It will render the normal, interpreted HTML in the browser.

Rails 3: How To Return A JSON Document?

I'm in the process of creating a simple API for my application. I have create the controllers and did all the processing. However, the view is being returned.
How can I return a JSON document to the user instead of the view?
Also, if there's an error, should I also return a JSON document or... ?
Thanks!
Add this to your controller
respond_to :html, :json
(remove html if you only want json-api).
In your actions you can then simply use a respond_with call, like:
respond_with(#posts = Post.all)
It will render JSON-object if format is JSON, and it will render your html-view if html is requested. If your routes are created as standard resources, simply adding .json suffix to the url will give you the JSON-result, ie. if the route is specified as:
resources :posts