Rails json include 2 instances of same model - ruby-on-rails

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

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

How do I include only last record in the response that contains associated records in Ruby On Rails?

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

Making several methods inside includes

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

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

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

Resources