Ruby on Rails: получение всех сущностей, у которых нет вхождений по определенной ассоциации и условию.

Я использую Рельсы 2.3.8

У меня есть две модели, которые представляют велосипеды и прокат велосипедов соответственно. У одного велосипеда может быть много прокатов, но не более одного «активного» проката. Я различаю активные прокаты с помощью поля статуса в таблице bike_rentals со значением BIKE_RENTAL_OUT (с двумя другими возможными значениями: BIKE_RENTAL_RETURNED и BIKE_RENTAL_INCIDENT)

Чтобы создать новую аренду, я хочу представить пользователю список всех велосипедов, которые в настоящее время не взяты в аренду, то есть всех велосипедов, у которых нет «активной» аренды (ноль вхождений в ассоциации с определенным условием).

Я придумал решение, используя именованную область, как показано ниже:

class Bike < ActiveRecord::Base
    has_many :bike_rentals
    named_scope :not_rented,
                :conditions => "bikes.id NOT IN " + 
                     "(SELECT bike_id FROM bike_rentals " + 
                     "WHERE bike_rentals.status = 'BIKE_RENTAL_OUT')"

end

class BikeRental < ActiveRecord::Base
    belongs_to :bike
end

и в контроллере я получаю этот список как:

@bikes = Bike.not_rented.find(:all, :order => 'chasis_number')

Приведенный выше код работает, но у меня возникло ощущение, что это должно быть лучшее решение или более «рельсовое» решение для этой (предположительно общей) проблемы.

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

Любые идеи?


person Miquel    schedule 13.02.2011    source источник


Ответы (1)


Если я правильно понимаю, вы хотите вернуть все велосипеды, у которых нет статуса «BIKE_RENTAL_OUT» в таблице велосипедов has_may, связанной с bike_rentals. Это должно быть в состоянии быть ограничено следующим образом:

named_scope :not_rented, :joins => :bike_rentals, :conditions => [ "bike_rentals.status != ?", BIKE_RENTAL_OUT]

Надеюсь это поможет

person David Barlow    schedule 14.02.2011
comment
К сожалению, этого недостаточно, потому что велосипед может одновременно находиться в этом соединении с BIKE_RENTAL_OUT и с BIKE_RENTAL_RETURNED, поэтому он все равно будет отображаться в списке, возвращаемом вашим named_scope. Мне нужны велосипеды, у которых нет строки с BIKE_RENTAL_OUT, независимо от любых других записей, которые тот же велосипед имеет в соединении. - person Miquel; 15.02.2011
comment
Я не уверен на 100% в том, что вы говорите, но если вы имеете в виду, что хотите оценить статус самой последней аренды для каждого велосипеда, вам придется использовать дополнительный выбор в своей области. вот ссылка на вопрос, который показывает это stackoverflow.com/questions/4858646/ - person David Barlow; 15.02.2011