我有一些模型,我希望用户能够订阅或取消订阅,即在某些事件发生时选择加入或不接收通知。
例如,我有一个视频模型,用户可以评论和评论。如果用户订阅了视频,他们会在发生某些事情时收到通知(类似于Github)。评论,评论,状态变化等。
我想知道如何根据模型及其相互关系来设置它。
例如,我会创建一个通用的NotificationSubscription模型吗?:
class NotificationSubscription
belongs_to :subscribable, polymorphic: true
belongs_to :subscriber, class_name: "User", foreign_key: "user_id"
end
class User
has_many :notification_subscriptions, dependant: :destroy
end
然后在可订阅的模型中:
class Video
has_many :notification_subscriptons, as: :subscribable, dependant: :destroy
has_many :notification_subscribers, through: :notification_subscriptons, source: :subscriber
end
或有疑虑:
module Subscribable
extend ActiveSupport::Concern
included do
has_many :notification_subscriptions, as: :subscribable, dependent: :destroy
has_many :subscribers, through: notification_subscriptions
end
module ClassMethods
end
def subscription_for(subscriber)
subscriber.try(:notification_subscriptions).try(:find_by, subscribable: self)
end
def subscribe(subscriber)
return false if subscription_for(subscriber).present?
subscription = NotificationSubscription.new(subscribable: self, subscriber: subscriber)
subscription.save
end
def unsubscribe(subscriber)
subscription = subscription_for(subscriber)
return false unless subscription.present?
subscription.destroy
end
end
class Video
include Subscribable
end
和notification_subscription架构:
class CreateNotificationSubscriptions < ActiveRecord::Migration
def change
create_table :notification_subscriptions do |t|
t.references :user, index: true
t.references :subscribable, polymorphic: true, index: true
t.boolean :subscribed
t.boolean :ignored
t.string :reason
t.timestamps
end
add_index :notifications_subscriptions, [:user_id, :subscribable_id, :subscribable_type], unique: true
end
end
答案 0 :(得分:1)
我会使用多态关联,但我认为你的措辞有些错误。给出的例子是:
http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
end
class Employee < ActiveRecord::Base
has_many :pictures, as: :imageable
end
class Product < ActiveRecord::Base
has_many :pictures, as: :imageable
end
它比你的多态代码简单得多。它实际上是你在第一个和第二个例子中所拥有的组合。
稍微偏离主题,但希望这很有用,我会将ActiveSupport::Notifications
用于事件本身。通过这种方式,您可以触发事件并让单独的对象订阅该事件,以通过直接电子邮件或通过启动Sidekiq作业来发送订阅者(用户)通知。 http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html