Simplify if else condition ruby - ruby-on-rails

I have a if else condition in my ruby code listed below:
if !category.nil?
return false unless company_matches.any? { |w|
comparison = /(\s|^)#{w}(\s|$)/i
(title.index(comparison) || description.index(comparison) || clean_title.index(comparison) || clean_desc.index(comparison)) && (category == 'Business')}
else
return false unless company_matches.any? { |w|
comparison = /(\s|^)#{w}(\s|$)/i
(title.index(comparison) || description.index(comparison) || clean_title.index(comparison) || clean_desc.index(comparison))}
end
How can i simplify this to make it look more subtle?

company_matches.any? do |company|
[title, description, clean_title, clean_desc].any? do |attribute|
attribute.match? /(\s|^)#{company}(\s|$)/i
end && (category == 'Business' || category.nil?)
end

You can create a method to do your comparisons so you don't repeat yourself. You can also abstract the comparison variable out of the if .. else block. Here's what I have:
comparison = /(\s|^)#{w}(\s|$)/i
result = perform_comparison(title, description, clean_title, clean_desc, comparison)
unless category.nil?
return false unless company_matches.any? { |w| result && (category == 'Business')}
else
return false unless company_matches.any? { |w| result }
end
# somewhere else in your code
def perform_comparison(title, description, clean_title, clean_desc, comparison)
title.index(comparison) || description.index(comparison) || clean_title.index(comparison) || clean_desc.index(comparison)
end

Related

Simplifying method

I have this method which works fine but I'm thinking that it may be improved, either for readability and/or efficience.
def default_something
something =
Legal::Something.find_for_A_in_placea('xx', claim.blabla.identifier) ||
Legal::Something.find_for_B_in_placeb('xx', claim.eligible.first.bleble.indivcode) ||
Legal::Something.find_for_B_in_placeb('xx', claim.eligible.last.blublu.indivcode) ||
Legal::Something.find_by(id: DEFAULT_SOMETHING_ID)
{
'name' => something.name,
'day' => something.meta_data[:day],
'hour' => something.meta_data[:hour],
}
end
I can "beautify it" by creating some more methods like:
def default_something
something = def A || def B || (etc)
end
def A
Legal::Something.find_for_A_in_placea('xx', claim.blabla.identifier)
end
def B
Legal::Something.find_for_B_in_placeb('xx', claim.eligible.first.bleble.indivcode) ||
Legal::Something.find_for_B_in_placeb('xx', claim.eligible.last.blublu.indivcode)
end
In addition I should say:
find_for_B part only retrieves a value when claim.eligible.first.bleble.indivcode || claim.eligible.last.blublu.indivcode = 'ASL'
Is the "beautified" version the way to go?
And/or should I add an if statement regarding
Legal::Something.find_for_B_in_placeb('xx', claim.eligible.first.bleble.indivcode) ||
Legal::Something.find_for_B_in_placeb('xx', claim.eligible.last.blublu.indivcode)
to improve efficiency and readability, stating it happens only when "indivcode" = "ASL"?
What else can I do?

