0

我想向我的应用程序添加取消订阅功能。实现它的最佳方法是什么?我正在考虑添加一个布尔列,并根据它的真/假值发送邮件,但在这种情况下,我必须为每种类型的通知创建一个布尔列。有没有办法创建一个包含哈希的单列,例如:

{:daily_notification=>true, :weekly_notification=>false, :yearly_notification=>true}

提前致谢。

4

2 回答 2

1

我在我的应用程序中按照以下方式进行操作,因为我有很多需要取消订阅的电子邮件,所以我将权限哈希保存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
于 2013-04-17T06:14:27.627 回答
1

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"))

它有点混乱,但可以使用方法或范围轻松清理。

于 2013-04-17T07:19:05.390 回答