Rails3 rendering action from another controller - ruby-on-rails

i want to render an action from another controller, but i get the error:
undefined method `formats' for nil:NilClass
<script>
$("#validate_company").live("keyup", function() {
$("#company_info").html("<%= escape_javascript(render(:controller => 'live_validation', :action => 'validate_client_company')) %>");
});
</script>
This is the Controller:
class LiveValidationsController < ApplicationController
def validate_client_company
if params[:first_name].length > 0
#client = Client.find_by_company(params[:company])
if #client.nil?
#message = "<img src='/images/accepted_48.png' alt='Valid Username'/>"
else
#message = "<img src='/images/cancel_48.png' alt='Invalid Username' /> Name taken"
end
else
#message = ""
end
render :partial => "message"
end
end
The partial _message is just
<%= #message %>

You seem to be mixing up stuff.
You have html inside your controller-method? That should be in your view. For each controller-method, normally a view with the same name is rendered, except if you explicitly call render from within your controller-method.
You do not write html in your controller. You write html in the view, and sometimes you have helpers to make your views more readable.
Secondly, in your first piece of code, which is some view-code, i hope. The view is prepared at server-side and then sent to the client. You can render another view, a partial, from a view. But this does not load data live.
How i would fix this. Inside your views where you want to dynamically render the validation:
<script>
$("#validate_company").live("keyup", function() {
$("#company_info").load("<%= url_for :controller => 'live_validations', :action => 'validate_client_company' %>");
});
</script>
Then inside your controller you write:
class LiveValidationsController < ApplicationController
def validate_client_company
if params[:first_name].length > 0
#client = Client.find_by_company(params[:company])
#error = #client.nil? ? :valid_username : :invalid_username
else
#error = nil
end
render :partial => "message", :layout => false
end
end
Inside your app/helper/live_validations_helper.rb you add a method
def get_validation_message(error)
if error == :invalid_username
image_tag('/images/cancel_48.png', :alt => 'Invalid Username') + "Name taken"
elsif error == :valid_username
image_tag('/images/accepted_48.png', :alt => 'Valid Username')
end
end
and inside your message view you write something like:
<%= get_validation_message(#error) %>

render :action => does not run the associated controller method.
It simply renders the template that Rails would, by default, have associated with the action. That is to say, if the action validate_client_company simply called render without passing any arguments, Rails would look for a template in a folder with the same name as the controller and with a name with the same name as the action. Calling render :action => simply looks for that same template and renders it.
Best guess is that Rails cannot find a template named validate_client_company. I expect that none exists, because the action validate_client_company renders a partial named message instead of rendering a template with the default name for that action.
In the action which renders the script, you need to set up the instance variables and then in the template for that action you need to use the following:
render :partial => 'live_validations/message'
It certainly makes sense to have mini MVC stacks within the larger MVC stack, so that you can run sub-actions within running larger actions. For this scenario, you may wish to look at Cells. However, you cannot do this with Rails by itself.

You probably want something like this:
<script>
$("#validate_company").live("keyup", function() {
$("#company_info").load("<%= url_for :controller => 'live_validation', :action => 'validate_client_company' %>");
});
</script>
But the rest of your code is kinda of messed up... Rendering a partial from inside a controller?

Got it to work!
<script>
$("#validate_company").live("keyup", function() {
$("#company_info").load("/live_validations/validate_client_company",{company:$('#validate_company').val()});
});
</script>

Related

send a rendered view as an email rails

I would like to send what is normally a view as the body of an email.
Whats the simplest way to do this?
eg: I have pages/reports.html.erb and I want to send the page that you'd see if you visited that path as the body of an email.
Is there some way to take the html that is rendered and assign it to the body variable of an email?
Additionally, I'd like to include the PDF version as an attachment. (I'm using wicked_pdf)
def reports
#email = params[:email]
#something here?
respond_to do |format|
format.html
format.pdf do
render :pdf => "usage_report"
end
end
end
note: I'm using rails 3.1 with mongoid 2 for the DB and sendgrid on heroku if that helps
EDIT: What I ended up doing:
replace #something here? with:
email_obj = {}
email_obj.to = params[:email]
email_obj.from = 'reports#company.com'
email_obj.subject = 'Report'
email_obj.body = render_to_string(:template => "pages/reports", :layout => false)
ReportsMailer.deliver_report(email_obj).deliver
and in the mailer class mailers/reports_mailer.rb
class ReportsMailer < ActionMailer::Base
default from: "from#example.com"
def deliver_report(email)
#email = email
mail( :to => #email.to,
:subject => #email.subject,
:from => #email.from)
end
end
and in reports_mailer/deliver_report.html.erb
<%= render :inline => #email.body %>
The rails mailer views are stored in a sub folder in views by the name of the mailer just like controller views. It is hard to say if this will work completely for you not knowing what the view/controller for that method looks like but what you could do is take the rendering for that page and turn it into a partial which you can then render in both the controller view and the mailer view as such:
given a partial: _my_partial.html.erb
within the views:
render "my_partial"
Using the partial you can even pass any variable that would be necessary for the view to be rendered to it with:
render "my_partial", :variable => variable
Update:
This may be of interest as well: Rendering a Rails view to string for email

How to make Rails render a view and automatically scroll down?

I have an obnoxiously large landing page with a registration form in the middle of it. If I submit the form and validation fails, I want to render the landing page again, but I want it be scrolled down to the registration form so they can see the errors and make edits. Is this possible to jump down to the form with the render method, or do I need to do redirect_to "account/new#theFormID"?
I would rather not do a redirect because you have to save the form information in a session, repopulate the form, et cetera, and I want to stick the conventional
if #resource.save then redirect_to ...
else render "new"
end
Put the anchor directive on the form and you can still rely on :render from the controller...
form_for(#my_model, :url => { :action => "create" , :anchor => "my_anchor" })
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html
redirect_to profile_path(#profile, :anchor => "wall")
That is how you pass anchors.
I scrolled to an anchor with render using a global var and Javascript (as hinted by Ibrahim).
On my controller I had this:
#anchor = "my_anchor"
render :action => "edit"
And on my page, I checked if I had a global #anchor, and if so, roll to it with Javascript:
<% if #anchor %>
<script type="text/javascript">
window.location.hash = "<%= #anchor %>";
</script>
<% end %>
Use javascript?
<script>
window.location.hash="ANCHOR";
</script>
And another thing... if it's a link like I'm actually using, you have to add a unique param so the browser thinks it's submitting something new, otherwise it just refreshes without hitting the server. I'm using:
link_to "REFRESH", refresh_my_model_path(#my_model, :anchor => "my_anchor", :options => {:id => Time.now} )

updating a rails partial with AJAX

I'm new to using AJAX in Rails (I know... I know...), and am positive that I'm doing something wrong that's probably just the wrong call or something. But I've hunted and can't seem to find it.
Anyway, I'm rendering out quick partial (this is working right) and then I want to refresh it with an AJAX call. Here's what I thought would work:
<div id="two_on_two"><%= render :partial => "quickread" %></div>
<p><%=link_to_remote "load two new stories", :url => {:partial => 'quickread'}, :update => 'two_on_two' %></p>
that just blows out the page (a quick flash and then just a blank browser window). If I switch from :partial to :action in that AJAX call, then it dynamically loads a "template missing" in that two_on_two div.
Clearly, there's something easy I'm missing here, right?
Thank you so much!
First, read api:
http://apidock.com/rails/ActionView/Helpers/PrototypeHelper/link_to_remote
You should specify your url correctly (controller, action, other params, not partial!) and define your RJS in controller action.
IE:
index.html.erb
<div id='two_on_two'></div>
link_to_remote 'Link Name', :url => {:controller => "bar", :action => "baz"}
bars_controller.rb
def baz
respond_to do |format|
format.js{ render :update do |page|
page.replace_html 'two_on_two', 'Hello world!'
end}
end
end
So when you will click Link Name, in your two_on_two div will appear "Hello world text".

Rails conditional ('if') statements based on controller action

There might be a better way to do this, but I'm trying to make an if statement in rails, based on the current action, in a controller (this will be used in a view).
For example, if its the edit page, or the show page, etc. I'd like a different style for something - is there an if statement that can specify this?
(I need an if statement, because its used in a partial, on multiple pages).
Thanks!
Elliot
The params hash that is available in the controller contains :controller and :action keys, which specify the controller and action names of the request.
Therefore you could say
if params[:action] == "foo"
# Show stuff for action 'foo'
elsif params[:action] == "bar"
# Show stuff for action 'bar'
elsif ...
# etc.
end
It's not good practice IMO to have partials asking what the current controller and action names are. Think "tell, don't ask" (http://www.pragprog.com/articles/tell-dont-ask). That is, rather than having the partial ask it's caller about its state, tell the partial what you want it to do.
One way to do this is by passing variables to the partial through the locals option:
<%= render :partial => "/common/toolbar", :locals => {:edit => true} %>
Then in the partial:
<% if defined?(edit) && edit %>
... stuff appropriate to edit mode
<% end %>
You can do it this way:
class ApplicationController < ActionController::Base
layout :set_layout
def set_layout
case params[:action]
when "foo"
"foo_layout"
when "bar"
"bar_layout"
...
else
"default_layout"
end
end
...
end
hope it helps =)
You can use layouts for partials too:
<%= render :partial => 'some_partial', :layout => 'wrap_with_stuff' %>
If you want to work out what layout to use dynamically I'd put that in a helper. So you'd end up with
# In your view
<%= render :partial => 'some_partial', :layout => layout_for_my_partial %>
# In your helper
def layout_for_my_partial
params[:action] == 'show' ? 'show_wrapper' : 'everything_else_wrapper'
end
This will only work in some circumstances, but might be what you're trying to do.
See more here.
http://ryandaigle.com/articles/2007/8/3/what-s-new-in-edge-rails-partials-get-layouts

How can i display an error for ajax in rails

I am trying to display an error message of flash in Ajax using Rails but it doesn't display it, and I have tried several ways to do it but I just can't get it right.
Here is my form to display my errors:
#flash-error.flash-error{:style => "display: none"}
#flash-notice.flash-info{:style => "display: none"}
%h3 New Document
- form_for(:repo_document, :url => {:all_categories => #repo_categories, :action => "create", :format => "js", :query => params[:query]}, :html => { :id => "repo_document_form", :multipart => true, :target => 'upload_frame'}) do |form|
Here is the controller:
if !params[:stands]
respond_to do |format|
format.js do
responds_to_parent do
render :update do |page|
page.show "flash-error"
page.replace_html "flash-error","Please select stands you want to grant permission to view this stand."
end
end
end
return
end
end
What am I doing wrong?
js.rjs to the rescue
def action
#true = params[:stands]
respond_to |format|
format.js
end
end
in action.js.rjs:
if #true
# do true stuff
else
page.replace_html 'error_block_dom_id', :text => 'This is my error'
end
and the original view file that you make the ajax call from:
#nothing here due to no errors - errors will appear if they happen
<div id="error_block_dom_id"></div>
No overarching reason to use the flash - just update a DOM object with the error content.
A possible solution would be to send an ajax call to an action in a controller and set your flash messages in that action
Flash is only going to display on the next time the page is loaded. It doesn't update through AJAX. One of the caveats of AJAX is that it doesn't deal with file uploads...
See this for more details; http://guides.rubyonrails.org/form_helpers.html#uploading-files
I think the problem might be elsewhere: Element's method show (call of which is generated when You call page.show "flash-error") will not remove display: none css style when it is given inside the external Css file. This is a quotation from older version of Prototype's API Documentation.
So try to add display: none as inline style of Your div's. I hope it will help!

Resources