我想向我的应用程序添加取消订阅功能。实现它的最佳方法是什么?我正在考虑添加一个布尔列,并根据它的真/假值发送邮件,但在这种情况下,我必须为每种类型的通知创建一个布尔列。有没有办法创建一个包含哈希的单列,例如:
{:daily_notification=>true, :weekly_notification=>false, :yearly_notification=>true}
提前致谢。
我想向我的应用程序添加取消订阅功能。实现它的最佳方法是什么?我正在考虑添加一个布尔列,并根据它的真/假值发送邮件,但在这种情况下,我必须为每种类型的通知创建一个布尔列。有没有办法创建一个包含哈希的单列,例如:
{:daily_notification=>true, :weekly_notification=>false, :yearly_notification=>true}
提前致谢。
我在我的应用程序中按照以下方式进行操作,因为我有很多需要取消订阅的电子邮件,所以我将权限哈希保存YAML format
在我的用户表中,如下所示
add_column :users, :permission, :string, :limit=> 500
保存默认权限
user = User.first
default_permission_hash = {"send_daily_email"=>"true", "send_weekly_email"=>"true", "send_monthly_email"=>"true"}
user.permission = default_permission_hash.to_yaml
user.save
更新权限
user = User.first
permission_hash = YAML::load(user.permission)
permission_hash["send_daily_email"] = false
user.permission = permission_hash.to_yaml
user.save
在模型中
def is_permission_for?(email)
permission_hash = YAML::load(self.permission)
permission_hash[email] == "true"
end
在控制器中
user = User.first
if user.is_permission_for?("send_daily_email")
//send daily email
end
Salil 建议的替代方法是使用单个位掩码列,我们称之为subscription_mask
.
首先,在适当的模型中设置一个数组常量(假设User
):
# user.rb
SUBSCRIPTION_TYPES = ["Daily", "Weekly", "Monthly"]
稍后可以添加其他订阅类型,只要它位于此数组的末尾即可。这一列可以非常有效地存储大量标志。
然后,您可以使用 virtual 属性创建一组与位掩码交互的方法subscriptions
:
# Make subscriptions attr_accessible so we can mass assign to it (useful for forms)
attr_accessible :subscriptions
# Basic setter, overwrites all subscriptions with an array of subscriptions
def subscriptions=(subs)
self.subscription_mask = (SUBSCRIPTION_TYPES & subs).map{ |s| 2**SUBSCRIPTION_TYPES.index(r) }.inject(0, :+)
end
# Basic getter, returns an array of the set subscriptions
def subscriptions
SUBSCRIPTION_TYPES.reject do |s|
((subscription_mask || 0) & 2**SUBSCRIPTION_TYPE.index(s).zero?
end
end
# Check if a subscription is set
def has_subscription? (sub)
self.subscriptions.includes? sub
end
# Add subscriptions to the current mask without affecting any others
def set_subscriptions (*subs)
self.subscriptions = self.subscriptions | subs
end
# Remove subscriptions from the current mask without affecting any others
def unset_subscriptions (*subs)
self.subscriptions = self.subscriptions - subs
end
那里有一些方法,但我发现它们在不同的情况下很有帮助。
使用这些方法,您可以像这样设置用户的订阅:
@user.subscriptions = ["Weekly", "Monthly"]
并检查他们是否订阅了:
@user.has_subscription? "Daily" # => false, in this case
如果同一用户订阅了每日消息但取消订阅每周消息:
@user.set_subscriptions "Daily"
@user.unset_subscriptions "Weekly" # => ["Weekly", "Monthly"]
# Or, to do both changes at once (you need to re-set Weekly though)
@user.subscriptions = ["Weekly", "Monthly"]
这种方法的另一个优点是可以在查询中使用它。例如,要让所有用户每周订阅:
User.where("subscription_mask & ? > 0", 2**SUBSCRIPTION_TYPES.index("Weekly"))
它有点混乱,但可以使用方法或范围轻松清理。