2015-12-09 3 views
1

В модели я пытаюсь вернуть условный набор результатов ActiveRecord. Если автор написал книги, верните их. Если автор не написал никаких книг, верните статьи. Это работает:Rails Рефакторинг: более эффективные запросы ActiveRecord и тестирование состояния

def writings 
    Books.where(author_id: 1).present? ? Books.where(author_id: 1) : Articles.where(author_id: 2) 
end 

Как это может быть улучшено
1. При проверке условий и значения параметров, т.е. не выполняет Books.where запроса дважды?
2. С точки зрения производительности

я работаю над улучшением моей эффективности и стиля и часто используют либо Style Guide bbatsov или addition.

ответ

1

Вы можете использовать presence метод в сочетании с двойной трубой:

def writings 
    Books.where(author_id: 1).presence || Articles.where(author_id: 2) 
end 

Из документации: http://apidock.com/rails/Object/presence

presence() public

Возвращает приемник если он присутствует, то возвращается nil.

Некоторые примеры:

true.presence # => true 
1.presence # => 1 
false.presence # => nil 
[].presence # => nil 
''.presence # => nil 
User.where(id: -1).presence # => nil 
0

Ну, в первую очередь, вы всегда делаете 2 запроса. 1 - получить подарок ?, второй - получить либо книги, либо статьи.

Вы можете улучшить, изменив код, чтобы выбирать книги, а если их нет, то возвращается статьи.

def writings 
    books = Books.where(author_id: 1) 
    if books.size > 0 
    books 
    else 
    Articles.where(author_id: 2) 
    end 
end 
1

Рассмотрим реализацию counter_cache на обеих моделях статьи книги и.

# class Book 
belongs_to :author, counter_cache: true 

# class Article 
belongs_to :author, counter_cache: true 

Подробнее о кэшировании счетчика here.

Затем вы можете проверить значение books_count перед запуском любых запросов.

# class Author 
# assumes has_many :books 
# and  has_many :articles 
def writings 
    if books_count.nonzero? 
    books 
    else 
    articles 
    end 
end