Есть ли лучший способ сохранить данные в столбце с logi c, рассчитанным в модели с использованием Rails? - PullRequest
0 голосов
/ 01 мая 2020

У меня есть модель 'work_space', которая имеет 'много' обзоров '. В моей модели 'обзоры' пользователи могут оценивать рабочее пространство с целым числом, хранящимся в столбце :rating. Я создал метод в своей модели WorkSpace для вычисления среднего значения всех обзоров для определенного рабочего пространства.

класс WorkSpace def avg_rating reviews.average(:rating).to_f end

Я добавил этот метод в свой сериализатор WorkSpace, и он возвращает данные, которые я ищу ,

Затем я создал метод в моей модели WorkSpace, который вычислял бы 5 самых высоких «оцененных» рабочих пространств.

класс WorkSpace scope :by_average_for, ->(column) { joins(:reviews) .group('work_spaces.id') .order(Arel.sql("AVG(reviews.#{column}) desc")) .having("AVG(reviews.#{column}) > 4", column) if column } def top_avg_rating WorkSpace.by_average_for(:rating).limit(5) end

Проблема, с которой я здесь сталкиваюсь, заключается в том, что когда я получаю данные для top_avg_rating, в нем перечислены правильные рабочие области, но я получаю только те данные, которые присутствуют в моей схеме WorkSpace, и не добавленные данные, которые я обычно получаю от моего сериализатора WorkSpace. Наиболее важно, что avg_rating отсутствует.

  create_table "work_spaces", force: :cascade do |t|
    t.string "place_id"
    t.float "lat"
    t.float "lng"
    t.bigint "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "name"
    t.string "address"
    t.string "photo"
    t.integer "cached_votes_total", default: 0
    t.integer "cached_votes_score", default: 0
    t.integer "cached_votes_up", default: 0
    t.integer "cached_votes_down", default: 0
    t.integer "cached_weighted_score", default: 0
    t.integer "cached_weighted_total", default: 0
    t.float "cached_weighted_average", default: 0.0
    t.index ["user_id"], name: "index_work_spaces_on_user_id"
  end

Я подумал, что было бы неплохо сохранить / кэшировать данные, которые я получаю из моей модели WorkSpace, в новый столбец. Поэтому я добавил столбец в свою модель WorkSpace.

t.float "avgrating"

Затем я попытался сохранить данные для моего avg_rating в этом столбце.

Класс WorkSpace def update_rating reviews.average(:rating).to_f update(avgrating: reviews.average(:rating).to_f) end

Это на самом деле работает, но я должен добавить этот метод в мой сериализатор, чтобы обновить столбец. Есть ли другой способ убедиться, что этот метод вызывается? Я изучил after_save вариантов и кэширование, но я не смог собрать воедино ничего, что имело бы смысл.

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

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

1 Ответ

0 голосов
/ 01 мая 2020

Добавьте select к by_average_for

scope :by_average_for, ->(column) {
  avg_rating = "AVG(reviews.#{column})"

  joins(:reviews)
    .select("work_spaces.*, #{avg_rating} AS avg_rating")
    .group('work_spaces.id')
    .order(Arel.sql("#{avg_rating} desc"))
    .having("#{avg_rating} > 4", column) if column
}

, тогда вы можете получить доступ avg_rating

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...