Create Nested Object with Rails 4 (JSON call) - ruby-on-rails

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

Related

Rails API: how translate json request in spanish if my model is in english?

Model convention parameters need to be in English, but the input JSON request keys need to send it in Spanish, how is the best practice for rails to accept parameters in Spanish and save in database?
MODEL:
class Player < ApplicationRecord
validates :name, :level, :goals, :salary, :bonus, :team, presence: true
end
INPUT:
{
"jugadores" : [
{
"nombre":"Snow",
"nivel":"C",
"goles":10,
"sueldo":50000,
"bono":25000,
"sueldo_completo":null,
"equipo":"rojo"
},
{
"nombre":"JC",
"nivel":"A",
"goles":30,
"sueldo":100000,
"bono":30000,
"sueldo_completo":null,
"equipo":"azul"
}
]
}
Controller:
...
def create
#player = Player.new(player_params)
if #player.save
render json: #player, status: :created, location: #player
else
render json: #player.errors, status: :unprocessable_entity
end
end
...
def player_params
params.permit( jugadores: [ :nombre, :nivel, :goles, :salario, :bono, :salario_completo, :equipo ] )
end
...
thnx
Ill tried to translate with I18n, but I can't solve translate ActiveController
$"translation missing: en.{"jugadores"=>{"name"=>"Irving"}}"

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 to use nested_attributes when processing JSON?

I'm trying to write an update method that processes JSON. The JSON looks like this:
{
"organization": {
"id": 1,
"nodes": [
{
"id": 1,
"title": "Hello",
"description": "My description."
},
{
"id": 101,
"title": "fdhgh",
"description": "My description."
}
]
}
}
Organization model:
has_many :nodes
accepts_nested_attributes_for :nodes, reject_if: :new_record?
Organization serializer:
attributes :id
has_many :nodes
Node serializer:
attributes :id, :title, :description
Update method in the organizations controller:
def update
organization = Organization.find(params[:id])
if organization.update_attributes(nodes_attributes: node_params.except(:id))
render json: organization, status: :ok
else
render json: organization, status: :failed
end
end
private
def node_params
params.require(:organization).permit(nodes: [:id, :title, :description])
end
I also tried adding accepts_nested_attributes_for to the organization serializer, but that does not seem to be correct as it generated an error (undefined method 'accepts_nested_attributes_for'), so I've only added accepts_nested_attributes_for to the model and not to the serializer.
The code above generates the error below, referring to the update_attributes line in the update method. What am I doing wrong?
no implicit conversion of String into Integer
In debugger node_params returns:
Unpermitted parameters: id
{"nodes"=>[{"id"=>101, "title"=>"gsdgdsfgsdg.", "description"=>"dgdsfgd."}, {"id"=>1, "title"=>"ertret.", "description"=>"etewtete."}]}
Update: Got it to work using the following:
def update
organization = Organization.find(params[:id])
if organization.update_attributes(nodes_params)
render json: organization, status: :ok
else
render json: organization, status: :failed
end
end
private
def node_params
params.require(:organization).permit(:id, nodes_attributes: [:id, :title, :description])
end
To the serializer I added root: :nodes_attributes.
It now all works, but I'm concerned about including the id in node_params. Is that safe? Wouldn't it now be possible to edit the id of the organization and node (which shouldn't be allowed)? Would the following be a proper solution to not allowing it to update the id's:
if organization.update_attributes(nodes_params.except(:id, nodes_attributes: [:id]))
looks super close.
Your json child object 'nodes' need to be 'nodes_attributes'.
{
"organization": {
"id": 1,
"nodes_attributes": [
{
"id": 1,
"title": "Hello",
"description": "My description."
},
{
"id": 101,
"title": "fdhgh",
"description": "My description."
}
]
}
}
You can do this sort of thing. Put this in your controller.
before_action do
if params[:organization]
params[:organization][:nodes_attributes] ||= params[:organization].delete :nodes
end
end
It will set the correct attribute in params and still use all the accepts_nested_attributes features.

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 Post array of data all at one time?

I have a Rails 3 Application that is trying to post an array of users, all at one time. I am trying to post through the Postman REST client. If I tried to post a single user at a time it works well, but it is not possible to post multiple users at a time.
This is my User model:
class User < ActiveRecord::Base
attr_accessible :name,age,email,mobile,gender
end
And my User controller:
respond_to :html , :json
def create
#user = User.new(params[:user])
if #user.save
render :json => { :status => :ok, :message => "User Created Successfully"}.to_json
end
end
User posting data in JSON format for multiple users:
{
user:[
{
"name":"abc",
"age": 23,
"email": "abc#gmail.com",
"mobile": 9876543210,
"gender":"M"
},
{
"name":"def",
"age": 26,
"email": "def#gmail.com",
"mobile": 9876543210,
"gender":"F"
}
]
}
Is it possible to do this in Rails?
I tried:
def create
#userlist = User.new(params[:user])
#userlist.each do |u|
u.save
end
render :json => { :status => :ok, :message => "User Created Successfully"}.to_json
end
but the data is not saved.
Is there any solution?
Nested attributes saving under User:
{
"users" :[
{
"name":"abc",
"age": 23,
"email": "abc#gmail.com",
"mobile": 9876543210,
"gender":"M",
"projects":
[
{
"projectname":"abc",
"type":"abc"
},
{
"projectname":"def",
"type":"abc"
},
{
"projectname":"ghi",
"type":"abc"
}
]
},
{
"name":"def",
"age": 26,
"email": "def#gmail.com",
"mobile": 9876543210,
"gender":"F",
"projects":
[
{
"projectname":"abc",
"type":"abc"
},
{
"projectname":"def",
"type":"abc"
},
{
"projectname":"ghi",
"type":"abc"
}
]
}
]
}
As seen here, I'd suggest you bulk insert (depending on the likely amount of users that will be passed at a time), using this gem:
def create
users = []
#userlist = params[:users]
#userlist.each do |u|
user = User.new(u)
users << user
end
User.import(users)
render :json => { :status => :ok, :message => "User(s) Created Successfully"}
end
Ok, i see your edit of the posted params. so do it in your controller like this:
def create
#userlist = params[:users]
#userlist.each do |u|
user = User.new(u)
user.save!
end
render :json => { :status => :ok, :message => "User Created Successfully"}.to_json
end

Resources