2016-05-30 2 views
1

У меня есть следующий метод класса поиска, который берет кучу параметров и затем строит запрос.Rails Обработка Nil в классе Метод Chaining

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 

Каков правильный способ обработки, если один из моих собственных методов класса, например. self.by_country(country) возвращает nil, так что запрос продолжается с любыми параметрами/s. Я попытался вернуть себя, если один из параметров пуст, но запрос потерян, и класс возвращается, что приводит к ошибкам.

+0

'self.by_country (country)' не должен возвращать 'nil'. Он должен возвращать экземпляр «ActiveRecord :: Relation» с пустым множеством, и вы можете больше привязывать к нему запросы. – Uzbekjon

+0

Обратите внимание, что вам нужно только запросить цепочку запросов, имеющих соответствующие критерии. Если «страна» не указана, цепочка 'by_country (country)' будет выдавать оператор SQL без каких-либо строк, поэтому ваш запрос не сработает с другими допустимыми критериями. Вы можете выбрать, какие цепные методы вызывать в 'self.search', чтобы заставить его работать правильно. –

ответ

2

Я согласен с @Michael Gaskill, что вы, вероятно, должны вызывать области действия, которые фактически влияют на окончательный запрос (т. Е. Имеют значащие параметры).

Однако, если вы настаиваете на прицелах игнорирования nil параметров, вы можете сделать их вернуть current_scope вместо (который является undocumented, но полезный метод):

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

Я согласен с @Michael Gaskill и соответствующим образом скорректировал свой код. Что касается вашего ответа, я обнаружил, что вы можете либо «все», либо «current_scope». –

1

Мы сделали что-то подобное, разбив его например:

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 

Мне нравится читаемость. Я стараюсь разбить его на столько частей, сколько необходимо, но это должно быть адаптировано к вашей бизнес-логике. Не знаю, если для вас имеет смысл проверить, предоставлен ли пригород, например.

Смежные вопросы