允许匿名/来宾用户"试用"功能,而无需在Rails/Devise/CanCan应用程序中注册

Edw*_*ith 5 ruby-on-rails devise cancan

我正在使用Devise和CanCan开发Rails 3应用程序.

该应用程序允许匿名(未注册)用户访问某些应用程序,并允许注册用户访问其他部分.

应用程序(瑜伽锻炼应用程序)的一个方面是用户可以通过将瑜伽姿势串联起来创建瑜伽序列,然后他们可以在视频播放器中播放它们.

我目前已为注册用户提供所有功能,但现在希望允许匿名用户能够创建序列并播放它,但要"保存"它(即能够在任何后续会话中再次使用它) ,他们需要注册.

目前,这需要实际创建一个属于用户的Sequence模型实例(简化如下)

class Sequence < ActiveRecord::Base

  validates_presence_of :name
  validate :status_must_be_private_if_user_nil

  # Associations
  has_many :ordered_asana_sequences, :class_name => "OrderedAsanaSequence", :order => 'position ASC', :dependent => :destroy
  has_many :asanas, :through => :ordered_asana_sequences

  belongs_to :user


  def status_must_be_private_if_user_nil
  errors.add(:status, "must be private is user is nil") if
    user == nil and status != :private
  end
end
Run Code Online (Sandbox Code Playgroud)

但是,当然,匿名用户没有用户模型.

我有点像Hackces属于用户的东西,但它不是强制性的(user_id可以是nil,如上所示),并且通过CanCan保护编辑的能力:

class Ability
    {snip}
    # A guest can play with creating sequences
    can :create, [Sequence]
    # A guest can edit/update their own Sequences
    can :update, [Sequence], :user_id => user.id
end
Run Code Online (Sandbox Code Playgroud)

但是,这意味着任何匿名用户(user_id = nil)都可以编辑任何其他匿名用户的序列.其中,我猜不是世界末日,但我希望它更安全.

以下是我想到的潜在方式:

'注册'匿名用户

  • 如果访客用户进行序列编制,则生成电子邮件和密码并"注册"此"访客"用户.然后将新序列模型分配给此新用户.如果用户决定注册真实,只需使用新的电子邮件和密码更新现有用户记录.
  • 优点:对现有应用程序的更改很少 - 只需要在"注册"过程中处理它.
  • 缺点:最终可能会有大量死用户帐户,我需要在之后进行清理

不要持久化序列,而是将其序列化并将其存储在会话中

  • 如果访客用户去创建序列,当他们想要"保存"它时,将其拍摄到序列化模型的控制器方法并将其存储在会话中.然后,序列播放器,我猜,序列编辑器可以选择从会话而不是数据存储中拉出它
  • 优点:不为guest虚拟机创建用户帐户,因此无需清理.无需处理修改功能,因为访客不会从数据存储中获取模型,而是从他们的会话中获取模型.
  • 缺点:看似hacky.在应用程序中需要很多接触点来确定从哪里获取序列.错误的可能性更高

找出将一个Sequence分配给guest用户的其他方法,然后将user_id设为nil

  • 优点:它将是辉煌的
  • 缺点:不知道该怎么做.

我希望有一些我在Devise中没有看到的东西(也许是可邀请的?),这些东西比我自己更清洁.

或者,是否有人对此问题有任何建议?这似乎是一个相对常见的要求,但无法发掘任何指导.

谢谢!

And*_*rew 4

Ryan 在对 CanCan 的介绍中提出了以下建议:

在内存中为站点上的来宾用户创建一个新用户对象,但不保存它。这样,所有需要与用户关联的功能仍然可以工作,但它们不会保存。

请参阅此处的 Railscast:http://railscasts.com/episodes/192-authorization-with-cancan

Ryan 的代码示例是:

class Ability  
  include CanCan::Ability  

  def initialize(user)  
    user ||= User.new # This initializer is creating your memory-only guest users

    if user.role? :admin  
      can :manage, :all  
    else  
      can :read, :all  
      can :create, Comment  
      can :update, Comment do |comment|  
        comment.try(:user) == user || user.role?(:moderator)  
      end  
      if user.role?(:author)  
        can :create, Article  
        can :update, Article do |article|  
          article.try(:user) == user  
        end  
      end  
    end  
  end  
end
Run Code Online (Sandbox Code Playgroud)

因此,在您的应用程序中,如果您使用此方法,那么在您的视图中,您可以检查current_user.new_record?,并为注册用户与访客呈现不同的“保存”按钮。

您可以通过在序列创建页面上提供隐藏的帐户注册表单来使这变得非常简单(避免将其存储在会话等中)。然后,只需让客人的“保存”按钮显示帐户创建表单,当他们提交该表单时,他们就会同时提交用户注册和序列创建。

那么你所有的 Sequences#create 操作需要做的就是:

...
current_user.update_attributes(params[:user]) if current_user.new_record?

if current_user.sequences.create(params[:sequence])
   redirect_to ...
else
   render ...
end
...
Run Code Online (Sandbox Code Playgroud)

您需要将其转化为工作代码,但我相信基本想法是可行的。

祝你好运!