2015-03-27 2 views
-2

Предположим, у меня есть класс Active Record.Рубин проверить, является ли метод цепочки valud

Если у меня есть:

Дом, который имеет много людей, у которых есть много собак, у которых есть много ошейников.

Я не буду использовать определения схемы, поскольку они тривиальны.

Теперь я хочу со страницы, где у меня есть объект дома, чтобы прорезать все ворота в этом доме.

Итак:

for c in house.people.dogs.collars do 
    puts c 
end 

Если нет людей в доме, то я получу undefined method ошибку, когда цепь попадает people.dogs.

Я могу обойти это двумя способами. Я могу заключить все это в гнездо операторов if, проверяя один уровень за раз и выполняя только указанный выше код, если я сначала проверил все части цепочки. Я также мог бы использовать begin и rescue.

Мой вопрос:

Есть еще один способ сделать это? Некоторые методы, которые позволили бы мне сделать что-то вроде:

for c in foo(house.people.dogs.collars) do 
    puts c 
end 

без каких-либо других кодов. Foo будет проверять, действительно ли цепочка действительна, а затем выполнить ее, иначе она молча ничего не сделает. Если нет лучшего способа сделать это, я просто сделаю функцию самостоятельно и верю хэш или массив в качестве обеспечения.

+1

В Rails: 'house.people.try (: dogs) .try (: collars)'? –

ответ

2

Не верно. Потому что house.people вернет массив. И вы не можете вызвать dogs на этом массиве. Вам нужно будет позвонить dogs на каждого человека в массиве.

Следующая будет работать в обоих случаях, если имеются элементы в ассоциации или если нет:

house.people.flat_map(&:dogs).flat_map(&:collars) 

Вы можете очистить это с has_many through associations или есть метод на house, который инкапсулирует эту логику.

Кроме того, стоит упомянуть, что вы испытаете ужасную производительность, потому что каждый шаг в цепочке приведет к нескольким вызовам в базе данных. В зависимости от размера вашей базы данных я бы хотел написать специализированные области с объединением баз данных.

+0

Спасибо, я имел в виду, и насколько я вижу, написали, что проблема будет возникать, когда я пытаюсь получить доступ к собакам. Я понимаю, что люди вернут массив и что у массива не будет метода «собаки». Я посмотрю на это, а также на ответ. Да: через отношения будут работать, я использовал их для разных вещей. Мой вопрос был просто потому, что часто существует невероятно сложный способ делать разные вещи в рубине, и я подумал, существует ли такая вещь здесь. – Axiombadger