What is the current best solution to fix the problem that rails respond_with returns an empty body with status 200 on successful PUT requests, but Ember (JQuery) expects a valid JSON response, therefore javascript warnings are shown?
I could of course replace respond_with in the rails code with if/render/then/render/end, however that loses the brevity and I would prefer not to do that. I have been checking and in some places I read that this should already be fixed in JQuery, but with the below versions I still get the same problem.
Ember : 1.5.1
Ember Data : 1.0.0-beta.8.2a68c63a
Handlebars : 1.3.0
jQuery : 1.11.0
Ah yes, Rails PUT requests. Best I came up with was to fill in the response myself, like so:
def update
book = Book.find(params[:id])
updated_book = BookUpdater.new(book, user: current_user).update(permitted_params)
respond_with do |format|
if updated_book.errors.present?
format.json { render json: { errors: updated_book.errors }, status: 422 }
else
format.json { render json: updated_book, status: :ok }
end
end
end
Gotta keeps the Embers happy.
Related
I have a method to translate different strings in Product class from English language to another. It has two variables: string and language. And for the first one I expect to get current value of the text area. Here how it looks like in JS:
var primary_value = document.getElementById('primary_body_html_value').getElementsByClassName('note-editable')[0].innerText;
And then I want to use this method inside JS function:
var translated_string = "<%= GoogleTranslator.translate(primary_value, 'de') %>"
The main question is how can use this 'primary_value' inside 'translated_string'? As I know - I can use Ajax but I am a bit new to this and I don't understand how to write correctly a method for Ajax and for Product controller. In case if you need a controller code:
class ProductsController < AuthenticatedController
before_action :set_product, only: %i[show edit update]
def index
if params.include?('id')
redirect_to edit_product_path(params[:id]) and return
end
end
def edit
redirect_to products_path, error: 'product not found' unless #product
render :edit_polaris
end
def update
if #product.update(product_params)
render json: {
status: :ok,
notice: 'Saved successfully!'
}, status: 200
else
render json: {
status: :error,
error: 'Something Went Wrong'
}, status: 400
end
end
private
def product_params
params.permit(
:id,
primary_locale: {},
locales: {}
)
end
def set_product
#product = Product.find(product_params[:id])
end
end
This is just a sketch but hopefully can help you out.
It can be inside one of your existing controller methods, for the sake of the example lets say you added a route (and controller method) called translated_string to ProductsController.
#ProductsController
def translated_string
primary_value = params[:primary_value]
#translated_string = GoogleTranslator.translate(primary_value, 'de')
render json: {translated_string: #translated_string}
end
Now when something happens on your DOM page where primary_value is set, you send primary_value via ajax to translated_string and you get the json response with the translated string back - u can do whatever you want with it. This is just an example, there are a million ways to go about it, hope this gives you a direction.
Having a strange issue trying to update search results via AJAX in rails in that rails is loading the js.erb in a <pre> tag at raw text on the page and not firing any js in that file.
in index controller
if request.format.js?
respond_to do |format|
format.js { render layout: false }
end
end
Form set to fire AJAX with remote: true
= form_tag(search_path, id: "form", remote: true, :'data-type' => 'script') do
index.je.erb
alert('hello');
$("#results").innerHTML("<%= escape_javascript(render partial: 'results', locals: { results: #results } ) %>");
routes.rb
match 'search', to: 'properties#index', via: :post, defaults: { format: 'js' }
In routes I have tried to force js from the form as previously it was JSON, but makes no difference.
From the logs, the controller is receiving the js request but i get this in CHrome debugger:
(index):69 Resource interpreted as Document but transferred with MIME type text/javascript: "http://localhost:3000/search".
Sticking a alert("Js is working") works without issue so JS is there and firing
Im stuck, this should be working by now, is it something silly i have missed, or something new in Rails 5 i am not aware of?
If i can provide any more info to help you halp me please just ask!
Thanks in advance
OK then. ´remote: true` is not enough it seems! It does seem to submit the ajax request to the controller, but the controller is determined that it is text.
adding
jQuery ->
$('#form').on "change", ->
$.ajax '/properties/index',
type: 'GET'
dataType: 'script'
data: $('form').serialize()
and hyjacking the form submit into pure ajax seemed to fix it all!
I work on a task manager app, and I want to create html div 'cards' (with title, duration etc...), with all the datas I got on a database in rails.
I guess that I have to use javascript functions, but I can't get a way to do it.
I saw a lot of things on google, but I can't find exactly javascript calls from a rails controller (because I only catch all datas in the controller).
Here is my controller :
def new
# Retrieve all tasks in the project
#taskModel = Task.new()
#projectTasks = #taskModel.getProjectTasks()
# Add tasks on html
(0..#projectTasks.length).each do |i|
respond_to do |format|
format.js { render :js => "window.createTask();" } # I need to pass parameters in the createTask function
end
end
end
and my js file :
window.createTask = (title, content, duration) ->
card = document.createElement('div');
document.getElementsByClassName('content')[0].appendChild(card);
With my code, I get this error : ActionController::UnknownFormat
ActionController::UnknownFormat indicated that your ajax request is interpreted as a request with the wrong format. To answer this part better you'd have to post the javascript with the ajax call.
Secondly, you have to rethink the render in this block
(0..#projectTasks.length).each do |i|
respond_to do |format|
format.js { render :js => "window.createTask();" } # I need to pass parameters in the createTask function
end
end
You are calling respond_to multiple times which is just wrong. Put this loop into a new.js.erb view.
I'm converting a website from Symfony to Ruby on Rails and am finally down to my javascript pop up email contact form. I don't want to rewrite the form or the java script as it took a lot of work to get it to work in the first place. That will be phase two.
Here's where I'm having the problem:
sendBtn = new Button({
label: "Send",
onClick: function(){
if (emForm.validate() == true){
// Post the data to the server
request.post("/contact/create",
{data: domForm.toObject("contact-form"),
// Wait 2 seconds for a response
timeout: 2000
}).then(function(response){
emailDialog.hide();
alertDialog.set("content",response)
alertDialog.show();
});
}
}
},"submit-btn");
I know it gets to the request.post as I copied the line "email.Dialog.hide()" just before it and it hid it. I later added code to catch any errors. It goes there immediately and not after the two second timeout. I'm using dojo here, by the way. So I suspect it doesn't like the "/contact/create" as it's the only thing I changed.
In my routes.rb I have:
get 'contact/create'
Do I have the right information in my post? If not how do I get there? The javascript is included in application.html.erb so it can be invoke from all pages on the site.
In case it's pertinent, my contact_controller.rb is currently just this:
class ContactController < ApplicationController
def create
respond_to do |format|
#format.html {}
#format.js {}
format.json { render :json => {:response => 'Amazing, it works'} }
end
end
def show
end
end
Take a look at your network tab in dev tools, it should tell you why it is failing post... I'd say try adding handleAs: 'json' option to your request.post. For more on dojo/request, read this
As it turned out, I had the right path in the request.post statement. I found out my copying the Javascript into my html.erb file so I could use
<%= contact_create_path %>
in it's place. I ended up getting the same value so that wasn't the problem. I then checked my Firebug console. Rails sends a nice dump of the problem. I was getting a 404 error. The problem was that I was doing a post and there was no route for it. So I changed the routes.rb file from
get 'contact/create'
to
post 'contact/create'
This might cause me other problems later on if I want to do a non-Javascript version.
I then got another error:
ActionController::InvalidAuthenticityToken in ContactController#create
Through the help of Stackoverflow I found the fix. I added the second line below:
class ContactController < ApplicationController
skip_before_filter :verify_authenticity_token
...
Again, this solution may cause other problems. Skipping verification doesn't seem like a good thing. I had a number of other problems getting the whole process to work, but their specific to my application.
To increase speed of page loading I`ve implemented creation comments via AJAX. It is simple and not heavyweight.In controller action I have:
def create
#comment = #commentable.comments.new(params_comment)
respond_to do |format|
if #comment.save
flash.now[:notice] = "Your comment added."
#response = {comment: #comment, model: #commentable}
format.js { #response }
format.html { redirect_to #commentable }
else
format.js { render nothing: :true, status: :not_acceptable }
format.html { redirect_to #commentable, status: :not_acceptable }
end
end
end
and js file:
$("<%= escape_javascript( render 'comments/comment', #response)%>").appendTo(".comments").hide().fadeIn(500)
$('.notice-wrapper').html("<%= j(render partial: 'shared/notice') %>")
$('.alert').fadeOut(3000)
if $(".no-comments").css("display") is 'block'
$(".no-comments").hide()
$(".new_answer").hide()
$(".open").show()
But instead of speed up performance I got the opposite effect. Response time through JavaScript increased on 100-200 ms(~300ms total). Is this normal behavior or I am doing something wrong? Is there any way to improve speed little bit?
My performance test:
UPD:
My performance test with just JS file.
Let's put aside for the moment my opinion that embedding ERB in CoffeeScript is utterly gross to look at and unmaintainable. It is indisputable that there's a huge performance impact when you generate and compile CoffeeScript on every request.
You also lose any chance at HTTP caching.
My first suggestion would be to separate CoffeeScript from ERB. Populate hidden fields in your ERB with the data you need, and then mine those fields in your CoffeeScript.
But if you must embed ERB in what should be static files, embed the ERB tags in pure JavaScript instead, and let the compiled CoffeeScript use those.
The code you've written wouldn't really be expected to speed up the request, because Rails still need to process all the ERB etc. You're still returning rendered HTML and sending it to the browser where it is added to the DOM.
If you wanted to make it 'faster' you could simply render the #response as json and deal with it on the client using jQuery or a front end framework.
The code does make it nicer for the user, however, because it doesn't refresh the entire page.
My suggestion would be to hook into the form request, and on success, render the new comment, else re-render form with errors. An example:
# app/javascripts/comments.coffee
$('#comment-form').bind 'ajax:complete', (data, status, xhr) ->
// psuedo code
1. if status is success
append comment -- $('#comments').append(data.comment)
2. else
re-render form with errors -- $('#comment-form').html(data.form)
Return comment template (comments/comment) and append to comments
Update your controller to return the form with JS response if not_acceptable.
Note the file is found in app/javascripts/comments.coffee