Rails json response including nested reources and their methods - ruby-on-rails

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

Related

Render hash with objects belonging to instance

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}]

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})

Create Nested Object with Rails 4 (JSON call)

I am refactoring a project, and I remembered that I had some troubles in realizing how to put a nested object, but I found this question useful.
So, as I understand it, you needed to pass as a parameter your associated model name in plural and add a '_attributes' to it. It worked great in Rails 3.2.13.
Now, here is what I have in Rails 4:
class TripsController < Api::V1::ApiController
def create
begin
#user = User.find(params[:user_id])
begin
#campaign = #user.campaigns.find(params[:campaign_id])
if #trip = #campaign.trips.create(trip_params)
render json: #trip, :include => :events, :status => :ok
else
render json: { :errors => #trip.errors }, :status => :unprocessable_entity
end
rescue ActiveRecord::RecordNotFound
render json: '', :status => :not_found
end
rescue ActiveRecord::RecordNotFound
render json: '', :status => :not_found
end
end
private
def trip_params
params.require(:trip).permit(:evnt_acc_red, :distance, events_attributes: [:event_type_id, :event_level_id, :start_at, :distance])
end
end
And the Trip model looks like this:
class Trip < ActiveRecord::Base
has_many :events
belongs_to :campaign
accepts_nested_attributes_for :events
end
So, I am doing a POST call with the following JSON:
{"trip":{"evnt_acc_red":3, "distance":400}, "events_attributes":[{"distance":300}, {"distance":400}]}
And, even though I don't get any kind of error, no event is being created. The trip is being created correctly, but not the nested object.
Any thoughts on what should I do to make this work on Rails 4?
Alright, so... I was sending the JSON wrongly:
Instead of:
{
"trip": {
"evnt_acc_red": 3,
"distance": 400
},
"events_attributes": [
{
"distance": 300
},
{
"distance": 400
}
]
}
I should have been sending:
{
"trip": {
"evnt_acc_red": 3,
"distance": 400,
"events_attributes": [
{
"distance": 300
},
{
"distance": 400
}
]
}
}

Syntax error in as_json when using multi level :include

I've got two models that are connected through a third one:
Playlist has_many :song_in_playlists, :dependent => :destroy
has_many :songs, :through => :song_in_playlists
Song has_many :song_in_playlists, :dependent => :destroy
has_many :playlists, :through => :song_in_playlists
The song_in_playlist table simply lists the playlist_id, song_id, as well as a track_number.
When calling /playlists/1.json, I'd like to get a json hash that holds the playlist's attributes and has another hash inside, which contains the songs (as in /songs.json plus the track_number from the song_in_playlists table entry).
According to the Rails API, I should be able to achieve this doing the following:
def show
#playlist = Playlist.find(params[:id])
[...]
respond_to do |format|
format.html # show.html.erb
format.json { render json: #playlist.as_json(
:include => { :song_in_playlists => {
:only => :track_number, :include => :songs {
:except => [:dropbox_link, :local_path] } } }
) }
end
end
end
However, what I do get is the following:
/home/sloth/audiomixer/app/controllers/playlists_controller.rb:30: syntax error, unexpected '{', expecting '}'
:only => :track_number, :include => :songs {
^
/home/sloth/audiomixer/app/controllers/playlists_controller.rb:31: syntax error, unexpected '}', expecting keyword_end
:except => [:dropbox_link, :local_path] } } }
^
/home/sloth/audiomixer/app/controllers/playlists_controller.rb:103: syntax error, unexpected $end, expecting keyword_end
So I tried a little less complexity, calling
format.json { render json: #playlist.as_json(
:include => song_in_playlists {
:only => :track_number } ) }
but I'm getting a similar error. As soon as I'm putting any braces in between the parentheses, Rails complains, although the API documentation states the opposite.
I really don't know what to try anymore :(
PS: Ruby 1.9.3, Rails 3.2.13
--- EDIT ---
Okay, I don't really know why but I got this to produce the expected output:
format.json { render json: #playlist.as_json(
:include => { :song_in_playlists => {
:include => :song, :only => :track_number } } ) }
However, when trying to add { :except => [:dropbox_link, :local_path] } in between :song and , :only, I'm getting the same errors again..
This is only partly about rails
:include => song_in_playlists {:only => :track_number}
just isn't valid ruby syntax
this should be
:include => {:song_in_playlists => {:only => :track_number}}
Each time, the key is the association name (song_in_playlists) and the value is hash containing one or more of the keys :only, :except or :include
If you want to change what attributes from the songs table are in the json then you need to take
format.json { render json: #playlist.as_json(
:include => { :song_in_playlists => {
:include => :song, :only => :track_number } } ) }
and replace :song with a hash that describes what you want to do with song, for example
format.json { render json: #playlist.as_json(
:include => {
:song_in_playlists => {
:include => {
:song => {
:except => [:dropbox_link, :local_path]
}
},
:only => :track_number
}
})}

to_json :include :order?

Is it possible to order included models?
format.json { render :json => #client.to_json(:include => { :videos => { :order => 'sortorder' } }) }
You need made when you create your #client. In your SQL request

Resources