.where returns nil exception if user does not enter anything rails 4 - ruby-on-rails

I want to query some data from table based on user for submission.
Its working fine but if I post nothing in the the fields and post my form, it returns me nil exception.
Is there a way we can deal with nil exception, or do I need to change query?
question_options = question.question_options.where(id: self.option_id).first

The simplest solution is to use try. For example:
question_options = question.question_options.where(id: self.option_id).try(:first)
The documentation for try is here

For your issue multiple solutions exists. Your query returns nil and thats ok because nothing was found. The simplest solution is an if statement. if question_options.nil? do some thing else. Or you can use an unitialized object (or a NullObject) do work with it question_option = question.question_options.where(id: self.option_id).first || QuestionOption.new
The are other possibilites too. It depends on your requirement what way you choose.

Related

conditional match on rails rspec

I want to write a test on helper method which fetches data from external service based on an id. So there is an uncertainty whether the value will be returned or nil. But if value is returned, id of returned value must be equal to given id. Is there a way to achieve this?
expect(record).to be_nil.or expect(record.id).to eq(deal.user_id)
however it seems the or condition does not work the way I think. I am new to RoR. Might be missing any obvious way to do it.
You can write ruby code in specs too:
if record != nil
expect(record.id).to eq(deal.user_id)
end
or combine matchers:
expect(record).to be_nil.or(eq(deal.user_id))

Better way than if foo.blank?

I am building a basic app that will retrieve a customers data and show it on screen, however some of the fields will be null and so I get a lot of undefined method 'registration_number' for nil:NilClass errors
Is there a better way to to deal with these other than lots of if statements
if #customer.registration_number.blank?
Do something
else
#customer.registration_number
end
Thanks in advance
If you want to actually do something on missing values, you can't avoid a conditional per value. (Especially if that "something" differs from value to value).
If you want to simply ignore missing values, you can use one of the nil-swallowing tricks.
#customer.try(:registration_number)
#customer&.registration_number
#customer.registration_number rescue nil # don't use this one, there are better ways
You can do a try there
#customer.try(:registration_number)
and if there is no value, it will just return nil

What is the difference between find and find_by?

I know from the rails documentation that find will result in a RecordNotFound error. However, the find_by method simply returns nil if a record is not found. Returning nil seems more intuitive to me and safe in general, so I am wondering if there is any benefit in using the find method over the find_by method?
For example, what is the difference between the following:
myRecord.find(1)
and
myRecord.find_by(id: 1)
If the only difference is that find raises an error when a record isn't found, I don't really see the benefit in using find.
EDIT
For all the people that jumped on my question and said that it had been already answered, you are wrong. I clearly stated that I knew find returns an error when a record is not found (which is what everyone else emphasizes in their answers) and that find_by returns nil. I want to know if there are any other differences.
In your specific example there is little difference between the two of them other than the error vs nil which you mention. Whether you want to handle an error or nil is totally up to you.
For a great explanation of understanding when an error is preferable to nil and vice versa read this.
If you are searching by an attribute other than id using find will not work as it can only access elements by their id.

How do I check if it returns a null?

i should check whether there is some values based on this condition. if there is some, then i should do one action or else do a different action.
i work on rails, mysql and xp
this is not working #test.nil? suggest me a alternate way
#test=Model.find(:all,:conditions=>"id=#someid")thanks in advance
#test.nil? should work fine. It's probably not working because your find method is wrong. Try this instead:
#test = Model.find_by_id(#someid)
An alternative syntax is:
#test = Mode.find(#someid)
—Which will raise a RecordNotFound exception if the record doesn't exist.

Saving updates to objects in rails

I'm trying to update one of my objects in my rails app and the changes just don't stick. There are no errors, and stepping through with the debugger just reveals that it thinks everything is updating.
Anyway, here is the code in question...
qm = QuestionMembership.find(:first, :conditions => ["question_id = ? AND form_id = ?", q_id, form_id])
qm.position = x
qm.save
For reference sake, QuestionMembership has question_id, form_id, and position fields. All are integers, and have no db constraints.
That is basically my join table between Forms and Questions.
Stepping through the code, qm gets a valid object, the position of the object does get changed to the value of x, and save returns 'true'.
However, after the method exits, the object in the db is unchanged.
What am I missing?
You may not be finding the object that you think you are. Some experimenting in irb might be enlightening.
Also, as a general rule when changing only one attribute, it's better to write
qm.update_attribute(:position, x)
instead of setting and saving. Rails will then update only that column instead of the entire row. And you also get the benefit of the data being scrubbed.
Is there an after_save?
Is the correct SQL being emitted?
In development log, you can actually see the sql that is generated.
For something like this:
qm = QuestionMembership.find(:first, :conditions => ["question_id = ? AND form_id = ?", q_id, form_id])
qm.position = x
qm.save
You should see something to the effect of:
SELECT * FROM question_memberships WHERE question_id=2 AND form_id=6 LIMIT 1
UPDATE question_memberships SET position = x WHERE id = 5
Can you output what sql you are actually seeing so we can compare?
Either update the attribute or call:
qm.reload
after the qm.save
What is the result of qm.save? True or false? And what about qm.errors, does that provide anything that makes sense to you? And what does the development.log say?
I have run into this problem rather frequently. (I was about to say consistently, but I cannot, as that would imply that I would know when it was about to happen.)
While I have no solution to the underlying issue, I have found that it seems to happen to me only when I am trying to update mysql text fields. My workaround has been to set the field to do something like:
qm.position = ""
qm.save
qm.position = x
qm.save
And to answer everyone else... when I run qm.save! I get no errors. I have not tried qm.save?
When I run through my code in the rails console everything works perfectly as evidenced by re-finding the object using the same query brings the expected results.
I have the same issue when using qm.update_attribute(... as well
My workaround has gotten me limping this far, but hopefully someone on this thread will be able to help.
Try changing qm.save to qm.save! and see if you get an exception message.
Edit: What happens when you watch the log on the call to .save!? Does it generate the expected SQL?
Use ./script/console and run this script.. step by step..
see if the position field for the object is update or not when you run line 2
then hit qm.save or qm.save!... to test
see what happens. Also as mentioned by Tim .. check the logs
Check your QuestionMembership class and verify that position does not have something like
attr_readonly :position
Best way to debug this is to do
tail -f log/development.log
And then open another console and do the code executing the save statement. Verify that the actual SQL Update statement is executed.
Check to make sure your database settings are correct. If you're working with multiple databases (or haven't changed the default sqlite3 database to MySQL) you may be working with the wrong database.
Run the commands in ./script/console to see if you see the same behavior.
Verify that a similar object (say a Form or Question) saves.
If the Form or Question saves, find the difference between the QuestionMembership and Form or Question object.
Turns out that it was emitting the wrong SQL. Basically it was looking for the QuestionMembeship object by the id column which doesn't exist.
I was under the impression that that column was unnecessary with has_many_through relationships, although it seems I was misguided.
To fix, I simply added the id column to the table as a primary key. Thanks for all the pointers.

Resources