Returning from rails controller - ruby-on-rails

Here's a beginner rails question...
After I do:
format.xml { head: ok}
How do I return from the controller endpoint without showing the view? If I drop off the end of the function at this point, I get what I expect, but if I call 'return', I end up in the view (or in my case in a missing view template). I can code up lots of if/else etc., but it would be nice to early out from the function without ending up in a view template.
I've searched around and can't figure out what the obvious answer is to this; it must be straightforward...

You can use "render :nothing => true, :status => :ok" to return without rendering anything, once you have send a render :nothing => true you need to return from the controller, something like this might work. You can swap the head() method call for a render => :nothing followed by a return, the head() method is documented here:
api.rubyonrails.org/classes/ActionController/Base.html#M000635
Here's the code that should do it for you...
gist.github.com/126367
Ping me if that doesn't properly answer your question, documentation for the render call with some helpful user comments can be found here:
apidock.com/rails/ActionController/Base/render
(sorry I couldn't hyperlink the links for you, as a new user stackoverflow won't allow me to post more than one!)

Use
render :nothing => true, :status => :ok
in your action method

I guess you must be asking for :
render :nothing => true

Related

Rails Controller -- just return the processed data (dont load into a view)

I'm new to Ruby and Rails. I just completed a course in Laravel, so I am aware of the MVC system(not a newbie as far as the basic concepts are concerned).
I have a rather simple question,
I am sending a POST request to my RAILS REST API,the body of the post request contains a json encoded string like this--->
Array ( [method] => POST [timeout] => 45 [redirection] => 5 [httpversion] => 1.0 [blocking] => 1 [headers] => Array ( ) [body] => {"post_content":"here is the post","post_title":"here we are ","post_author":"1"} [cookies] => Array ( ) )
As you can see,its coming from my php based blog.
My rails API is supposed to be taking the post content and automatically adding links to certains words, by comparing the words with some stuff that i have in an SQLite database.
Ok, so my problem is this:
I just want the response from the Rails controller, I dont want anything loaded into a view. The Rails Controller - returns the content, with 'a href' tags around words that are found in my database. This is to be sent back as the response to my post request, and i want to access it directly as the body of the response.
As of now I dont know how this is to be done. Laravel has the ability to 'return' whatever you want to , at the end of the Controller Action, but in Rails, everything seems to want to load into a view.
I have researched some questions here and found one which said 'render :nothing => true',but that renders nothing at all.Here is what my code looks like.
def process
content = params['post_content']
##perform db function and get back the content with the links embedded.
##HOW TO RETURN THIS CONTENT.
end
Personally, I think, i have to use the render_to_string method, but I have no idea how to do this.
Any help is appreciated.
Best Regards,
Richard Madson.
Some options to consider:
Render just the raw string as the http response body:
render :text => content
Render a view without the default surrounding layout:
render :layout => false
In that case your view could just be:
<%= #content %>
Or render the content as json:
render :json => { :content => content }
The question is, what do you want returned? Text? XML? JSON?
I'm going to assume you want JSON back based on the JSON going in.
respond_to do |format|
format.json { render json: #someobject }
end
It might be helpful to see the rest of the controller method.
If I understand correctly believe what you are looking for is
render :text => "response"
there is also - JSON, XML, nothing, js, file, etc - more information here http://guides.rubyonrails.org/layouts_and_rendering.html

API and Rails with JSON

I'm really confused on the concept of this.
I'm supposed to make API that handles JSON responses. I read this
and other places, they all showed example on how to do it for the show or index aspect of the controller. I understand that, where you outputs all the attributes of the model. But my main question is, if somebody were to create or edit, what do I do with the whole JSON on there?
If all you need to do is pass back a 200 for a successfull create, then don't creating a response.
render :nothing => true
If on the other hand, you added some important information to the object that you are updating that the client will require (If you are not sure, then assume that the client will require it), then you should pass the updated object's attributes back
respond_to do |format|
format.json {render :json => {... }}
end

How do you call a model's show url from a Rail create controller?

I'm having trouble calling a model's show path from within a create controller.
I'm using the Koala gem in a Rails 3.2 app. I'm trying to publish to Facebook's open graph automatically when a User creates a particular record type.
I have a page set up with all the required FB meta tags.
I can run the Koala methods from the console and everything works fine.
But if I try to run this from the controller I get an error.
My controller looks like this:
def create
#fb_model = current_user.fb_models.build(params[:fb_model])
if #fb_model.save
Koala::Facebook::API.new(app_token).put_connections( current_user.fb_uid, "namespace:action", :object => fb_model_url(#fb_model) )
respond_to do |format|
format.html { redirect_to(#fb_model, :notice => 'Successfully created.') }
format.xml { render :xml => #fb_model, :status => :created, :location => #fb_model }
end
else
respond_to do |format|
format.html { render :action => "new" }
format.xml { render :xml => #fb_model.errors, :status => :unprocessable_entity }
end
end
end
When I create a record, my logs show:
Koala::Facebook::APIError (HTTP 500: Response body: {"error":{"type":"Exception","message":"Could not retrieve data from URL."}}):
If I edit the controller to use a static url for testing, everything works fine.
...
if #fb_model.save
Koala::Facebook::API.new(app_token).put_connections( current_user.fb_uid, "namespace:action", :object => "http://myapp.com/fb_model/2" )
...
Why can't I pass the record's url to FB from within the create controller using fb_model_url(#fb_model)?
I eventually got to the bottom of this. It's actually a really frustrating issue, as there is no indication that this is the problem in any logs or elsewhere.
The problem was that I was deploying/ testing on Heroku, and only had 1 web dyno running. My app was unable to handle both the Facebook request and the post/ get simultaneously, causing the error.
This has been addressed in another question Facebook Open Graph from Rails Heroku. It's really not what I was expecting, and I didn't come across this question in any of my earlier searching. Hopefully this can help someone else.
I solved the issue by switching from thin to unicorn.
build is finalised when the parent model is saved, and you dont seem to be operating on a parent.
I think you actually want this:
#fb_model = current_user.fb_models.new(params[:fb_model])
Also you seem to be calling #fb_model.save twice which is wrong.
Thanks for posting your findings - I've been dealing with this issue for the past couple of days and wouldnt have figured that. So when you simply increased your dyno load, you no longer had this error? I was on the verge of just using the Javascript SDK even though my 'put_connections' callbacks work in the heroku console.

Basic Ruby on Rails AJAX Error

I'm working through Agile Web Development with Rails, Edition 4 with some tweaks (mostly just naming variations), and I've arrived at Iteration F2. In this iteration, you modify the index button with :remote => true, you add format.js to the respond_to section of the controller, and you generate a js.rjs file to execute the AJAX render. Or at least that's my interpretation of it. The goal of these steps is to have a cart (in this case, a team) in the sidebar update using AJAX when adding new line items (in this case, members)
In my case, I'm trying to add members to a team. Her's some code snippets I've added:
index.html.erb:
<%= button_to 'Add to Team', members_path(:player_id => player),
:remote => true %>
members_controller:
def create
#team = current_team
player = Player.find(params[:player_id])
#member = #team.add_player(player.id)
respond_to do |format|
if #member.save
format.html { redirect_to(nba_url) }
format.js
format.xml { render :xml => #member,
:status => :created, :location => #member }
else
format.html { render :action => "new" }
format.xml { render :xml => #member.errors,
:status => :unprocessable_entity }
end
end
end
create.js.rjs:
page.replace_html('team', render(#team))
The page is able to render, and I'm still able to click the button to add members to the team. However, the AJAX isn't working. When I reload, I can still see that the members have been added in the sidebar. All of the other team functionality remains, as I'm able to empty the team and add whichever members I wish. When I check the server log, I find the following error:
Error:
ActionView::Template::Error (undefined local variable or method `page' for #<
#<Class:0x413e1b8>:0x413cb20>):
1: page.replace_html('team', render(#team))
app/views/members/create.js.rjs:1:in `block in _app_views_members_create_js_rj
s___908569197_34199712_807066544'
app/views/members/create.js.rjs:1:in `_app_views_members_create_js_rjs___90856
9197_34199712_807066544'
app/controllers/members_controller.rb:47:in `create'
Based on this it seems like it has found the create.js.rjs but is having trouble interpreting it. I'm not sure what the weird symbols are in front of page.
Edit: I've also found that if I view the source code before and after clicking the button, the button is indeed refreshing the code and adding the desired items. The problem seems to be exclusively in trying to refresh the partial.
Any help is appreciated. Thanks!
It seems your rjs file has some invalid bits at the start. Maybe try to re-create the file?
What did you expect to do with render(#team) ?
I've taken a look at the action view's method "render" and didn't found how you were expecting it to function. Maybe there is another functionality that you are aware and I don't.
You can also use erb and not rjs, using it just like a view
Along the lines of Bert Goethal's answer, is your editor saving your text file as UTF-8 with BOM?
A BOM will add two unicode encoded characters to the beginning of the file, and that might be where those are coming from...

Partial not updated on first click

I am having problems with a remotely executed action and a partial that doesn't update the first time I click the link.
Inside the view (a partial named books) I am creating a link:
link_to "⊗", read_book_path(book), :remote => true
The read_book_path is defined in routes.rb
There is also a conditional that displays a different text when that book is read.
Inside my controller, I have defined a new action:
def read
#books = Book.all
#book = Book.find(params[:id])
#book.read = !#book.read
#book.save
respond_to do |format|
format.html { redirect_to(books_url) }
format.js {render :layout => false, :locals => { :book => #book } }
end
end
This means I need a file read.js.erb, this file's content is:
$("#books").empty().html("<%= escape_javascript( render(:partial => "books") ) %>");
When I click the link, I can see in the terminal window that the database field is updated but the partial is not. Clicking the same link again updates the partial.
Changing the link to :remote => false also works but the page reloads (as expected).
I have tried to debug it with Safari and the Developer tools and I can see the server's response when clicking the link for the first time.
Something is wrong there, the HTML generated by <%= escape_javascript( render(:partial => "books") ) %> contains the wrong HTML with the old content of the partial. Only the second or third click shows the updated HTML.
I have integrated jquery-ujs - is that the reason the partial doesn't update the first time or am I missing something else?
This really gave me a headache, can you help me?
Edit:
If that helps: I created a listener in application.js to ajax:before and ajax:complete. The first one shows a little spinner, the second one hides it.
When I click the link, the spinner shows but it doesn't hide.
It looks like you have an ordering problem that's causing the trouble. You're capturing a complete set of books into the #books variable and then modifying a separate copy of a single book. This change will not be propagated back.
# Load and modify the one book by flipping the flag
#book = Book.find(params[:id])
#book.read = !#book.read
#book.save
# Load all books
#books = Book.all
As a note this is an extremely inefficient way of doing things, so I hope you're not working on a large amount of data. You might find it's easier to do this by simply toggling the one field with a simple UPDATE query:
Book.update_all({ :read => true }, { :id => params[:id] })
I'm not sure why you're calling $(...).empty().html(...) instead of simply $(...).html(...) since the html() method should replace the HTML wholesale with no need to clear it in advance.
One thing that might help is using .js.rjs where the equivalent would be:
page[:books].replace_html(:partial => 'books')
With simple JavaScript, RJS allows you to eliminate a lot of the drudgery. You can use JS in RJS as well for cases where there is no equivalent:
page << '$("#books").empty()'
page[:books].replace_html(:partial => 'books')
To make this more Rails friendly, you could call your partial _book which would make the local variables redundant. Each partial has a default variable with a name matching the template name:
render(:partial => 'book', :collection => #books)

Resources