Rails Parse Active record validation error - ruby-on-rails

I have the following in my controller:
def create
equipment = Equipment.create(:name => params[:name])
errors = equipment.errors.messages
puts "equipment errors: " + errors.inspect
respond_to do |format|
format.json { render :json => #equipment }
end
end
The response from the 'puts' is:
equipment errors: {:name=>["has already been taken"]}
How do I parse the error and get the message?
Thanks

equipment.errors.full_messages.join(", ")
This should give you "Name has already been taken". It concatenates all the errors.

Its just a hash. Access the message with
errors[:name].first
This gets the value of the :name key from the hash, which is an array with one element, and then returns the value of the first element of the array, which is the error message.
With more errors, use Array functions to access all of them and display them appropriately.

Related

rails 5 ForbiddenAttributesError on bulk operations

i try to bulk operation in my rails controller this is my script
def update_by_user
user_skill_selected = UserSkillSelected.create(params[:user_skill_selected][:users])
# check through array if all is valid
if user_skill_selected.all? {|item| item.valid?}
render json: {json_status: save_success}
else
render json: {json_status: save_failed}
end
end
and this is my user_skill_selected_params
def user_skill_selected_params
params.require(:user_skill_selected).permit(:user_id, :subskill_id, :skill_id, :users => [])
end
unfortunately i get an error in my log, the log said
"exception": "#<ActiveModel::ForbiddenAttributesError:ActiveModel::ForbiddenAttributesError>",
after that i try to bulk operations from rails console with using create method with the array value and its work
can anyone solve this... :(
sorry for the bad english
This can be confusing. Your code is passing in params[:user_skill_selected][:users] to the model create method, instead of your user_skill_selected_params strong parameters, which is why you're seeing that error.
Change this line:
user_skill_selected = UserSkillSelected.create(params[:user_skill_selected][:users])
To this:
user_skill_selected = UserSkillSelected.create(user_skill_selected_params)
And it should eliminate this error.

Rails JSON API tests don't return json when exception is thrown

I'm writing a test to check for invalid DELETE requests to a Rails API using Rspec.
This is what I have:
context 'invalid id number' do
it 'returns success: false' do
xhr :delete, :destroy, id: 999999999999999999
expect(JSON.parse(response.body)['success']).to be_false
end
end
Postgres throws some kind of integer overflow exception (as it should), but in my spec I can't look at the JSON object because it's never formed. How can I make it return { success : false } instead of a blank string? How do I force the JSON object to return despite the exception?
When I use pry to look at the json object, I get this error: JSON::ParserError: A JSON text must at least contain two octets! because response.body evaluates to the empty string ""
Whoa, almost forgot to include the controller code.
def destroy
if (site == ::MyModel.find(params[:id]))
site.destroy
render :json => {success: true}
else
render :json => {success: false}
end
There are two issues here:
Depending on your database an id of "999999999999999999" is probably outside of an integer type. I recommend reducing it to below signed integer limit, like 9999.
You are trying to find a non-existent record and its raising a record_not_found exception. I recommend changing your destroy method to:
def destroy
site = ::MyModel.find_by(id:params[:id])
if (site.present?)
render :json => {success: false}
else
site.first.destroy
render :json => {success: true}
end
end
EDIT
#rafb3 is correct find_by and present? is a better choice.
By the sounds of it you will need some kind of rescue statement for the exception:
rescue ArithmeticException => ex
# We need to complete the contract and return json here
#response = { success: false }
end
If you want to learn more about contracts check out this link
Remember to stay away from returning objects in failure responses, as if you send back something like site in this case and site does not exist or the database connection is not there your exception response code may have its own exception!
Also try and stay away from rescue Exception => e explanation here: Why is it a bad style to `rescue Exception => e` in Ruby?
TLDR: Your request always expects a json response so in all places even failure it should return one.

How to create temporary attribute & use that in json reponse in rails active record

I am new to ROR.
I am having a controller where i am getting the search results in available_users variable..
availble_users //some active record result with id,name & address
available_users.each do |userstatus|
userstatus.class_eval do
attr_accessor :is_friend
end
if current_user.invitations.find_by(:friend_id => userstatus.id) //invitation is another table
userstatus.is_friend = "true"
else
userstatus.is_friend = "false"
end
end
render json: available_users
but when i am getting the response on ajax request it is serving the same array without including is_friend column.
here is my json response.
id: 2
name: abc
address:
please can anyone figure me out why it is not appending this temporary attribute.
Thanks.
what you have will work if you pass the methods option to_json
render json: available_users.to_json(:methods => :is_friend)
Or you could do this
available_users.each do |userstatus|
if current_user.invitations.find_by(:friend_id => userstatus.id) //invitation is another table
userstatus["is_friend"] = "true"
else
userstatus["is_friend"] = "false"
end
end
render json: available_users
[]= is an alias for write_attribute

Rails: validation error codes in JSON

So, I am writing Rails web application which has JSON API for mobile apps. For example, it sends POST JSON request to example.com/api/orders to create order.
{id: 1, order: { product_name: "Pizza", price: 10000}}
In case of validation errors I can response with HTTP 422 error code and order.errors.full_messages in json. But it seems better for me to have specific error code in JSON response. Unfortunately, it seems like Rails does not provide ability to set error code for validation error. How to solve this problem?
You can pass a custom status code by using the status option when rendering the response.
def create
#order = ...
if #order.save
render json: #order
else
render json: { message: "Validation failed", errors: #order.errors }, status: 400
end
end
I usually tend to return HTTP 400 on validation errors. The message is a readable status response, the errors are also attached.
This is a respons example
{
message: "Validation failed",
errors: [
...
]
}
You can also embed additional attributes.
I was after something similar, so what I did was extend String eg
class ErrorCodeString < String
def init(value, error_code)
#error_code = error_code
super(value)
end
def error_code
#error_code
end
end
Then in a custom validation (this won't work on standard validation) I'd do
errors.add(:email, ErrorCodeString.new('cannot be blank', 50)
Now when you return your JSON you can check to see if the error value is an ErrorCodeString and add the error_code value to the output. As ErrorString inherits String, you shouldn't be breaking anything else along the way.
Rails 5 has error.details that can be used for exactly that.
In the model
errors.add(:price, 1023, message: "Transaction value #{price} is above limit (#{maximum_price}).")
In the controller
format.json { render json: #order.errors.details, status: :unprocessable_entity }
error details can be anything, eg. you could also use :above_limit instead of 1023.
The API response body will then look like
pp JSON.parse(response)
{"price"=>[{"error"=>1023}]}
This feature has been backported to Rails 4, see also http://blog.bigbinary.com/2016/05/03/rails-5-adds-a-way-to-get-information-about-types-of-failed-validations.html
Also: Is there a way to return error code in addition to error message in rails active record validation?

Not adding data to associated table

With the code below and entry is created in the venuetypes table with the correct *venue_id* and time stamps however, the type column remains as null
def new
#new1 = "gfdsgfd"
#venue = Venue.new
#venue.save
#venuetype = #venue.venuetypes.create(:type => "test")
#venuetype.save
respond_to do |format|
format.html # new.html.erb
format.json { render json: #venue }
end
end
Unless you've specified otherwise, rails expects a type column to be used for single table inheritance which is probably causing problems.
Also, venuetypes.create will only save the venue type if it is created successfully, as will the .save call afterwards. You have almost certainly got an error on the venue type which is causing it not to be saved. Try using .save! which will throw an error or by lookins at #venuetype.errors which will contain any error messages that have caused it not to be saved.

Resources