im trying to add some methods inside some includes with as_json in rails, but the second includes with method doesnt shows on the json. this is the code
format.json { render :json => { :projects => #projects.as_json(:include => [
:retail,
:property => {:methods => :name},
:user => {:methods => [:name, :address] } ] ) } }
and this is the json generated:
{"projects":[{"comment":null,"contractor":1,"created_at":"2013-10-17T16:57:36Z","id":5,"property_id":3,"retail_id":1,"updated_at":"2013-10-17T16:57:36Z","user_id":2,"retail":{"address":null,"created_at":"2013-10-16T22:29:38Z","id":1,"name":"asdasdsa","phone":"6677969224","property_id":null,"social_reason_id":null,"updated_at":"2013-10-17T17:18:09Z","web":"www.boxie.io"},"property":{"city":"Culiacan","colony":"Fracc Los Sauces","coordinates":"(24.7802016, -107.34894730000002)","country_id":1,"created_at":"2013-10-17T00:56:32Z","external_number":null,"id":3,"internal_number":2848,"population":null,"state_id":4,"street":"Alame\u00f1a","updated_at":"2013-10-17T00:56:32Z","zipcode":8028,"name":"Calle Alame\u00f1a, Fracc Los Sauces, 8028, Culiacan, Campeche Mexico"}}]}
as you can see the user information doesn't appear on the json.
Thank you
You didn't wrap them correctly, Your second and third child association should be hashes.
#projects.as_json(:include => [
:retail,
{ :property => {:methods => :name } },
{ :user => {:methods => [:name, :address] } }
]
Related
I have model called Exchanges that stores a user_id of the user who created it. I can call #exchange.user and it returns User.where(user_id: #exchange.user_id)
There's also an association to show all the users who have favorited an Exchange, which can be called with #exchange.favorite_users
I want to return both of these, in the json response, but only the first one is being returned.
#exchanges = Exchange.includes(:tags, :favorite_users, :user).where(approved: true)
respond_to do |format|
format.json { render json: {data: {exchanges: #exchanges.to_json(include: [:tags, user: {:only => [:id,:slug], :methods => [:avatar_url]}, favorite_users: { only: [:id]}] ), tags: #tags.to_json }}}
end
This version returns user: {:only => [:id,:slug], :methods => [:avatar_url]}, but not favorite_users: { only: [:id]}.
format.json { render json: {data: {exchanges: #exchanges.to_json(include: [:tags, favorite_users: { only: [:id]}, user: {:only => [:id,:slug], :methods => [:avatar_url]}] ), tags: #tags.to_json }}}
This one only returns favorite_users: { only: [:id]}, but not user: {:only => [:id,:slug], :methods => [:avatar_url]}
How can I return both?
Exchange Model
class Exchange < ApplicationRecord
belongs_to :language
belongs_to :user
has_many :exchanges_users
has_many :favorite_users, :through => :exchanges_users, source: :user
has_many :tags_exchanges
has_many :tags, :through => :tags_exchanges
end
#exchanges.to_json(include: [
:tags,
{user: {only: [:id,:slug], methods: [:avatar_url]}},
{favorite_users: { only: [:id]}}
])
If you want to return both of associate model, wrap an association by using {}
Brakets only use just association symbol but cannot options
this function works. However, instead of including all the rounds. I just need to include the last one. How would I do it? I looked into using :scope but haven't found anything useful. Please help, it's driving me nuts!
def get_games_list
Rails.logger.info("get_games_list".colorize(:color => :white, :background => :blue))
player_1_games = Game.includes(:rounds, :player_2).where(:player_1_id => params[:player_id], :is_valid => true)
player_2_games = Game.includes(:rounds, :player_1).where(:player_2_id => params[:player_id], :is_valid => true)
render json: {
error_code: ERROR_NOERROR,
status: "ok",
player_1_games: player_1_games.as_json(
:include => {
:player_2 => {
:only => [:id, :user_name]
},
:rounds => {
:only => [:id, :playing_player_id]
}
}
),
player_2_games: player_2_games.as_json(
:include => {
:player_1 => {
:only => [:id, :user_name]
},
:rounds => {
:only => [:id, :playing_player_id]
}
}
)
}
return
end
You could create a :last_round has_one association in the Game model.
class Game < ApplicationModel
# ...
has_one :last_round, -> { order(round_date: :desc) }, class_name: 'Round'
# ...
end
I am working on this code:
render json: User.find(params[:id]).to_json(
:include =>
{
:user_quests => { :inlcude => { :quest }, :only => { :id } },
:user_skills
},
:except =>
{
:authentication_token,
:email
}
)
It results in a SyntaxError. The only working code I currently have is:
render json: User.find(params[:id]).to_json(
:include =>
[
:user_quests,
:user_skills
],
:except =>
[
:authentication_token,
:email
]
)
But I need to pass further parameters to only one of the associations to perform a nested include. The other one (:user_skills) should be fetched the same way as in the working code. How do I do that?
This code results in a syntax error, because you don't use collections properly. An array ([]) is a list of values, whereas a hashmap (or simply hash, {}) requires key-value pairs.
In to_json's context an array of associations:
[
:user_quests,
:user_skills
]
...is roughly equivalent to a hash of associations mapped to empty option hashes:
{
:user_quests => {},
:user_skills => {}
}
Having performed that transformation, you can selectively add options wherever you like.
Here it is solution which works for me and is compatible with Rails 4:
render json: User.find(params[:id]).as_json(
include:
{
user_quests:
{
include:
{
quest:
{
only: :_id
}
}
},
user_skills:
{
}
},
except: [:authentication_token, :email]
)
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
}
})}
I have an instance of an object that is created like this:
Example.create(:attrib0 => {
:attrib1 => value,
:attrib2 => [
{:attrib3 => value},
{:attrib4 => value}
]
})
How can I access :attrib4?
You should use serialize in your model, then you'll be able to return the hash correctly:
class SomeModel < ActiveRecord::Base
serialize :attrib0
end
Then the following should return the hash
hash = #model.attrib0
# => {:attrib1 => value, :attrib2 => [{:attrib3 => value}, {:attrib4 => value}]
# now to access attrib4 you need to get the attrib2 array,
# then grab attrib4 by its index:
hash[:attrib2][1]
# => {:attrib4 => value}
# or to get the value:
hash[:attrib2][1][:attrib4]
# => value
The above however can get quite complex and ugly, which is why I recommended creating another model for these attributes instead.
I think you should use nested attributes. Here's how it can be:
class Example
has_one :attrib0
accepts_nested_attributes_for :attrib0
end
params = { :attrib0 => { :attrib1 => value1,
:attrib2 => [ {:attrib3 => value3}, {:attrib4 => value4} ] }
}
example = Example.create(params[:attrib0])
example.attrib0.attrib1 #=> value1
example.attrib0.attrib2 #=> [ {:attrib3 => value3}, {:attrib4 => value4} ]
Using Ruby technique only:
h = {:attrib0 => {
:attrib1 => :value1,
:attrib2 => [
{:attrib3 => :value2},
{:attrib4 => :value3}
]
}}
p h[:attrib0][:attrib2].last[:attrib4] #=> :value3