I have a web app built with a Rails API to collect submissions. I have a form being submitted that sends an email lead to certain Stores that have matching attributes (location, size, etc). They are matched based off the following fields
- Location
- Capacity (min and max)
- Store Type (hotel, dining, unique)
I also have an attribute for the store to receive all leads, that I want to override any of the previous options, if set to true.
In the hard_worker.rb in my Rails API, I have it checking the following fields, in order to query which Stores to send the Leads to. I know the chaining of conditionals isn't correct, but cannot figure out how to reformat it to send correctly. Any help would be greatly appreciated, Thanks!
def build_filters_obj
filters = []
filters.push 'location_north' if @lead.location_north
filters.push 'location_east' if @lead.location_east
filters.push 'location_south' if @lead.location_south
filters.push 'location_west' if @lead.location_west
filters.push 'location_other' if @lead.location_other
return filters
end
def perform(lead_id)
@lead = Lead.find(lead_id)
lead_email = ValidEmail2::Address.new(@lead.email)
UserNotifierMailer.send_signup_email(@lead).deliver if lead_email.valid?
@stores = Store.all
@stores = @stores.where.not(email: [nil, ''])
n = @lead.guests_total.to_i
@stores = @stores.where("capacity_min <= ? AND capacity_max >= ?", n, n)
@stores = @stores.where(:type_unique => true) if @lead.store_type_unique
@stores = @stores.where(:type_dining => true) if @lead.store_type_dining
@stores = @stores.where(:type_hotel => true) if @lead.store_type_hotel
filters = build_filters_obj
filters.each do |filter|
@stores = @stores.where(filter.to_sym => true)
end
@stores = @stores.or(Store.where(:receive_all => true))
@stores.each do |store|
store_email = ValidEmail2::Address.new(store.email)
UserNotifierMailer.send_lead_email(store, @lead).deliver if store_email.valid?
end
end
I apologize if my code is atrocious, Ruby is not where I usually work and I'm sure I'm committing some beginner errors!
Biggest code smell I've noticed is there are lots of if checks, and it makes harder to reason with your code. Try to create hashes and call methods to clean the hash instead.
I would also suggest you to pass this code through rubocop. It will make your code feel more idiomatic and less wrong.
Maybe we can at least make it ready to use. In ruby idiomatic way to name this would be as a noun and directly use it. Notice that we are not creating strings and not converting them into symbols later.
You can build a hash then remove falsy values
So overall this is how you can call the query instead
https://rubyapi.org/3.2/o/hash#method-i-filter