2014-11-20 2 views
1

Использование Rails 4 в контроллере я хотел бы добавить атрибут к переменной экземпляра.Как добавить атрибут к переменной экземпляра в rails 4?

Извините за плохой пример, я пытаюсь сохранить его простым.

E.g. В контроллере я создаю новую переменную экземпляра, просматривая некоторых пользователей по имени Джон. Теперь, в моем контроллере, я хотел бы подвести итоги всех возрастов для всех пользователей по имени Джон, вернуть этот суммированный возраст в переменную экземпляра, чтобы он был доступен для представления.

Модель пользователя имеет атрибуты 'id', 'name' и 'age'.

@foo_users = Users.where(name: 'John') 

@foo_users.each do |foo| 
    @foo_users.age_sum = Users.where(name: 'John').sum(:age) <-- this does not work 
end 

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

<% @foo_users.each do |user| %> 
    User name: <%= user.name => 
    Sum of ages: <%= user.age_sum %> 
<% end %> 

Update: Я мог бы иметь более упростили мой пример. Вот приблизительный пример реальности.

Компания владеет гостиницами. В номерах есть номера. Программное обеспечение управления доставляет компании ежедневно Hotel_Statistics через API. Из-за отсутствия лучшего слова, эти Hotel_Statistics содержат hotel_id, ежедневные проверки, ежедневные выписки. В приложении back-office Rails компании, над которым я работаю, на отображаемой странице есть таблица отелей с их последними статистическими данными. Одна линии будет выглядеть так:

Hotel Id: 123 
Daily check-ins: 50 
Daily check-outs: 48 

Hotel Id: 124 
Daily check-ins: 35 
Daily check-outs: 37 

Компания также хочет показать идущую сумму за последние 30 дней возвратов (ауты, чистый чек-Ins). Чтобы выполнить это, в моем контроллере я нахожу Hotel_Statics для самой последней даты (обычно вчера).

latest_stat = HotelStatistic.order('date DESC, hotel_id DESC').first 
@latest_date = latest_stat.date 
@recent_stats = HotelStatistic.where(date: @latest_date).order('hotel.id ASC').all 

Я показываю детали @recent_stats на мой взгляд.

Теперь я хотел бы отобразить на мой взгляд сумму последних 30 дней @ recent_stats.check_ins для каждого отеля. Моя идея состояла в том, чтобы подвести итоги последних 30 дней статистики check_ins для данного отеля, как:

@recent_stats.each do |stat| 
    @last_30_days_check_ins = HotelStatistic.where(hotel_id: stat.hotel_id).where("date >= ?", Date.today - 30).sum(:check_ins) 
end 

математика работы, но мне нужен способ, чтобы получить доступ к переменной сумме 30 дня для каждого отеля. Я был в надежде сделать это легко в представлении, добавив день сумму отель 30 переменной @recent_stats например, так, на мой взгляд, я мог бы сделать:

<% @recent_stats.each do |statistic| %> 
    Hotel Id: <%= statistic.hotel_id %> 
    Daily check-ins: <%= statistic.check_ins %> 
    Last 30 days check-ins: <%= statistic.last_30_days_check_ins %>  
<% end %> 

Изменит ли это более реалистичный пример ничего в ваших предложенных ответов ? Благодаря

+0

Почему downvote? Я явно смущен. – Ryan

ответ

0

Тип @foo_users: ActiveRecord::Relation. Попытка добавить age_sum в качестве нового атрибута к объекту ActiveRecord::Relation не имеет смысла, потому что семантически age_sum не является атрибутом ActiveRecord::Relation объектов. Лучше хранить сумму возрастов в новой переменной экземпляра, например @user_age_sum.

UPDATE Попробуйте следующее

class HotelStatistic < ActiveRecord::Base 
    belongs_to :hotel 
end 

class Hotel < ActiveRecord::Base 
    has_many :hotel_statistics 

    def last_30_days_check_ins 
    self.hotel_statistics.where("date >= ?", 30.days.ago).sum(:check_ins) 
    end 

end 

Держите существующий код для создания @recent_stats в контроллере

По мнению

<% @recent_stats.each do |statistic| %> 
    Hotel Id: <%= statistic.hotel_id %> 
    Daily check-ins: <%= statistic.check_ins %> 
    Last 30 days check-ins: <%= statistic.hotel.last_30_days_check_ins %>  
<% end %> 
+0

Спасибо. Вот чего я боялся. В моем .each do loop я могу создать новую переменную для каждого | user |. Например, @ {user.name} .age_sum? – Ryan

+0

Хотя в пользовательскую модель можно добавить новый атрибут «age_sum», я рекомендую против этого, потому что семантически «age_sum» не является атрибутом объектов User. С точки зрения объектно-ориентированного программирования основная идея - это атрибут, который должен храниться в нужном объекте, а не в любых объектах, доступных вам (в вашем случае 'ActiveRecord :: Relation', а затем' User'. – Hoa

+0

Я обновил свой вопрос с более реалистичным примером. Спасибо – Ryan

0

Использование select должно решить вашу проблему:

@users = User.select("*, SUM(age) as age_sum").where(name: 'John') 

Теперь каждый User в @users массив будет иметь age_sum свойство. Это не на 100% идеально, так как значение свойства будет одинаковым для каждого экземпляра, но оно будет работать с тем, как вы настроили свое представление.

Редактировать Можно динамически определить метод экземпляра вручную:

@foo_users.each do |foo| 
    def foo.age_sum; Users.where(name: 'John').sum(:age); end; 
end 

Однако пока это возможно, она должна была бы быть очень хорошо использовать случай, чтобы оправдать негативное влияние в мае этого года (например, насколько читаемым, эффективным и поддерживаемым является код). Вероятно, есть намного лучшие способы ОО для решения одной и той же проблемы.

+0

Спасибо, что получает правильный результат, но не отвечает на вопрос. Вопрос заключается в том, как ввести новый атрибут в уже установленную переменную экземпляра. – Ryan

+0

Достаточно справедливо, см. Редактирование моего ответа – Pete

+0

Для более реалистичного варианта использования см. Мое редактирование исходного вопроса. Благодарю. – Ryan

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