ruby scripts - (NameError) undefined local variable or method `null' for main:Object

My code
require "json"
require "erb"
flowvar = $workflowvar
path = 'src/main/resources/'+$workflowvar+'.drl'
rule = ""
File.open(path,"w") do |f|
f.puts "package com.drools.demo\;"+"\n"+"import org.mule.MessageExchangePattern\;"+"\n"+"import com.drools.demo.cashliquidassets\;"+"\n"+"global org.mule.module.bpm.MessageService mule\;"+"\n"+
"dialect \"mvel\""+"\n"+"dialect \"java\""+"\n"+"declare cashliquidassets"+"\n"+"#role\(\'event\'\)"+"\n"+"end"+"\n"
f.close
end
def concateRule(attribute,val)
if(val==null || val=="")
return "";
end
if(attribute != null)
if (attribute == "taxonomy_code" || attribute == "parent_taxonomy_code" || attribute == "report_name")
return "";
end
end
if val.start_with('<>')
return attribute+" != "+val[3,val.length].strip
elsif val.start_with('>')
return attribute+" > "+val
elsif val.start_with('<')
return attribute+" < "+val
elsif val.include? ","
return attribute+".contains("+val+"\)"
else
return attribute+" == "+ val
end
end
json = JSON.parse($payload)
json.each do |hash1|
hash1.keys.each do |key|
hash1[key].each do |inner_hash,value|
#inner_hash = inner_hash
#values = value
str = concateRule #inner_hash,$values
end
end
end
Compile is working fine, but in runtime, I am getting this following error. Any suggestions
Root Exception stack trace:
org.jruby.exceptions.RaiseException: (NameError) undefined local
variable or method `null' for main:Object
at RUBY.concateRule(<script>:15)
at RUBY.block in (root)(<script>:43)
at org.jruby.RubyHash.each(org/jruby/RubyHash.java:1350)
at RUBY.block in (root)(<script>:40)
at org.jruby.RubyArray.each(org/jruby/RubyArray.java:1735)
at RUBY.block in (root)(<script>:39)
at org.jruby.RubyArray.each(org/jruby/RubyArray.java:1735)
at RUBY.<main>(<script>:38)
You need to use nil instead of null.
So, just replace it.
Following the conversation in the comments above, here is how I would write the method:
def concat_rule(attribute, val)
val = val.to_s
if val == '' || ['taxonomy_code', 'parent_taxonomy_code', 'report_name'].include?(attribute)
return ''
end
if val.start_with?('<>')
"#{attribute} != #{val[3..-1].strip}"
elsif val.start_with?('>')
"#{attribute} > #{val}"
elsif val.start_with?('<')
"#{attribute} < #{val}"
elsif val.include?(',')
"#{attribute}.contains(#{val})"
else
"#{attribute} == #{val}"
end
end
A few notes:
Using snake_case method names and 2 space tabs, is a very strongly adhered to style guide in the ruby community.
Similarly, you can make use of ruby's implicit return, to shorten the code: The final value at the end of a method is returned automatically.
Adding val = val.to_s to the top of this method simplifies the rest of the code; eliminating the need to repeatedly convert to a string or perform nil checks.
You can use ruby's string interpolation ("#{code-to-evaluate}") syntax as a more elegant way to define strings than repeated use of + for concatenation.

setting a variable before an if statement ruby

