Я создаю простой трекер привычек. У пользователя много Привычек, и мне нужно отслеживать, выполнили ли они Привычки в данный день во времени. *
completed_habit.rb
belongs_to :user
belongs_to :habit
У меня есть метод в моей модели Habit, который я хотел бы создать массив дат со значением 1 или 0, а затем я просто l oop через этот массив в представлении и показать X или чек.
def sequence
query = <<-SQL
SELECT
series_date,
COUNT(habit_id) AS completed
FROM generate_series(
( SELECT created_at::date FROM habits
WHERE habits.id = :user_id
),
CURRENT_DATE,
'1 day'
) AS series_date
LEFT JOIN completed_habits ON completed_habits.created_at::date = series_date
WHERE habit_id = :habit_id
AND user_id = :user_id
GROUP BY series_date
ORDER BY series_date DESC;
SQL
Habit.find_by_sql([query, { user_id: self.user, habit_id: self.id } ])
end
Когда я запускаю этот запрос в Postico, я получаю следующее, которое почти готово (я бы предпочел, чтобы строка для дат, для которых в этот день не указано completed_habit с завершенным значением 0):
Однако, когда я визуализирую @habit .sequence в моем представлении Rails, я получаю следующее:
Я не понимаю, почему он не возвращает series_date, привычку_id и завершено значения, которые я вижу в Postico.
ОБНОВЛЕНИЕ:
Использование Model.connection.exec_query Теперь у меня это работает, но все еще кажется довольно привлекательным нкий мне. Есть ли более чистый, более "Railsy" способ сделать это?
def sequence
query = <<-SQL
SELECT
series_date,
COUNT(habit_id) AS completed
FROM generate_series(
( SELECT created_at::date FROM habits
WHERE habits.id = $1
),
CURRENT_DATE,
'1 day'
) AS series_date
LEFT JOIN completed_habits ON completed_habits.created_at::date = series_date
GROUP BY series_date
ORDER BY series_date ASC;
SQL
binds = [
ActiveRecord::Relation::QueryAttribute.new("habit_id", self.id, ActiveRecord::Type::Integer.new)
]
Habit.connection.exec_query(query, 'sql', binds).to_a
end
schema.rb
create_table "completed_habits", force: :cascade do |t|
t.integer "user_id"
t.integer "habit_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "habits", force: :cascade do |t|
t.string "name"
t.integer "user_id"
t.string "frequency"
t.boolean "is_active"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.text "description"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "name"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end