I'm trying to send error messages(like following things in console when i did a wrong sql) back to frontend in json.
Traceback (most recent call last):
NameError (undefined local variable or method `posts' for main:Object)
So i wrote this in controller:
begin
#results = Post.find_by_sql(params[:sql])
if #results.first.nil?
render json: { fail: "No such tuple"}
else
render json: { html: render_to_string(:template => 'all/findit') }
end
rescue
render json: { fails: #results.errors}
But from the console in browser, it still only gives a 500 error and the ajax shows "fail".
How to fix this bug? Thanks!!
Post::find_by_sql returns an array so you wouldn't be able to call #errors on it.
"The results will be returned as an array, with the requested columns encapsulated as attributes of the model you call this method from."
Source: https://api.rubyonrails.org/classes/ActiveRecord/Querying.html#method-i-find_by_sql
Related
I have the following REST API call in my code which if wrong returns this error
def get_token
responseObject = {
message: "Error",
errors: ["User does not exist"]
}
render status: 403, json: responseObject
end
Problem is in my response.json(), i get this instead
So when i try to do this in my code response.json().errors, i always get undefined because somehow it doesnt see my response in my body as json.
Actually not sure how to solve this mess.
Thanks
when i try to create it says undefined method.
def create
#stock = Stock.find(params[:stock_availabilities][:stock_id])
#stock_availability = StockAvailability.new(stock_availabilities_params)
respond_to do |format|
if #stock_availability.save
format.html { redirect_to stock_path(v_id: #volunteer.id), notice: "stock saved successfully" }
else
#stock_availabilities = StockAvailability.where(stock_id: #stock.id).all
format.html { render 'index' }
end
end
end
Where stock_availabilities belongs to Stock table. foreign key is stock_id.
The params Generated in log is
Parameters: {
"utf8"=>"✓",
"authenticity_token"=>"ZWxRnGJqwLmhfosIhQ+xdLrG3HJXy1m/dHcizT+Y5+E=",
"stockavailability"=>{
"qty"=>"20",
"price"=>"2000",
"captured_at"=>"26/8/2015"
},
"commit"=>"Save Stockavailability"
}
Completed 404 Not Found in 1ms
I kind of regenerated your issue
2.1.1 :003 > a=nil
=> nil
2.1.1 :004 > a['asd']
NoMethodError: undefined method `[]' for nil:NilClass
from (irb):4
from /home/illu/.rvm/rubies/ruby-2.1.1/bin/irb:11:in `<main>'
2.1.1 :005 >
In your case it probably
params[:stock_availabilities] is giving nil and you are trying to access the key :stock_id in the nil class.
I suggest you to pry the values at the point.
EDIT1:
After having a look at your server log it is clear that the key stock_availabilities you are trying to access is actually stockavailability
your code should be like
# though no :stock_id key/value is found in your server log
#stock = Stock.find(params[:stockavailability][:stock_id])
try change :
#stock = Stock.find(params[:stock_availabilities][:stock_id])
to
#stock = Stock.find(params[:stockavailability][:stock_id])
Your this problem will get solved but you will get other error too. Because you are not passing stock_id properly in params. So try set that as well in form hidden field.
To run your code without error. You should have stock_id in your this param section "stockavailability"=>{"qty"=>"20", "price"=>"2000", "captured_at"=>"26/8/2015"},
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?
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.
I'm using Rails 3 with mongoid 2 and have a simple question regarding mongoid validation.
if #forum.topics.create!(name: params[:topic][:name])
# success, do something
else
#should handle errors but doesn't
render 'new'
end
If I use the .create! method, it runs validations on a mongoid model class correctly, but it is not getting to the else block to display the error. Instead it returns a rails error page saying...
Mongoid::Errors::Validations in TopicsController#create
Validation failed - Name can't be blank.
That's good, but how do I display that in a view instead of getting an ugly rails error message page?
Try this way:
new_topic = #forum.topics.new(name: params[:topic][:name])
if new_topic.save
# success, do something
else
render 'new', errors: new_topic.errors.full_messages
end
with this way you will have the local variable errors which is a Hash formated like following:
new_topic.errors.full_messages # => ["\"Name\" can't be blank"]
you can rescue the Mongoid::Errors::Validations and use it's instance method to get the errors
new_topic = #forum.topics.new(name: params[:topic][:name])
new_topic.create!
rescue Mongoid::Errors::Validations => e
summary = e.summary
problem = e.problem
res = e.resolution
using the above error messages you can display the error
Documentaion link
https://docs.mongodb.com/mongoid/6.2/api/Mongoid/Errors/Validations.html