Params for json array in Rails - ruby-on-rails

I'm new to rails,
Please check my code and tell me whats wrong with my use params, because this is how it made sense to me.
Controller:
def create
user = User.find(user_params)
order = user.purchases.new
render json: order.errors if !order.save
basket = params.require(:basket)
basket.each do |b|
i = Item.find(b[:item_id])
render json: i.errors, status: 422 if !i
order.purchases_items.create(item_id: i, quantity: b[:quantity])
end
render nothing: true, status: 201 # location: show action
end
and my test file is sending
test "making order" do
post "/api/users/#{#tuser.id}/orders",
{ basket: [ { item_id: '2', quantity: '5' },
{ item_id: '1', quantity: '4'} ] }.to_json,
{ 'Accept' => Mime::JSON, 'Content-Type' => Mime::JSON.to_s }
assert_response 201
assert_equal Mime::JSON, response.content_type
end
Thanks,
What I basically want to do is store each array element in the array basket from params[:basket], and iterate over it.

Sometime params keys are not get converted into symbols automatically. Can u try passing string "basket" instead of symbol :basket?

Related

Render the full Json array in response.body

This test keeps failing Im not sure what to do. I am guessing a fix would be to render the raw Json array but I am utterly lost.
error
NoMethodError: undefined method []' for nil:NilClass
/Users/newuser/railschallenge-city-watch/test/api/emergencies_create_test.rb:10:inblock in '
emergencies controller
def create
#emergency = Emergency.new(emergency_params)
if #emergency.save
render json: #emergency.to_json , :status => 201
end
end
test 'POST /emergencies/ simple creation' do
post '/emergencies/', emergency: { code: 'E-99999999', fire_severity: 1, police_severity: 2, medical_severity: 3 }
json_response = JSON.parse(response.body)
assert_equal 201, response.status
assert_equal nil, body['message']
assert_equal 'E-99999999', json_response['emergency']['code']
assert_equal 1, json_response['emergency']['fire_severity']
assert_equal 2, json_response['emergency']['police_severity']
assert_equal 3, json_response['emergency']['medical_severity']
end
Try this:
render json: #emergency.to_json(:root => "emergency"), :status => 201
render json: {"emergency" => #emergency}.to_json , :status => 201

Dealing with array while using to_json

I have just started learning ruby on rails and I was using this code to get the json representation of the question model
post "api/quizzes/addquestion/#{#quiz.id}",
{ question:
{ text: "Question Text Example", mark: 2, choices:["a","b","c","d"], right_answer: "a" }
}.to_json
I got :
choices: [] , empty array
I don't know the reason for this as all other attributes are sent succesfully. What is the solution for such problem
I am using this while testing the following method:
def add_question
question = Question.new(question_params)
quiz = Quiz.find(params[:quiz_id])
if question.save
quiz.questions << question
render json: { success: true, data:{:question => question}, info:{} }, status: 201
else
render json: { success: false, data:{}, :info => question.errors }, status: 422
end
end
def question_params
params.require(:question).permit(:text, :mark, :choice, :right_answer)
end
the test :
class AddingQuestionsTest < ActionDispatch::IntegrationTest
setup {#quiz = Quiz.create(name: 'Quiz1', subject: 'physics', duration: 10, no_of_MCQ: 5, no_of_rearrangeQ: 5)}
setup {#question = Question.create(text: "Question Text Example", mark: 2, choices:["a","b","c","d"], right_answer: "a")}
test 'successes to add question to a quiz' do
post "api/quizzes/addquestion/#{#quiz.id}",
{ question:
{ text: "Question Text Example", mark: 2, choices:["a","b","c","d"], right_answer: "a" }
}.to_json,
{ 'Accept' => Mime::JSON, 'Content-Type' => Mime::JSON.to_s }
question_response = json(response.body)
assert_equal 201, response.status
assert_equal #quiz.questions.first, #question
assert_equal publish_response[:success], true
end
end
and this is the question model:
class Question < ActiveRecord::Base
serialize :choices,Array
belongs_to :quiz
end
When I run the test I get failure in:assert_equal #quiz.questions.first, #question
choices: []
choices: ["a", "b", "c", "d"]
Just we need to change
def question_params
params.require(:question).permit(:text, :mark, :choice, :right_answer)
end
to
def question_params
params.require(:question).permit(:text, :mark, :right_answer, :choice => [])
end

Rails render json object with camelCase

I have the following controller code in a simple Rails API:
class Api::V1::AccountsController < ApplicationController
def index
render json: Account.all
end
def show
begin
render json: Account.includes(:cash_flows).find(params[:id]), include: :cash_flows
rescue ActiveRecord::RecordNotFound => e
head :not_found
end
end
end
The problem with this is that, the generated json have the format:
{
id:2,
name: 'Simple account',
cash_flows: [
{
id: 1,
amount: 34.3,
description: 'simple description'
},
{
id: 2,
amount: 1.12,
description: 'other description'
}
]
}
I need that my generated json is camelCase('cashFlows' instead of 'cash_flows')
Thanks in advance!!!
Following the recommended by #TomHert, I used JBuilder and the available config:
Keys can be auto formatted using key_format!, this can be used to convert keynames from the standard ruby_format to camelCase:
json.key_format! camelize: :lower
json.first_name 'David'
# => { "firstName": "David" }
You can set this globally with the class method key_format (from inside your environment.rb for example):
Jbuilder.key_format camelize: :lower
Thanks!!!

Can't pass spec test because of created_at

I'm testing 'get' method and getting error:
expected:
[{\"user_id\":11,\"user_first_name\":\"bob\",\"user_last_name\":\"marley\",\"user_picture\":\"/images/missing.png\",\"id\":2,\"text\":\"my
third review\",\"date\":\"2013-12-27T09:08:06.364Z\"}]
got:
[{\"user_id\":11,\"user_first_name\":\"bob\",\"user_last_name\":\"marley\",\"user_picture\":\"/images/missing.png\",\"id\":2,\"text\":\"my
third review\",\"date\":\"2013-12-27T09:08:06.000Z\"}]
what the hell? Why last numbers are different while all other fields are equal?
it "should return reviews for user" do
review = Review.create(reviewer_id: #user.id, user_id: #user2.id, text: 'my third review')
get 'get_reviews_for_user', user_id: #user2.id
expect(response).to be_success
json = JSON.parse(response.body)
expect(json['reviews'].to_json).to eq([{user_id: #user.id,
user_first_name: #user.first_name,
user_last_name: #user.last_name,
user_picture: #user.picture.url(:thumb),
id: review.id,
text: review.text,
date: review.created_at
}].to_json)
end
In controller:
def get_reviews_for_user
user = User.where(id: params[:user_id]).first
return render json: {success: false} if user.nil?
reviews = []
Review.where(user_id: user.id).each do |review|
reviewer = review.reviewer
reviews << {user_id: reviewer.id,
user_first_name: reviewer.first_name,
user_last_name: reviewer.last_name,
user_picture: reviewer.picture.url(:thumb),
id: review.id,
text: review.text,
date: review.created_at}
end
render json: { success: true, reviews: reviews }
end
The times are different because the milliseconds are truncated when the time is translated into JSON.
You can use Timecop to freeze the time to a give value like this : Timecop.freeze(Time.now).
You can also use a stub like this (in you test) :
allow(Review).to receive(:where).with(user_id: #user.id).and_return([review])
allow(review).to receive(:created_at).and_return(Time.now)

Problem building JSON file

want to get all db entries by a specific hash and return it as json. I use the following code:
#tasks = Task.find_all_by_hash(params[:hash])
respond_to do |format|
format.json { render :json => #tasks }
end
now i have the problem that my json file isn't correct. it has the following output:
[
{
task: {
hash: "9dfca619f00f5488785f6b74ad1b590beefaee7a88c04884bf197e7679f3"
id: 4
created_at: "2010-12-16T09:09:51Z"
updated_at: "2010-12-16T09:14:10Z"
done: true
name: "Hallo"
}
},
{
task: {
hash: "9dfca619f00f5488785f6b74ad1b590beefaee7a88c04884bf197e7679f3"
id: 5
created_at: "2010-12-16T09:12:37Z"
updated_at: "2010-12-16T09:12:37Z"
done: true
name: "Test"
}
},
...
]
but actually i want it like this:
{ tasks: [
{"id":"1","date_added":"0001-02-22 00:00:00","post_content":"Check out my content, this is loaded via ajax and parsed with JSON","author":"Ryan Coughlin"},
{"id":"2","date_added":"0000-00-00 00:00:00","post_content":"More content, loaded. Lets try to add a form in and post via ajax and append the new data","author":"Billy Bob"}
]}
any advice? thank you!
Try collecting the task alone to an array and create a json object using that. Some thing like
#tasks = Task.find_all_by_hash(params[:hash])
a = []
#tasks.each do |t|
a << t[:task]
end
b = {:tasks => a}
respond_to do |format|
format.json { render :json => b }
end

Resources