Render hash with objects belonging to instance - ruby-on-rails

I have theses associations:
# Post
has_many :photos
# Photos
belongs_to :post
In my show action, in the post controller, I have this:
def show
#post = Post.find(params[:id])
#photos = #post.photos
render json: {post: #post.id }
end
However, I'd like the json to include the photos of the post, and get something like this:
{
post: 14,
photos {
photo1 {
url: /myURL/,
id: 1
},
photo1 {
url: /myURL/,
id: 2
}
}
}
I found many posts on how to do the opposite but not this. How should I approach this ?

You can do it this way:
render :json => #post, :include => [:photos => {:only => :url, :id}]

Related

Undefined method `build_for` for class in Rails

I have a simple app in which I want to allow the admin to create a new company. My create method in the controller is as follows:
def create
#company = Company.find_by({ name: company_create_params[:company_name] })
if #company.nil?
#company = Company.build_for(company_create_params)
else
return render :status => 200, :json => {
:error => true,
:reason => 'This company already exists in the database!'
}
end
if #company.save
return render :status => 200, :json => {
:success => true
}
else
return render :status => 500, :json => {
:error => true,
:reason => 'There was a problem adding the company'
}
end
end
private
def company_create_params
params.require(:company).permit( :company_name, :company_total_credits )
end
And my company model is:
class Company < ActiveRecord::Base
has_many :role
end
But every time I make an API post it gives me an error Undefined methodbuild_forfor class #<....>
Is it because of the has_many relationship? I don't want to add any value for the roles, rather I want them to be able to do it later on. Is there no way to fix this?
ActiveRecord doesn't provide a build_for method, hence the error.
You probably meant build, which is a method defined on collection associations. In this case, you probably want new or create since Company is a model, not an association.
Your whole action could be reduced significantly by following some conventions, by the way:
class Company < ActiveRecord::Base
has_many :roles
validates :company_name, uniqueness: true
end
# controller
def create
#company = Company.new(company_create_params)
if #company.save
render json: { success: true }
else
render status: 500, json: {
error: true,
reason: #company.errors.full_messages.to_sentence
}
end
end

Accessing has_one relationship through JSON with React.js and Rails

I'm creating a simple comment form using React.js inside my Rails application. When I submit a comment, I'm unable to render the author's name with the comment.
TypeError: comment.user is undefined
React.createElement(Comment, {username: comment.user.name, body: comment.body key: comment.id}
commentlist.jsx.erb
var CommentList = React.createClass({
render: function () {
var commentNodes = this.props.comments.map(function ( comment ) {
return <Comment username={ comment.user.name } body={ comment.body } key={ comment.id } />
});
return (
<div className="comment-list">
{ commentNodes }
</div>
)
}
});
commentscontroller.erb
def index
#presenter = {
:comments => Comment.last(5),
:form => {
:action => comments_path,
:csrf_param => request_forgery_protection_token,
:csrf_token => form_authenticity_token
}
}
end
def create
#comment = Comment.new(comment_params)
#comment.commentable = #event
#comment.body = comment_params[:body]
#comment.user_id = current_user.id
#comment.save
if request.xhr?
render :json => Comment.last(5)
else
redirect_to comments_path
end
end
comments/index.html.erb
<%= react_component('CommentBox',
{:presenter => #presenter.to_json(:include => :user)},
{:prerender => true}) %>
Anyone know how I can fix this? Just let me know if I'm missing any code samples.
UPDATE
This doesn't answer my question, but it's a solution. I added an author method to the comment model that returns the commenter's name, so I can now access the name directly from the comment.
def author
User.find(self.user_id).name
end
Though I'd still like to know how to access through an association.
def as_json
{:author => self.user.name}
end
And wherever you are rendering json object just call Comment.last.as_json
Refer http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/

param is missing or the value is empty: user_club - rails

I want to call create action of controller user_clubs and I did this way:
View Clubs
<button>
<%= link_to "Join Club", user_clubs_path(:user_id => current_user.id, :club_id => #club.id, :join_date => Date.current), :method => :post %>
</button>
Controller user_clubs
def create
#user_club = UserClub.new(user_club_params)
respond_to do |format|
if #user_club.save
format.html { redirect_to #user_club, notice: 'User club was successfully created.' }
format.json { render :show, status: :created, location: #user_club }
else
format.html { render :new }
format.json { render json: #user_club.errors, status: :unprocessable_entity }
end
end
end
def user_club_params
params.require(:user_club).permit(:user_id, :club_id, :join_date) --->**Error here**
end
Error information
app/controllers/user_clubs_controller.rb:75:in user_club_params'
app/controllers/user_clubs_controller.rb:28:increate'
Request
Parameters:
{"_method"=>"post",
"authenticity_token"=>"5Grhb+LIGt9B8XbnEcvg7BZQlDE935KO/aeikZoqxYs=",
"club_id"=>"1",
"join_date"=>"2014-11-17",
"user_id"=>"2"
}
Clubs and UserClubs are different. Club is a model that represents a team of people and user_clubs is the model that represents the many-to-many relationship between Users and Clubs.
First, can someone explain me how the call to user_clubs_path followed by the arguments know that has to go to the action create of user_clubs controller?
In second, the objective problem, why is this an error?
First question
Because of your routes definition, type into a terminal:
rake routes
And you'll see all generated routes and its associated helpers. First column (rake output) references the named helper: user_clubs => user_clubs_path):
Second question
You should add the parameters into user_club key, because you're requiring (by strong_parameters) this "scope" params.require(:user_club):
user_clubs_path(:user_club => {:user_id => current_user.id, :club_id => #club.id, :join_date => Date.current})
You'll receive in the controller:
{
"_method" => "post",
"authenticity_token" => "...",
"user_club" => {
"club_id" => "1",
"join_date"=> "2014-11-17",
"user_id"=> "2"
}
}
The parameters need to be nested under the user_club key. Try this instead:
user_clubs_path(:user_club => {:user_id => current_user.id, :club_id => #club.id, :join_date => Date.current})

Rails json response including nested reources and their methods

Hello i"m trying desperately to render json that includes methods within my included nested resources. I tried many variants but just can't get that thing to run.
This is what i have:
format.json {render json: #user, :include => [ :votes, :petitions, :roles ] }
And that is what i had hoped to work
format.json {render json: #user, :include => {
:votes => { :methods => [ :status, :count_users_voted ] },
:petitions => { :methods => [:status, :count_users_voted] },
:roles
}
}
Any hints anyone?
Add something like this to your User model:
def as_json(options = { })
super((options || { }).merge({
:methods => [:agrees, :disagrees]
}))
end
def agrees
self.liked_by_count
end
def disagrees
self.disliked_by_count
end
Pretty straight forward, I hope this helps

How to Include additional field in Rails 3 Application JSON Response

I have a Rails application which displays nested form in json format.
In the JSON Response i am also displaying an id field which represent another table.
How to display name corresponding to that id what i am getting so that i can display both name and id in my json format.
My controller
show method
def show
#maintemplate = Maintemplate.find(params[:id])
respond_with (#maintemplate) do |format|
format.json { render :json => #maintemplate }
end
end
Thanks in advance....
Try this:
render :json => #maintemplate.to_json(:include => { :user => { :only => :name } } )
This will replace the user_id key with a user key and a value with only the name attribute of user, like this:
{
"user_id": "12"
"user": { "name": "..." }
...
}
You can then access the username in the json response with ["user"]["name"]. You can also access the user id with ["user_id"].
For more see the documentation on as_json.
Update:
Using the info provided in the comments, I think this is what you actually want:
render :json => #maintemplate.to_json(:include => { :routine => { :include => :user, :user => { :only => :name } } } )
Add to as_json method with the additional method-attributes you desire to the class in which you are calling.
class MainTemplate
...
def name
User.find(self.user_id).name
end
def as_json(options = {})
options[:methods] = :name
super(options)
end
end

Resources