ruby on rails rendering json in js.erb - javascript

In a create method in controller I have the following code:
respond_to do |format|
format.js { render json: { html: render_to_string(partial: '/users/photos/card', object: #photo, as: 'photo') } }
end
which works perfectly. Now I would like to move this in create.js.erb to have the possibility to execute additions js. However I do not figure out how to render the json above in create.js.erb.
Any idea how to accomplish this. Thanks in advance!

If I understood you right, what you are trying to achieve is to be able to access your JSON inside a js.erb view. In order to accomplish that, what I've done in the past is the following:
In your create.js.erb:
var yourJSON = JSON.parse("<%= raw(j render :partial => '/users/photos/card', object: #photo, as: 'photo') %>");
And in your controller:
respond_to do |format|
format.js # This will render the create.js.erb
format.json { render :partial => '/users/photos/card' } # Leave this one in case you also want to be able to respond to this format i.e: "http://localhost:3000/users/photos/card/id.json"
end
Hope this helps!
P.S: Let me know if you were trying to achieve something different.

Related

Ruby on Rails -> Create div dynamically

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.

rails redirect_to format html sends response in js

I made a before_filter in some of my controller to redirect keyword searches to the parent controller
It's very simple:
before_filter :redirect_search
def redirect_search
redirect_to controller: "buildings", action: "index", format: "html" if params[:q].present?
end
Please note that the keyword_search is sent in "js" format
Everything seems to work. When I look at the server, I can see that the buildings/index is run and that the page is rendered but nothing happens in the browser.
In the browser's console I see this
GET http://localhost:3000/buildings.html 200 OK
It has the html page in the response body
This means that buildings/index is run as html but then sent as js to the browser.
Why is that so? How can I fix it?
Try with
def redirect_search
respond_to do |format|
format.html {redirect_to buildings_path} if params[:q].present?
format.js {render :js => "window.location.href='"+buildings_path+"'"} if params[:q].present?
end
end
Thanks to Bachan's answer, I could solve my issue this way:
def redirect_search
render :js => "window.location.href='"+buildings_path+"'" if params[:q].present?
end
Thanks!
I think the problem is in the view which is doing the request
you are sending a JS request (ajax), so you should return a js.erb file and render new HTML using js

Comprehensive ajax page for Rails

I have a Controller named ProductsController. In that controller are several actions such as socks and towels. I also have views of socks and towels. The view pages of socks and towels have the exact same form inside it. I'm going to use ajax in both files for the forms. Since the form is the exact same in both views, I see it pointless to create multiple ajax js files for the actions to call when ajax is called. How can I have both actions socks and towels call the same js.erb file instead of socks.js.erb and towels.js.erb respectively?
My controller and the action socks.
def socks
#socks = Socks.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #socks }
#ok, I get the line below is needed for ajax. Is there something I could add for
#the action not to call socks.js.erb and instead a different file, say ajax.js.erb
format.js
end
end
I think you're looking for render here. Using it you can render a template/view of another action. See the doc: Layouts and Rendering.
render 'products/show'
render :template => 'products/show'
render "/u/apps/warehouse_app/current/app/views/products/show"
as Sergio rightly said, you can do exactly that using the render command. Basically, in both socks and towels actions, you can render a common ajax.js.erb file when the respond_to is for JS.
I am adding this answer however because of your comment. It seems that your socks and towels methods as well as the forms and associated responses are very similar. If that is the case, why not use a single action for the same? Basically, you can use a URL parameter to specify the nature of product in the ProductsController actions.
So you would have something like:
def ProductsController
def index
if params[:nature] == "socks"
#socks = Sock.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #socks }
format.js
end
elsif params[:nature] == "towels"
#towels = Towel.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #towels }
format.js
end
end
end
end
Now you would need 2 view files index.html.erb and index.js.erb and there you can check the params value again and display the relevant collection.
This is not an ideal solution, but more a quick fix.
Failing that, you can also define a new action method in the ProductsController and have both forms point to that.

Render javascript for partial - Rails 3

I'm still relatively new to rails and getting used to a few things. Just a quick question really, I have an AJAX form (with :remote => true etc...) which works and sends the data to the server without a pageload.
My question is around the javascript file that can be used after the post. My partial is called '_newsomething.html.erb' and once it's posted I want to execute a javascript file - do these files have to be named after actions in the controller to sync and work properly in rails? At the moment I have a javascript file called 'create.js.erb' with just an javascript alert in it, but it's not firing.
e.g. do I need to have a partial called '_create.html.erb' and then a javascript file called 'create.js.erb'? Is there anyway of telling Rails where to go for a javascript file from within the controller?
Thanks in advance!
EDIT: Controller code below (very basic and generated at the moment)
def create
#snip = Snip.new(params[:snip])
respond_to do |format|
if #snip.save
format.html { redirect_to(#snip, :notice => 'Snip was successfully created.') }
format.xml { render :xml => #snip, :status => :created, :location => #snip }
else
format.html { render :action => "new" }
format.xml { render :xml => #snip.errors, :status => :unprocessable_entity }
end
end
end
In your controller action you have to have:
respond_to do |format|
format.html { .... }
format.js
end
The format.js is the important part. If Rails discovers that you are POSTing through AJAX, then it will render _create.js.erb partial.

How can I pass to Ruby obj to Javascript?

I have this to calling the choose_category:
{ :action => :choose_category, :id => category } do %>
And I have this method to calling the choose_category.js.rjs:
def choose_category
begin
category = Category.find(params[:id])
rescue
ActiveRecord::RecordNotFound
logger.error("Attempt to access invalid product #{params[:id]}")
# flash[:notice] = "Invalid product"
redirect_to :action => :index
else
respond_to { |format| format.js }
# redirect_to_index
end
end
I want to call back the category name, how can I do that? I try this, but it return nothing for me.
page.alert(#category.name)
Your problem is that #category isn't defined in your RJS template.
RJS files are essentially views that generate Javascript. Like views, they have access to instance variables set in the controller, but not local variables.
Putting this in the begin section of your action should solve your problem.
#category = Category.find(params[:id])
I'm not sure of this since I'm not very familiar with js and rjs, but I would add to your rjs something like this:
category_name = <%= #category.name %>;
and then
page.alert(category_name)
or just:
page.alert(<%= #category.name %>)
If you can write your own JavaScript why not use the Ruby's to_json() method to output your object in JSON to an embedded constant on your page and then write some JavaScript to access this variable and manipulate as needed?

Categories

Resources