Rails 3.2.2 not executing rjs - javascript

I'm following the book Pragmatic Agile Web Development With Rails 4th Edition, BUT I'm using Rails 3.2.2 instead of 3.0.5 as recommended in the book:
~$ ruby -v
ruby 1.9.3p125 (2012-02-16) [i686-linux]
~$ rails -v
Rails 3.2.2
I got stuck when including AJAX to redraw the Cart without reloading the page. Here is the create action in line_items_controller.rb:
def create
#cart = current_cart
product = Product.find(params[:product_id])
#line_item = #cart.add_product(product.id)
respond_to do |format|
if #line_item.save
format.html { redirect_to(store_url) }
format.js
format.json { render json: #line_item, status: :created, location: #line_item }
else
format.html { render action: "new" }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
And here is my RJS file create.js.rjs (under app/views/line_items):
page.alert('NO PROBLEM HERE')
page.replace_html('cart', render(#cart))
However, when I click the button that starts this action:
<%= button_to 'Add to Cart', line_items_path(:product_id => product), :remote => true %>
I get the following error in the development log:
ActionView::MissingTemplate (Missing template line_items/create, application/create with {:locale=>[:en], :formats=>[:js, :html], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "/home/me/src_rails/depot/app/views"
):
app/controllers/line_items_controller.rb:47:in `create'
If I change the filename of create.js.rjs to create.js.erb, the problem is corrected:
Rendered line_items/create.js.erb (0.4ms)
but nothing happens in the view.... not even the alert.
What am I missing?
What is the difference between file.js.erb and file.js.rjs?

It looks like rjs has been removed as the default as of Rails 3.1. You could get it back by installing the prototype-rails gem, but I think you should just use jQuery, which is the new default.
As for your code, the reason it's not working is that it's an rjs template being interpreted as .js.erb, and this is likely just producing invalid JavaScript (you should see errors in the JavaScript console in your browser). An rjs template used to set the page variable for you, and you would write Ruby code using it to manipulate your page. In a .js.erb template, it works more like in your .html.erb views. You write actual JavaScript, with Ruby embedded using <% %> tags. So the code in create.js.erb should look something like this:
alert('NO PROBLEM HERE');
$('#cart').html("<%= escape_javascript(render(#cart)) %>");

In rails >= 3.1 there is no jquery-rjs anymore. But you can use CoffeeScript here:
line_items/create.js.coffee:
alert 'NO PROBLEM HERE'
$('#cart').html '<%= j render(#cart) %>'
or something like that.

Related

How to execute JS after saving a model in DB in Rails 6?

I’m Rails beginner and I’m a bit overwhelmed by the quite simple problem. I would like to do something like this:
Users fills in a form.
Taps on the submit button
Model is saved into database.
If the save operation was successful, execute a javascript.
The questions is: how to accomplish that in the best way possible in Rails 6? Should I use .js.erb files? Or should I have javascript put into webpacker?
I tried so far the following code, but without any success:
controller/jobs_controller.rb
def create
#job = current_user.jobs.build(job_params)
respond_to do |format|
if #job.save
format.html { redirect_to #job, notice: 'Success!' }
format.js {}
else
format.html { render :new }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
views/jobs/create.js.erb
alert('hello');
As it was pointed out by #max-pleaner I was missing remote: true in the form tag.

Rails code for format js do not work

I'm trying to implemet a complex task, and faced with a problem, that my JS code do not work when called from format.js.
I have a link with such code:
= link_to new_user_support_letter_path, {:id => 'contact-us', :remote => true }
In my user_support_letters_controller.rb:
def new
#letter = UserSupportLetter.new
respond_to do |format|
format.js {}
format.html
end
end
In new.js.erb:
alert("rrr");
So, when I click a link nothing happens.
Meaningful logs for clicking a link:
I, [2016-10-19T21:47:41.130608 #1] INFO -- : Started GET "/user_support_letters/new" for 172.18.0.6 at 2016-10-19 21:47:41 +0000
I, [2016-10-19T21:47:41.150411 #1] INFO -- : Processing by UserSupportLettersController#new as JS
I, [2016-10-19T21:47:41.269853 #1] INFO -- : Rendered user_support_letters/new.js.erb within layouts/application (0.1ms)
I, [2016-10-19T21:47:41.344629 #1] INFO -- : Rendered application/_support_email.slim (0.1ms)
...
Can anybody tell what I'm doing wrong? Thanx!
To get this to work you need to set layout to false and declare the content_type you're using.
From what I know/have read this is standard behaviour in rails. Here is a similar post discussing it with a link to a bug log. https://stackoverflow.com/a/1170121/3366016
Change your controller action to this:
def new
#letter = UserSupportLetter.new
respond_to do |format|
format.js { render layout: false, content_type: 'text/javascript' }
format.html
end
end
By default it will try to load in the current layout for the given content type. For JS it typically is smart enough to know not to load a layout. By setting false you are disabling the layout and just telling it to render without a layout.
It seems if you are using some form of templateing it messes with the requests a bit. This answer seems to identify in the comments a specific work around for slim template. This answer describes another solution, basically using the default layout setup. With this, Rails seems to know how to handle it for JS requests.

js.erb not executing javascript but is processed rails

I'm trying to get my pagination working with Ajax, using either will_paginate or kaminari.
When I hit pagination link my log says
Processing by Instructor::FullDashboardController#pupil_leads as JS
and
Rendered instructor/full_dashboard/pupil_leads.js.erb within layouts/main (0.1ms)
But the js has no effect. So to test it I wrote
console.log("Hello");
<%logger.debug "This is the js file"%>
alert('Hello Rails');
In the js.erb file, in my log I see This is the js file as expected, but there is nothing in js console in my browser and the alert doesn't show. So I know the file is being processed, as my logger.debug works but there is no js.
How can I further troubleshoot this?
Rails 4.1
Ruby 2.1
Full Dash Controller
class Instructor::FullDashboardController < ApplicationController
layout 'main'
...
def pupil_leads
#ivar = Model.where("something = ?", some_object.id).order("created_at desc").page(params[:page]).per(10)
respond_to do |f|
f.js { render :content_type => 'text/javascript' }
f.html
end
end
Add layout: false option to the render block:
def pupil_leads
# some code here
respond_to do |f|
f.js { render layout: false, content_type: 'text/javascript' }
f.html
end
end
For some reason Rails don't recognize request as xhr, I also watched that the views extension (.erb.html or .slim) must be specified in full.

Rails 3, rendering partial view through ajax

I'm making an e-mail service with mailboxer gem.
In my index view I have several links that will lead to inbox/draft... like this:
<%= link_to "Inbox", show_conversations_path, :remote => true %>
...
<div id="content">
</div>
Then my show_conversation js.erb
$("#content").html("<%=escape_javascript(render :partial=>"show_conversations")%>");
the controller (messages_controller)
def show_conversations
#inbox = current_user.mailbox.inbox
respond_to do |format|
format.js
end
end
And there's also a partial view _show_conversations.html.erb (already tested, through a simple render so no errors there).
So my problem is that, when I click on the link, it actually redirects to a blank plage (when it shouldnt, or at least it's not my intention, redirect at all, just show the content on the div).
I've realized that it actually renders its controller, then the erb.js, the partial view, and I Don't know why the controller again but this time as HTML.
A piece of the log:
Started GET "/en/messages/show_conversations"4
Processing by MessagesController#show_conversations as JS
...
Rendered messages/_show_conversations.html.erb (7962.4ms)
Rendered messages/show_conversations.js.erb (23239.0ms)
Completed 200 OK in 23330ms (Views: 23237.9ms | ActiveRecord: 5.0ms)
Started GET "/en/messages/show_conversations
Processing by MessagesController#show_conversations as HTML
Completed 406 Not Acceptable in 8ms (ActiveRecord: 0.5ms)
I know it shouldn't redirect, and I believe it shouldn't call two times to the controller (and the second one as if it was html instead of js), but I don't really know why it's happening nor have I found a similar problem through the forum
Check with below code, if it works
def show_conversations
#inbox = current_user.mailbox.inbox
respond_to do |format|
format.js { render :layout => false }
end
end
Try modifying this line:
$("#content").html("<%=escape_javascript(render :partial=>"show_conversations")%>");
to:
$("#content").html("<%= escape_javascript(render :partial=>'show_conversations') %>");
or make it pretty:
$("#content").html("<%= j render :partial=>'show_conversations' %>");

Cucumber Testing js.erb functions when no html.erb exists

My rails application is using js.erb views instead of html.erb views for specific windows. This works fine in practice, but when I'm using cucumber tests with capybara it gives me an error of
Missing template admin/groups with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths
When I click the button pertaining to this particular view. There is no groups.html.erb but there is a groups.js.erb. I want to somehow tell cucumber/capybara to not try to render the groups.html.erb but still render the groups.js.erb. I would prefer not to generate an unnecessary html file to render the same thing the escape javascript below is doing.
groups.js.erb:
$("#admin_content").html("<%= escape_javascript(render :partial => 'groups') %>");
Relevant admin controller method:
def groups
#groups = Group.all
end
You should use proper MIME type handling for your responses. Try this:
def groups
#groups = Group.all
respond_to do |format|
format.js
end
end
eventually you can be more specific about how to respond :
format.js { render layout: false }
more info on respond_to here.
note: if your controller only manages js responses, you can add respond_to :js at the top of the class, and then use respond_with #object in your actions.

Categories