Какой эффективный способ связать модели сообщений, комментариев, пользователей и голосования в Rails? - PullRequest
1 голос
/ 02 февраля 2012

Сейчас у меня есть три модели Post, Comment и User (с использованием Devise ), связанные следующим образом:

post.rb:

class Post < ActiveRecord::Base
  attr_accessible :title, :content, :total_votes

  validates :title,   :presence => true,
                      :length   => { :maximum => 30 },
                      :uniqueness => true
  validates :content, :presence => true,
                      :uniqueness => true

  belongs_to :user
  has_many :comments, :dependent => :destroy
end

comment.rb:

class Comment < ActiveRecord::Base
  attr_accessible :content, :user_id

  belongs_to :post, :counter_cache => true
  belongs_to :user
end

user.rb:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :omniauthable
  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, :username

  validates_presence_of :username
  has_many :posts, :dependent => :destroy
  has_many :comments, :dependent => :destroy

  def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
    data = access_token.extra.raw_info
    if user = User.where(:email => data.email).first
      user
    else # Create a user with a stub password. 
      User.create!(:email => data.email, :password => Devise.friendly_token[0,20]) 
    end
  end
end

Я хочу добавить четвертую модель под названием Голосование со следующими условиями:

  1. Обе сообщения и комментарии могут быть проголосованы (вверх и вниз) и показывают общую / сумму.
  2. Каждый пост будет иметь много голосов (вверх и вниз) и отображать общую сумму / сумму.
  3. Каждый комментарий будет иметь много голосов
  4. Идентификатор пользователя должен храниться каждый раз, когда он или она голосует, чтобы я мог ограничить один голос на пользователя и показать идентификатор / имя пользователя, который проголосовал (не уверен, где его хранить)

Теперь я не уверен, является ли это хорошим поводом для использования полиморфных ассоциаций и / или counter cache .

Какой эффективный способ связать эти модели сообщений, комментариев, пользователей и голосования? (Если возможно, я бы хотел посмотреть, как будет выглядеть миграция)

1 Ответ

1 голос
/ 02 февраля 2012

Это прекрасный пример из учебника, где полиморфная ассоциация будет полезна.

Ваша votes таблица миграции будет выглядеть следующим образом:

create_table :votes do |t|
  t.references :votable, :polymorphic => true
  t.references :user
  t.integer :polarity
  t.integer :total
end

Это создаст таблицу с этой схемой:

id INTEGER
votable_id INTEGER
votable_type VARCHAR
user_id INTEGER
polarity INTEGER
total INTEGER

Здесь user_id будет лицом, которое проголосовало, polarity будет либо '1' для повышения, либо '-1' дляпонижающий голос (это позволяет вам просто суммировать полярности, чтобы получить положительные и отрицательные голоса для отмены), votable_type будет содержать то, за что голосует (Post или Comment), votable_id будет содержать идентификатор вещиголосование за, и total будет содержать промежуточную сумму голосов (для эффективности).

Тогда ваши модели будут выглядеть так:

class Vote < ActiveRecord::Base
    belongs_to :votable, :polymorphic => true
    belongs_to :user

    before_create :update_total

    protected

    def update_total
        self.total ||= 0
        self.total += self.polarity
    end
end

class Post < ActiveRecord::Base
    has_many :votes, :as => :votable
end

class Comment < ActiveRecord::Base
    has_many :votes, :as => :votable
end

class User < ActiveRecord::Base
    has_many :votes
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...