Better way than if foo.blank? - ruby-on-rails

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

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))

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

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.

Checking for nil strings in Rails view

I'm looking for a good shortcut for Nil checking in my Rails views. I've seen other questions on SO about this, but none seem to simplify this as much as I'd like. What I'd like is a short syntax to return an empty string "" if a particular value is nil, otherwise return the value.
There is a suggestion here which I am inclined to try out. It basically allows a statement like this:
user.photo._?.url
-- or --
user.photo.url._?
Is this a good idea or is it fraught with peril?
My other option would be to handle nils on my models, but that seems too global.
You should check try method which runs a provided method on the object and returns the value if the object in question is not nil. Otherwise it'll just return nil.
Example
# We have a user model with name field
u = User.first
# case 1 : u is not nil
u.try(:name)
=> Foo Bar
# case 2 : u is nil
u.try(:name)
=> nil
# in your case
user.photo.try(:url)
For details have a look at this blog post.
The idiomatic Ruby way to accomplish this is the || operator, which will return the value of the right-hand expression if the left-hand expression is nil (or false):
puts(user.photo.url || '')
Any moderately experienced Ruby programmer will understand exactly what that does. If you write a custom _? method, I now have to go look up the purpose of that method and remember what it does and hope that it always does the right thing. I generally find that sticking to idiomatic code is far more beneficial than saving a few keystrokes here and there.
try this:
user && user.photo && user.photo.url.present?
This will not blow up if user is nil or user.photo is nil
What about just using nil?
someObject.nil? # true if someOBj is nil
Or am I misunderstanding what you want?
I suspect your options are problematic, because if photo is nil, both of your statements should return 'Undefined method'.
You shouldn't even need to check for '.nil?'. Since you implied your checking is in the view, and not in the controller, I imagine you are checking an #instance variable, which will always be nil if undefined. So just do:
if #someObject
...
else
...
If you are putting the conditional in your controller, then again, just use an #instance variable and you'll always have at least nil, if undefined.

Rails: How to simplify ".select(:my_field).map(&:my_field)"?

To get the invoice numbers of selected jobs I do:
Job.where(...).map(&:invoice_number)
Since the invoice numbers is all I need, I thought to add select(:invoice_number) (I assume the SQL query becomes more efficient this way):
Job.where(...).select(:invoice_number).map(&:invoice_number)
Is there a better way to do the same ? (the .select(:invoice_number).map(&:invoice_number) part seems inefficient to me)
You could always use select_values. Something akin to:
Job.connection.select_values(Job.where(...).select(:invoice_number).to_sql)
This avoids the instantiation of ActiveRecord objects.
I know that this question is rather old, but in case anybody else checks this out, this can be achieved with pluck (http://apidock.com/rails/ActiveRecord/Calculations/pluck). As per http://edgeguides.rubyonrails.org/active_record_querying.html#pluck "pluck makes it possible to replace code like: Client.select(:id).map(&:id) with Client.pluck(:id)"
Would love to be proven wrong, but.. I don't think it's possible
Since all the active record methods are chainable, a method that returned an array of strings would break this. If such a method existed then it wouldn't be in AR, I can't think of where else to look..
You can use GROUP_CONCAT.
invoice_numbers = Job.where(...).select('group_concat(invoice_number) as invoice_numbers').
first.invoice_numbers.split(',').map(&:to_i)
This approach is too long and is not very obvious, but it will run faster than
Job.where(...).select(:invoice_number).map(&:invoice_number)

How to DRY up a ruby conditional structure needed for Rails

I'm finding I often have to use a structure to avoid a Rails error of undefined method 'name' for nil:NilClass.
The structure looks like this:
if country.state
country.state.name
end
It seems like a classic case of repeating oneself with country.state appearing twice in one simple block. Is there any way to DRY this up?
Rails adds a try method to object that mimics object#send but does not raise an exception if the object returns nil.
I think the syntax is
country.try(:state).name
Well not really. One option is to install the andand gem, but introducing a dependency for this may be a little much.
Other than using the slightly more concise syntax of:
country.state.name unless country.state.nil?
I don't think there's a DRY way to do this with the information given. I would argue that if you can't be sure whether country.state is nil or not, you may want to look at the code responsible for setting that value and determine whether that's a normal case or whether a validator upstream should be catching that.

Resources