I am working using rails and I have a class from activerecord called Car. In the application that I am building,The application let's the user add a new car in one the pages or if not they can choose the one that it's already there.
I am having difficulties trying to come up with a solution, although both of them work it would only execute until some part of code because it's in an if/else statement.
ad_group_controllers.rb
if params[:ad_group][:file]
#car = Car.create(year: params[:ad_group][:car][:year],model: params[:model],make_id: params[:make], trim: params[:trim])
#car.update(file: params[:ad_group][:file])
#ad_group.car = #car
else
#car = Car.find(params[:ad_group][:car][:id])
#trim = params[:trim] == 'none' ? nil : params[:trim]
#promotional_logo = params[:promotional_logo].blank? || params[:promotional_logo].downcase == 'none' || params[:promotional_logo] == '0' ? nil : PromotionalLogo.find(params[:promotional_logo])
if (#promotional_logo && #ad_group.promotional_logo.nil?) || (#promotional_logo.nil? && #ad_group.promotional_logo)
#ad_group.promotional_logo = #promotional_logo
#ad_group.adjust_for_promotional_logo
end
#ad_group.update_attributes(make: #make, car: #car, trim: #trim, client: #client, rollover: params[:ad_group][:rollover], promotional_logo: #promotional_logo || nil)
AdGroup.fields.each do |field|
#ad_group[field] = params[:ad_group][field]
end
end
#ad_group.ads.each do |ad|
url = #ad_group.car.file.blank? ? nil : #ad_group.car.file.url
car = #ad_group.car.file.blank? ? nil : #ad_group.car
ad.images.find_by(name: 'car').update(url: url, car: car)
url = #ad_group.promotional_logo.blank? ? nil : #ad_group.promotional_logo.file.url
logo = #ad_group.promotional_logo.blank? ? nil : #ad_group.promotional_logo
ad.images.find_by(name: "promotional_logo").update(url: url, promotional_logo: logo)
ad.texts.find_by(name: "client_name").update(content: #client.name)
if #ad_group.car.blank?
car_name = ''
else
car_name = "#{#car.year} #{#make.name} #{#car.model}"
car_name += " #{#car.trim}" unless params[:trim] == 'none' || params[:trim].blank?
end
ad.texts.find_by(name: "car_name").update(content: car_name)
Basically the if statement it's stating that if's there is a file in the adgroup paramaters create a car, and if not it should stay as
#car = Car.find(params[:ad_group][:car][:id])
the code below that has to execute for both cases. what is the best way to do this without repeating the code in the if and the else.

Rails break and return not working

I'm working with koala. I have to check the permission given is granted by user for the application. I have made a helper called facebook helper. There is a def has_permission?(perm). My code follows:
def has_permission? (perm)
#graph = Koala::Facebook::API.new(current_user.token)
#permissions = #graph.get_connections('me', 'permissions')
#bool = false
#permissions.each do |p|
if p[0] == perm && p[1] == 'granted'
#bool = true
break
end
end
return #bool
end
It always returns false. What is wrong with this ?
Is your #permissions getting populated? You can also write this without the break
def has_permission? (perm)
#graph = Koala::Facebook::API.new(current_user.token)
#permissions = #graph.get_connections('me', 'permissions')
#bool = false
#permissions.each do |p|
unless #bool
#bool = (p[0] == perm && p[1] == 'granted')
end
end
#bool
end
I would also move the p[0] == perm && p[1] == 'granted' into its own method for better readability.
I solved it myself:
def has_permission? (perm)
#graph = Koala::Facebook::API.new(current_user.token)
#permissions = #graph.get_connections('me', 'permissions')
# binding.pry
#bool = false
#permissions.each do |p|
if (p['permission'] == perm && p['status'] == 'granted')
#bool = true
break
end
end
#bool
end
Just changed p[0] to p['permission'] and p[1] to p['status']

How to use multiple #select blocks in Ruby?

Let's say I have a list of records like:
transactions = Transaction.all
And I have the following instance methods #currency, #geo, #industry. I want to select records which has the following criteria:
Select all transactions that has field currency which equals to #currency unless #currency is nil and in this case we'll ignore the condition (currency would mean all currencies when it's nil)
Select all transactions that has field geo which equals to #geo unless #geo is nil.
Select all transactions that has field industry which equals to #industry unless #industry is nil.
I tried multiple #select but with no luck something like:
transactions.select{ |i| (i.currency == #currency) unless #currency.nil? }.
.select{ |i| (i.geo == #geo) unless #geo.nil? }.
.select{ |i| (i.industry == #industry) unless #industry.nil? }
The problem with your example is the unless #currency.nil? will return nil (which is falsey) if #currency is nil, which is the opposite of what you intended.
You should use || instead:
transactions.select{ |i| (i.currency == #currency) || #currency.nil? }.
select{ |i| (i.geo == #geo) || #geo.nil? }.
select{ |i| (i.industry == #industry) || #industry.nil? }
In this case, if #currency is nil, the first condition will return true, and all elements will pass the select box to the next one...
Another option would be to run the select block only is the parameter is not nil. In this case, you'd like to break the line into separate blocks:
transactions.select!{ |i| (i.currency == #currency) } unless #currency.nil?
transactions.select!{ |i| (i.geo == #geo) } unless #geo.nil?
transactions.select!{ |i| (i.industry == #industry) } unless #industry.nil?
transactions.select do |t|
(#currency.nil? || t.currency == #currency) &&
(#geo.nil? || t.geo == #geo) &&
(#industry.nil? || t.industry == #industry)
end
this should do the job.
Or, if you are into dynamics:
[:currency, :geo, :industry].all? do |field|
(ivar = instance_variable_get("##{field}")).nil? || t.send(field) == ivar
end
Use AR/SQL instead of Ruby processing when possible:
transactions.where(currency: #currency, geo: #geo, industry: #industry)
Multiple use of select is superfluous in this situation. You can use && and || logical operators:
transactions.select do |transaction|
(#currency.nil? || transaction.currency == #currency) &&
(#geo.nil? || transaction.geo == #geo) &&
(#industry.nil? || transaction.industry == #industry)
end

Resources