Thomas Taylor
Thomas Taylor

Reputation: 874

Rails Handling Nil in Class Method Chaining

I have the following Search class method that takes a bunch of params and then builds a request.

def self.search(agent, params)
  RealPropertySale.where(id: available_ids)
                      .joins(:address)
                      .by_state(state)
                      .by_suburb(suburb)
                      .by_post_code(post_code)
                      .by_country(country)
                      .paginate(page: page)
end

def self.by_state(state)
  where(addresses: {state: state})
end

def self.by_suburb(suburb)
  where(addresses: {suburb: suburb})
end

def self.by_post_code(post_code)
  where(addresses: {post_code: post_code})
end

def self.by_country(country)
  where(addresses: {country: country})
end

What is the correct way of handling if one of my custom class methods e.g. self.by_country(country) returns nil so that the query continues with whatever param/s are present. I have tried returning self if one the params is blank but the query is lost and the class is returned resulting in errors.

Upvotes: 1

Views: 374

Answers (2)

Stan
Stan

Reputation: 583

We did something similar by breaking it down like so :

response = RealPropertySale.where(id: available_ids)
                  .joins(:address)
response = response.by_state(state)          if state
response = response.by_suburb(suburb)        if suburb
response = response.by_post_code(post_code)  if post_code
response = response.by_country(country)      if country
response = response.paginate(page: page)     if page

I like the readibility. I try to break it down to as many pieces as needed, but this should be adapted to your business logic. Don't know if, for you, it makes sense to check if suburb is provided for example.

Upvotes: 1

Matouš Borák
Matouš Borák

Reputation: 15944

I agree with @Michael Gaskill that you probably should only call the scopes that actually affect the final query (i.e. that have meaningful params).

However, if you insist on the scopes ignoring nil parameters, you may make them return current_scope instead (which is an undocumented but useful method):

def self.by_state(state)
  return current_scope if state.nil?
  where(addresses: {state: state})
end

Upvotes: 2

Related Questions