Adding POST Params to render json methods in Ruby on Rails - ruby-on-rails

I have a method called is_following in the user.rb model, and it checks to see if one user is following another.
Users Controller
def show
#user = User.find(params[:id])
respond_to |format|
format.json { render json: #user, :methods => [:image_url, :is_following] }
end
User Model
def is_following params
return "yep" if params[:follower_id] == id
end
However, I don't know how to pass params into the :is_following method in the controller. Anyone have any luck or solution to this?

This may not be the answer you're looking for but it definitely a solution. I recommend you stop using render to generate your JSON.
Gems such as jbuilder or rabl make it easier and gives you more flexibility.
Ruby on Rails is a MVC framework. You should leave view generation at the view layer. Doing this will save you from much more pain you'll endure in the future.

Related

respond_with ArgumentError (Nil location provided. Can't build URI.):

I have a controller that responds_with JSON for all of the RESTful actions, index, create, update etc,
class QuestionsController
respond_to :json
def index
respond_with Question.all
end
end
However, I also have other actions in the controller. For example, in one method, it checks whether a response was correct and then tries to return a variable with a boolean true or false
respond_with correct_response #either true or false
However, this is giving me the error
ArgumentError (Nil location provided. Can't build URI.):
There will also be other methods that I'll wish to respond with multiple values. In Sinatra, you can do this to respond with json
{:word => session[:word], :correct_guess => correct_guess, :incorrect_guesses => session[:incorrect_guesses], :win => win}.to_json
How would I do that in Rails?
So, two questions, what's the proper way to write this
respond_with correct_response
and how to respond_with multiple values in a way similar to the example I showed from a Sinatra app.
Thanks for your help.
You want ActionController::Base#render, not respond_with. The proper way to do what you're trying to achieve here is:
render json: {word: session[:word], correct_guess: correct_guess, incorrect_guesses: session[:incorrect_guesses], win: win}
respond_with is actually OK for this scenario--it just happens to do some magic for you and relies on having access to info it needs; take a look at Rails 4.1.9's actionpack/lib/action_controller/metal/responder.rb.
In your case, ArgumentError (Nil location provided. Can't build URI.) is actually telling the truth--it's trying to determine a URL to use from the location header setting but isn't able to figure it out. I'd wager you could get your code working if you gave it one:
class QuestionsController
respond_to :json
def index
respond_with Question.all, location: questions_url
end
end

How to use Rails respond_with with a create action and javascript?

I've been reading about respond_with. and used it before in a couple of tutorials but dont really think I understand it fully.
The functionality I am trying to implement right now is this: I have a list of items of class Article, and each of them has a link to the create Favorite action. When the user clicks on it it the favorite instance is created and the user is redirected to the home page. I want this to work with AJAX without a page refresh, and execute some JavaScript on the article item to let the user know it's been favourited successfully. I've used the :remote => true attribute in the relevant link, so the action is executing remotely without problem, but I am a bit stuck on how to execute the action's .js.erb file.
I've done the following in the controller:
class FavouritesController < ApplicationController
before_filter :authenticate
respond_to :html, :js
def create
#article = Article.find_by_id(params[:article_id])
current_user.Favourites.create(:article => #article)
redirect_to root_path
end
The problem is, I dont know what parameter should i pass to respond_with. I've tried replacing the redirect with both respond_with #article, and respond_with without parameters, and while both of them work (the create.js.erb is called), I dont understand why...
I dont want to 'respond_with' anything, but only that when the action is executed via javascript, the create.js.erb gets called. Can anyone explain a) why does respond_with work anyway whatever I pass to it, and b) what is the right way to do this?
BTW, I am using Rails 3.0
EDIT: I understand it better if I use respond_to like in the following code, but I would like to understand respond_with better.
respond_to do |format|
format.html { redirect_to root_path }
format.js
end
I ran across this question several times trying to solve a similar problem. It turns out my controller wasn't inferring the format as I assumed it would from the content type or the fact that it's an xhr request.
In any case, it worked when I switched from this:
contacts_path
To this:
contacts_path format: :json
I didn't care for that per se, so I changed my ajax call to include the dataType option like this (per jQuery ajax documentation):
$.ajax({url: contactUrl, type: 'POST', data: data, dataType: 'json' });
Hi Oalo go through the link below, it concisely explains the respond_with and respond_to. It lists all the options that you can pass to respond_with
http://ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with
Hope this answers your query

Give a detailed illustration of how the MVC works in Rails, and how the controller communicates with forms etc?

Perhaps this can even become a Community Wiki, but I would love a detailed description of how the controller works - or rather, how I can get it to do what I want it to do.
I understand the general structure of MVC and how the model stores the db structure, and the controller interacts with the db and passes info to the view.
However, I am puzzled (on a fundamental level) about how to accomplish simple tasks using my controller. I know that if I want to create a new record for a model/object, I just do object = Object.new(:name => "Object Name") in the Rails console.
But how on earth would I do that in the CRUD elements of the controller and why?
Please use a simple example - e.g. showing a user the balance of their bank account (I know there are many complexities surrounding this, but ignore them for the sake of this explanation). What would the model look like (just include: Name, Address, Transaction Type (Deposits/Withdrawals), Balance).
What would a view look like? What would the controller look like? Any choices you make (like using a form) please explain them. Why would you use a form, as opposed to a drop down menu and (in layman terms) how does the form or drop down menu interact with the controller? How do I get the info captured there to the db and why am I doing it that way?
I know this sounds like a lot to ask, but I have done RailsTutorial.org, watched many Railscasts, read the Rails guides, and read many other tutorials and still have some basic gaps in my understanding of the way Rails works and why.
Thanks in advance.
I don't know how much more help I can be, but I understand your pain having just come to rails myself. The article recommended by ghoppe, "Skinny Controller, Fat Model" explains the function of Ms Vs & Cs nicely. Seeing as that does not fully answer your question I will try to explain the mechanics of each structure.
Model
class Account < ActiveRecord::Base
belongs_to :user
validates_presence_of :address
def name # Account does not have a name field, but User does so I will make a name method for Account and feed it name of the user it belongs to.
user = self.user # Account gets the user method with the <belongs_to :user> association
# note: Rails expects Accounts to have a user_id field so it can perform the "magic" to associate Accounts with Users
if user.name
return user.name
else
return nil
end
end
end
The model describes your object. Like an object in any OOP language you want to put all of your object logic here. This includes the rails helpers for association(has_one, belongs_to, ...) and validation, as well as any other method or library you want the object to be able use throughout your Models Views and Controllers.
Controller
class AccountsController < ApplicationController
before_filter :name, :only => :edit, :destroy # #account.name will be executed before the edit or destroy method(action) can be invoked on #account. If the user who has the account has a name the action will execute.
def index # This is a RESTful action and is mapped by Rails by default to an HTTP GET request. Rails expects an index.html.erb or index.haml.erb or index.something in the Accounts view to map this action to.
#accounts = Account.all # #accounts is an instance variable and will be accessible in the view this action is mapped to.
end
def show
#account = Account.find(params[:id]) # params[:id] is passed to the controller from the view. The params hash is the primary tool form moving data from a form or URL into a controller. Anytime you click on the link_to the show or edit action of an object Rails will put that objects id in the params hash and call the appropriate action in that objects controller. If you click the show link on an account it will call this action. Now the instance variable in the view show.html.erb will hold a single account instead of an array
end
def new
#account = Account.new # This initializes a new account with all the fields set to blank unless you specified a default in your migration. This account has not been save to the db yet. It is ready for a user to fill in.
respond_to do |format| # Rails can automatically respond differently to different client request. If a client i.e browser wants HTML rails responds with HTML. If a client e.g. an API want XML Rails responds with XML.
format.html # new.html.erb #
format.xml { render :xml => #account }
end
end
def edit
#account = Account.find(params[:id]) # Same as show, but mapped to a different view
end
def create # Finally we have a POST. All the prior actions were GETs, but now we are saving some data to the db.
#account = Account.new(params[:account]) # The :account key is special. It is a hash of hashes. It is populated by the form fields in new.html.erb. To access a specific field such as address we say <params[:account][:address]> and whatever the user entered in the address field in the View is at out fingers in the Controller.
respond_to do |format|
if #account.save # If the validations pass and the account gets saved redirect to the show page of the new record, otherwise refresh/render the new page (hopefully showing what error caused the record to fail to save).
format.html { redirect_to(#account, :notice => 'Account was successfully created.') }
format.xml { render :xml => #account, :status => :created, :location => #account }
else
format.html { render :action => "new" }
format.xml { render :xml => #account.errors, :status => :unprocessable_entity }
end
end
end
def update # This is another of the seven RESTful Rails actions and results in a PUT request because you are updating an existing record
#account = Account.find(params[:id])
respond_to do |format|
if #account.update_attributes(params[:account])
format.js # Rails can also respond with JavaScript. Look up UJS. Rails 3 has made large improvements here.
format.html { redirect_to(#account, :notice => 'Account was successfully updated.') }
format.xml { head :ok }
else
format.js
format.html { render :action => "edit" }
format.xml { render :xml => #account.errors, :status => :unprocessable_entity }
end
end
end
def destroy # This results in a DELETE
#account = Account.find(params[:id])
#account.destroy # destroy is a more thourough delete and will check the options of this records associations and destroy the associated objects as well if they are dependant on this object. The option <:dependant => :destroy> is not set for this object's only association: User. The user this account belongs to will therefore survive the destruction of this account.
respond_to do |format|
format.html { redirect_to(accounts_url) }
format.xml { head :ok }
end
end
end
View
Hopefully you can draw your own logic from here. The view is designed to render information passed as instance vars from a controller to a client: browser, api, smart phone. As well as to pass information from a client to the controller via the params hash. No complicated logic should get performed in a view even though a view with erb has the capability to execute any ruby code.
If an example view would also be helpful I am happy to oblige.
The best description of what the controller is:
http://edgeguides.rubyonrails.org/action_controller_overview.html
http://edgeguides.rubyonrails.org/routing.html
The controller doesn't communicate with the Database. The controller talks to the model, which then communicate with the database.
When I was starting I found very useful to use scaffolding and just looking at what was created.
Do this:
rails generate scaffold Post name:string title:string content:text
Examine all files under the app/ folder. Examine the file config/routes
Then comment here your specific questions.
At first, I thought this question was far too broad, along the lines of "how do I program?" But after reading your comments, I see what you're getting at. You don't quite grasp how MVC works in Rails and are wondering where your code goes.
What you should strive for is a Skinny Controller and a Fat Model. Keep logic out of views. So in your example, you calculate the account balance in the Model, and pass that information along (using the controller) to the view.
For a concise explanation for beginners with sample code, I recommend this article over here.

What options do you have in Rails in creating a Restful API?

I want people to be able to perform operations in ruby scripts using an API.
What options do you have in rails?
What if I want certain operations to be authenticated?
You can make any resource RESTful in rails by using resources in the routes.rb file. So if you have a table called items, then you could go resources :items. This will automagically make your controller accept any of the seven standard RESTful actions, new, create, index, etc.
Rails can deal with lots of different formats out of the box, html, json, xml, etc. So if you want someone to search your items, the code would look something like this when you go to a url that looks something like mydomain.com/items.json?search_term=HelloWorld:
class ItemsController < ApplicationController
def index
#item = Item.find_by_name(params[:search_term])
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #item}
format.json { render :json => #item } # this will get returned
end
end
end
If you want operations to be authenticated, then you could use something like the omniauth gem to do OAuth authentication via facebook, or something like that. You'll need some sort of library on your client side to manage the session as well, unless you recommend doing something icky like passing your user/pass in the URL.

How can I access data from a Ruby on Rails application externally?

I'm trying to work with the data in my Rails application from within a separate Ruby script.
I read this forum post in which some people suggest that the best way to work with your data is to encapsulate the database within one application, and then have this application provide an API for working with that data. Because it's apparently bad to integrate your database into several different applications.
Well, now I want to work with some data from my Rails app from another script, but on the same system. How can I achieve this?
I might want to work with the data from my Rails app remotely in the future, but also from a script. I'm assuming this might require JSON or SOAP, but I would like to know before I go researching it.
Have you take a look at ActiveResource? It's specifically designed to expose data from a Rails model to another Rails app over HTTP.
Since Ruby on Rails follows REST, your application is, by default, it's own API. For example, say you have the following controller:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
respond_to do |format|
format.html
format.xml { render :xml => #user}
format.js
end
end
def index
#users = User.all
respond_to do |format|
format.html
format.xml { render :xml => #users}
format.js
end
end
end
Now, when hitting that controller via the web browser, it will render your views as you would expect. For example:
GET /users/1 => /app/views/users/show.html.erb
GET /users => /app/views/users/index.html.erb
However, if you change your requests to be something like:
GET /users/1.xml
GET /users.xml
You'll be returned XML data instead of your HTML views. You can now access this data from any other application by using some sort of REST Client, or simply by calling cURL from any command line.
You can append any extension to the end of your URL, and it will find the appropriate respond_to section.
Accessing the data is simple too, just make a request to your application using something like HTTParty. Look at the examples, they're pretty good.

Resources