Система голосования Thumbs Up - PullRequest
       8

Система голосования Thumbs Up

0 голосов
/ 20 февраля 2012

Я хочу создать систему голосования Thumbs Up, но я не знаю, как это сделать наилучшим образом.

Вот мои записи № голосования (контроллер / действие):

def vote
    if Entry.where(id: params[:entry_id]).first && Vote.where(entry_id: params[:entry_id], user_id: @current_user.id).first.nil? # Check if entry with given entry_id exist && Check if user vote previously.
        Vote.create(entry_id: params[:entry_id], user_id: @current_user.id) # Create vote
        ActiveRecord::Base.connection.execute("UPDATE `entries` SET `entries`.`points` = `entries`.`points` + 1 WHERE `entries`.`id` = #{params[:entry_id].to_i}") # Update entry points count.
    end

    render nothing: true
end

Я думаю, что это не оптимальный способ сделать это, потому что в этом действии много запросов.Вот журналы запросов:

Started GET "/vote/2" for 127.0.0.1 at 2012-02-20 16:20:01 +0100
Processing by EntriesController#vote as JS
  Parameters: {"entry_id"=>"2"}
  ←[1m←[36mUser Load (1.0ms)←[0m  ←[1mSELECT id, name FROM `users` WHERE `users`.`auth_token` = '6f1aa3b944d530a1d52c6f40bcb69398' LIMIT 1←[0m
  ←[1m←[35mEntry Load (1.0ms)←[0m  SELECT `entries`.* FROM `entries` WHERE `entries`.`id` = 2 LIMIT 1
  ←[1m←[36mVote Load (0.0ms)←[0m  ←[1mSELECT `votes`.* FROM `votes` WHERE `votes`.`entry_id` = 2 AND `votes`.`user_id` = 1 LIMIT 1←[0m
  ←[1m←[35m (0.0ms)←[0m  BEGIN
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mINSERT INTO `votes` (`entry_id`, `user_id`) VALUES (2, 1)←[0m
  ←[1m←[35m (54.0ms)←[0m  COMMIT
  ←[1m←[36m (16.0ms)←[0m  ←[1mUPDATE `entries` SET `entries`.`points` = `entries`.`points` + 1 WHERE `entries`.`id` = 2←[0m
  Rendered text template (0.0ms)
Completed 200 OK in 115ms (Views: 1.0ms | ActiveRecord: 78.0ms)

У кого-нибудь есть идеи, как это сделать наилучшим образом?

Ответы [ 4 ]

2 голосов
/ 21 февраля 2012

Эта логика контроллера может быть очищена.Если только 1 голос = 1 балл, вы можете использовать counter_cache для отслеживания баллов.Если вам также нужны большие пальцы вниз, вы можете использовать update_counters .

Entry.rb

class Entry < ActiveRecord::Base
  has_many :votes
end

Vote.rb

class Vote < ActiveRecord::Base
  belongs_to :entry, :counter_cache => :points  
  belongs_to :user
end

User.rb

class User < ActiveRecord::Base
  has_many :votes
end

EntriesController # voice

def vote
  Vote.find_or_create_by_entry_id_and_user_id(params[:entry_id], @current_user.id)
  render :nothing
end

Для новыхЖурнал голосования SQL:

  Vote Load (0.3ms)  SELECT "votes".* FROM "votes" WHERE "votes"."entry_id" = 3 AND "votes"."user_id" = 1 LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.4ms)  INSERT INTO "votes" ("created_at", "entry_id", "updated_at", "user_id") VALUES ($1, $2, $3, $4) RETURNING "id"  [["created_at", Tue, 21 Feb 2012 16:51:54 UTC +00:00], ["entry_id", 3], ["updated_at", Tue, 21 Feb 2012 16:51:54 UTC +00:00], ["user_id", 1]]
  Entry Load (0.2ms)  SELECT "entries".* FROM "entries" WHERE "entries"."id" = 3 LIMIT 1
  SQL (0.2ms)  UPDATE "entries" SET "points" = COALESCE("points", 0) + 1 WHERE "entries"."id" = 3
   (2.3ms)  COMMIT

Для существующего голосования:

  Vote Load (0.4ms)  SELECT "votes".* FROM "votes" WHERE "votes"."entry_id" = 3 AND "votes"."user_id" = 1 LIMIT 1
 => #<Vote id: 7, user_id: 1, entry_id: 3, created_at: "2012-02-21 16:51:54", updated_at: "2012-02-21 16:51:54">
0 голосов
/ 20 февраля 2012

Вы можете использовать запрос, чтобы проверить, что запись существует, и если пользователь еще не голосовал по этой записи. Пример:

SELECT enrty.* FROM enrty LEFT JOIN votes ON enrty.voteId=votes.Id AND votes.UserId=userId And enrty.Id=enrtyId WHERE vote.id IS NULL

Если этот запрос возвращает запись, это означает, что запись существует ипользователь еще не проголосовал за эту запись.

0 голосов
/ 20 февраля 2012

Не прямой ответ, но вы можете использовать или искать вдохновение для других драгоценных камней, таких как voice_fu или thumbs up (последний начался как форк первогоодин).Если вы не используете один из них, скорее всего, вы чему-то научитесь из их кода.

0 голосов
/ 20 февраля 2012

похоже, что все ваши конструкторы выполняют свои собственные запросы ..

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

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

...