2013-04-17 57 views
0

我想爲我的應用程序添加取消訂閱功能。實現它的最好方法是什麼?我正在考慮添加一個布爾列,並根據其真/假值我會發送一封郵件,但在這種情況下,我將不得不爲每種類型的通知創建一個布爾列。有沒有什麼辦法可以創建一個包含散列的列,例如:在rails 3中取消訂閱功能

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

在此先感謝。

+0

爲什麼你想這樣做? –

+0

我有一個功能,用戶可以選擇他想要接收的通知類型。 – Deepika

+0

我的意思是,爲什麼要創建一個單列來存儲散列?爲什麼不使用三個布爾列? –

回答

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 
+0

任何人都懶得評論downvote ??? – Salil

+0

每次你想寫一個單一的信息,你必須加載一個YAML字符串,修改散列,並重寫YAML?你的數據庫中有500個字符的列來存儲3位數據?當用戶提交表單以更新他們的偏好時會發生什麼?你不用控制器中的'params'哈希函數,你是否首先將該哈希函數轉換爲YAML? –

+0

但你的建議的問題是,假設我想取消訂閱'n'電子郵件,我必須在我的數據庫中有那麼多列,這會使我的數據庫變得更重。 – Salil

1

的替代薩里爾的建議是使用單一bitmasked柱代替,姑且稱之爲subscription_mask

要開始,建立一個數組中的相應模型常數(假設User):

# user.rb 
SUBSCRIPTION_TYPES = ["Daily", "Weekly", "Monthly"] 

其他訂閱類型可以稍後加入,只要它在該陣列的端部。這個單列可以非常有效地存儲大量標誌。

然後你就可以創建一組的方法,與位掩碼進行交互,使用虛擬屬性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"] 

這個意見的另一個優點ch是可以在查詢中使用它。例如,讓所有用戶提供每週訂閱:

User.where("subscription_mask & ? > 0", 2**SUBSCRIPTION_TYPES.index("Weekly")) 

這是一個有點亂,但可以很容易地用一種方法或範圍的清理。

+0

[** flag_shih_tzu **寶石](http://www.plugingeek.com/repos/pboling/flag_shih_tzu)也使用這種方法處理ActiveRecord模型中的多個標誌。 –