Rails 3 Remote Form Ajax Success - ruby-on-rails-3

I'm having some issue figuring out how to handle success on my entries form using rails 3 ujs ajax.
If there are errors, I have a create.js.erb that will alert(j(#entry.errors.full_messages), and this works. But if there are no errors, the form doesn't redirect (because I'm rendering in a dialog) and I'd like the js to alert("success") and close the dialog. (using fancybox 2).
Can you give me some pointers working with rails 3 ujs and ajax?

An approach is to identify and handle the error at controller level instead of view.
def create
#entry = something
if #entry.save
#notice = "Success message!"
respond_to :js # render default create.js.erb
else
respond_to :js { render 'create_error.js.erb' }
end
end
// create.js.erb
$("#dialog").close();
alert("<%= #notice %>">;
// create_error.js.erb
alert(j(#entry.errors.full_messages);

Related

Dynamic page caching failing in Rails 5

I'm updating a site from rails 4.2 to 5.1
In the previous setup I have page caching on a generated stylesheet (per tenant), all working perfectly.
After upgrading to 5.1 this is no longer working
Using latest version of actionpack-page_caching
Controller for the Stylesheet that is cached looks like this:
class StylesheetsController < ApplicationController
caches_page :show, gzip: true
def show
#stylesheet = Stylesheet.find(params[:id])
respond_to do |format|
format.html
format.css { render text: #stylesheet.contents, content_type: "text/css" }
end
end
end
I'm getting the following error in the logs:
ActionView::MissingTemplate - Missing template stylesheets/show, application/show with {:locale=>[:en], :formats=>[:css], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby]}. Searched in:
There is no physical template for this as I'm rendering it directly from the stylesheet model. Have confirmed the model is returning data.
Caching is enabled in development.
In the layout page the reference to the dynamic stylesheet is:
<link href="<%= dynamic_stylesheet %>.css" rel="stylesheet" type="text/css" />
and the helper method (in application_helper) is:
def dynamic_stylesheet
stylesheet_path(current_account.stylesheet) unless current_account&.stylesheet&.id.nil?
end
I'm not sure what's getting skipped/missed here, any pointers?
Ok for anyone else who runs into this - the issue is a small change in Rails 5 with render text, in the controller example above it should now read:
format.css { render plain: #stylesheet.contents, content_type: "text/css" }
Found here What to use instead of `render :text` (and `render nothing: true`) in rails 5.1 and later?

Is jquery not availble in integration test for rails 3.2 app?

We use a fields_for and jquery to add a partial view on a form in rails 3.2 app. Here is the code:
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render :partial => association.to_s, :locals => {:f => builder, :i_id => 0}
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{j fields}\")")
end
In applicaton.js:
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
Whenever the 'Add Field' link is clicked, the partial view is rendered and a few input fields are added to the current form. The code works in execution without any problem. However in integration test (capybara & launchy), the click_link('Add Field') did not do anything and failed bringing up the partial. Is jquery not enabled in integration test?
By default Capybara use :rake_test driver on all tests, which is fast but dosen't support JavaScript.
Since this test needs JavaScript, make sure you have turned JS driver on.
describe "some feature", js: true do
# test code
end
This will use default JS driver Selenium.

I want to use `layout false` but I still want to use the CSS that would typically load when I'm rendering the layout - how do I do this?

I have a controller where I set layout to false:
class SplashController < ApplicationController
layout false
def index
end
end
But when I load this page there is no css whatsoever - I assume this has to do with how rails handles layout false - but my current knowledge of rails leaves me lost.
How do I not render a layout, but still load all the other assets (css, js, etc. . .) that would typically load if I were to load a layout? (*Note that the layout file has no specific reference to any of these assets)
By default, if you use the :text option, the text is rendered without using the current layout. If you want Rails to put the text into the current layout, you need to add the :layout => true option.
As you need only the information to be displayed, I suggest to use :text to render.
You can send plain text – with no markup at all – back to the browser by using the :text option to render:
render :text => "OK"
NOTE: Rendering pure text is most useful when you’re responding to AJAX or web service requests that are expecting something other than proper HTML.
UPDATE:
Also if you want that assets should be shown but still layout should be false then you have to render layout to false after making the assets available. This means you make some view, then define your required css and js files there and then call that view from controller and then set layout to false.
Setting the layout to false after view will show the css and js stuff but still keep the layout to false.
But setting the layout to false before showing the view that contains css and js will not include assets at all.
The other alternative of the above will work also:
css : <%= eval("render :partial => 'myurl/blah', :formats=> [:css], :layout => false").dump.html_safe %>
You see that how partial view that contains your assets like :css is getting called while layout is false.

Rails 3: Rendering actions with named anchors/fragments after failed form submission

The edit view for one of my models contains tabs that utilize anchors in the url to switch between settings such as model/1/edit#tab1 and model/1/edit#tab2. Is there a way to redirect to these anchors after submitting the edit form but failing to save due to errors? My current code is below:
def update
#user = Product.new(params[:user])
if #user.save
flash[:success] = "Your user has been created"
redirect_to #user
else
render 'edit' //want to render here with an anchor
end
end
I would like to store the url containing the anchor before form submit and then re-render the form with the same anchor while rendering error messages. Any ideas?
Best way was to use jquery cookie to save last opened tab and then set default tab using saved cookie.

Rails prevent layout during AJAX request

I have searched around and have not been able to find a solution for this type of mechanic. I want to load all pages normally in Rails, but whenever I do an ajax request I just want to return the page without the layout. So anytime I make an ajax requst I can append a ?page=true or something along those lines and have Rails just return the page without the layout.
Is this possible? Is there a better way to do it that I am missing?
Thanks for any help!
Final Solution Working Code:
In the controller all you need to do is append a little logic to the format.html in the respond_to block.
In the show method for example
def show
# code beforehand
respond_to do |format|
format.html { render :layout => !request.xhr? }
# other formats
end
end
And that's it! Prevent layouts during AJAX requests!
Note: Thanks to the smathy's comment on his answer this was simplified further. I originally had format.html { render :layout => nil if request.xhr? } This solution works just as well, but smathy's modification keeps it even simpler.
You don't need to add that parameter, request.xhr? will return true in your controller when it's an Ajax request. Just use that to decide whether to render the layout or not.