2014-01-25 3 views
0

У меня есть следующие отношения в модели User.Rails - has_one отношения с WHERE & ORDER?

has_many :subscriptions, dependent: :destroy 
has_one :subscription, -> { where 'end_date >= ?', Date.today } 

: подписка - это, по сути, их самая последняя ежемесячная подписка. : subscriptions - это массив всех своих предыдущих ежемесячных подписчиков (включая самые последние). Они перечисляют start_date, end_date, user_id, plan_id, payment_method.

Когда план подписки обновлен или изменен, я изменил end_date на текущей подписке на Date.today (обозначая подписку, подписанную сегодня), а затем создайте новую подписку, которая начинается сегодня и заканчивается через месяц.

Проблема с наличием end_date как Date.today заключается в том, что предложение WHERE будет принимать отмененную подписку и новую подписку. Но будет способствовать отмененной подписке, потому что SQL-запрос сгенерировал tacks в классе ORDER BY для первичного идентификатора.

ORDER BY "subscriptions"."id" ASC LIMIT 1 

Для жизни меня, я не могу понять, как в обратном ORDER BY с ASC в DESc на ид. Но я бы предпочел, чтобы он заказывался на основе метки времени created_at. Следующим был бы соответствующий код только для заказа, но не обязательно, что у меня есть предложение WHERE в дополнение к предложению ORDER BY.

has_one :subscription, -> { order 'created_at desc' } 

Кто-нибудь понял, как совместить эти два?

+1

Пробовал ли сортировать его в рубине в отличие от SQL? – hd1

+0

Нет, но это может быть маршрут, необходимый, если Rails не позволяет комбинировать предложение where и order в одном и том же соотношении has_one, что, безусловно, удивительно. –

ответ

2

По Rails 4, Rails автоматически добавляет заказ по идентификатору при вызове метода first. (Вместо этого вы можете позвонить take). Поэтому я предполагаю, что has_one звонит first внутренне.

has_one Поскольку только автоматическое создание метода, называемого subscription, почему бы не просто создать его самостоятельно ?:

def subscription 
    subscriptions.where('end_date >= ?', Date.today).order("created_at DESC").take 
end 

Если вам не нравится это, это не ясно из вашего вопроса, я ли вы пробовали это:

has_one :subscription, -> { where('end_date >= ?', Date.today).order("created_at DESC") } 

Нет причин, по которым вы не можете связать эти два предмета. Но, как я помню, Rails 4 first переопределит вашу директиву order и заменит ее order(:id), так что это может не сработать. Вы можете точно узнать, указав @user.subscription.to_sql.

+0

Цепочный ордер на инструкцию where работал, не знал, что вы можете это сделать. Благодаря! –

0

Проблема заключается в несоответствии вашего дизайна между истекающими подписками и датировкой их как «сегодня», и заявлением, что только одна подписка может иметь дату окончания> = сегодня. Они противоречат друг другу, поэтому вам нужно решить эту проблему.

Сердце кажется, что даты начала подписки являются включенными, а даты окончания являются исключительными - если вы не определяете даты окончания как «последнюю дату, на которую подписка активна», а не «на следующий день после последнего день, когда подписка активна », у вас есть две подписки, которые активны в тот же день.

+0

Я дезинформировал, заявляя, что я хотел, чтобы это было заказано на end_date, я имел в виду отметку created_at timestamp. Я дал ответ, который использует модельную область для достижения того, что мне нужно. Что работает в этом случае, но не может работать для других, в зависимости от потребностей Модели. –

0

Помимо создания настраиваемого метода для обработки этого, а не с использованием отношения has_one, единственным решением, которое я мог бы найти при заказе запроса, является установка области в модели Subscription для заказа с помощью create_at DESC.

class Subscription < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :plan 

    default_scope order: 'created_at DESC' 


    #Subscription Load (0.2ms) SELECT "subscriptions".* FROM "subscriptions" WHERE "subscriptions"."user_id" = ? AND (end_date >= '2014-01-25') ORDER BY end_date DESC LIMIT 1 [["user_id", 2]]                          
Смежные вопросы