Simplify logic to eliminate next
To improve readability by eliminating next
, rearrange your record validity test, so lines 4 to 9 become
if participant_account.present? || utility_program.present?
sub = Subscription.where(account_id: account.id, program_id: program.id)
else
# this is just a logger method defined in the second file.
failure_msg('participant account is #{account.inspect} & utility program is #{program.inspect}')
end
I am not sure this is what you mean. Ask yourself if you really need only one of participant_account
or utility_program
for the subscription query to succeed.
Don't do things many times that could be done once
To save some time, put line two before the iteration, because value of account
does not depend on data
. This also helps readability and debugging, as when programmers read the body of an iteration, they expect only to see lines that need to be evaluated many times.
Only make queries if you need the result
To save a little more time and memory, only calculate the value of program
if you know you are going to use it. So put it inside the conditional:
if participant_account.present? && utility_program.present?
program = Program.where(program_identifier: data[:id]).first
sub = Subscription.where(account_id: account.id, program_id: program.id)
else # ...
Extract methods
After these changes the conditional is starting to get a bit complicated, so extract some methods, for example:
if participant_account.present? && utility_program.present?
sub = subscription(account, first_program(data))
else # ...
def subscription(account, program)
Subscription.where(account_id: account.id, program_id: program.id)
end
def first_program(data)
Program.where(program_identifier: data[:id]).first
end
Put query logic in models
I don't know if Program is an ActiveRecord model. If it is, then #first_program
could be a class method in that model
Don't use #first unless you guarantee the order
For example, if you have ActiveRecord timestamps, you could use
Program.where(program_identifier: data[:id]).order(:created_at).first
Are validation and failure handling cross-cutting concerns?
You might also want to consider patterns that factor out your validation and failure handling code, but whether and how to use them depends on the larger structure of your program. For example, you could yield to your validations and sub = ...
line as lambdas from a validate_with_logging
method.