【问题标题】:Create Devise User From A Different Form and Controller - Ruby on Rails从不同的表单和控制器创建设计用户 - Ruby on Rails
【发布时间】:2016-09-17 07:11:01
【问题描述】:

我们有两个模型,一个“设计用户”和一个“影响者”。影响者是用户,因此它必须有一个用户(从数据库的角度来看)。一个用户可以是多个其他事物。因此,我们希望能够在不成为影响者的情况下注册用户,并且我们希望在用户想要注册为影响者时注册用户。

我有这样的表格:

influencers/new.html.erb

<%= form_for @influencer do |i| %>
  <%= i.fields_for(resource, as: resource_name, url: registration_path(resource_name)) do |u| %>
    <div id="registration_fields">
      <%= render 'devise/registrations/registration_fields', f: u %>
    </div>
  <% end %>

<div class='field'>
  <%= i.label :twitter_handle %><br/>
  <%= i.text_field :twitter_handle %>
</div>

<div class='field'>
  <%= i.label :short_bio %><br/>
  <%= i.text_area :short_bio %>
</div>

/views/devise/registrations/_registration_fields

<%= devise_error_messages! %>

<div class="field">
  <%= f.label :first_name %> <br />
  <%= f.text_field :first_name %>
</div>

<div class="field">
  <%= f.label :last_name %> <br />
  <%= f.text_field :last_name %>
</div>

<div class="field">
  <%= f.label :email %><br />
  <%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
  <%= f.label :password %>
  <% if @minimum_password_length %>
  <em>(<%= @minimum_password_length %> characters minimum)</em>
  <% end %><br />
  <%= f.password_field :password, autocomplete: "off" %>
</div>

<div class="field">
  <%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>

我们已经修改了 ApplicationHelper 和“新”方法,以便它可以毫无问题地呈现此设计表单。不幸的是,我们不知道如何正确地为我们的 InfluencersController 创建“create”方法。

这是我们收到的哈希:

Parameters: {..., "influencer"=>{"user"=>{"first_name"=>"buddy", "last_name"=>"king", "email"=>"bdking@gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "twitter_handle"=>"@bdking", "short_bio"=>"None"}, "commit"=>"Join as influencer"

本质上,我们希望在处理影响者信息的同时处理用户信息。我们尝试从 InfluencersController#create 中调用 Devise::RegistrationsController.new.create 方法。然而,这也带来了自己的困难(即使有多次 hack,我们也会遇到不同的问题,例如缺少“@response”或缺少“response.env”或缺少“devise.mappings”)。

话虽如此,我们相信继承将允许我们在 create 函数中调用“super”。但是,我们不希望 InfluencersController 从 Devise::RegistrationsController 继承,因为这个控制器绝不是真正的 Devise 控制器。

我们有什么办法可以解决这个问题吗?

【问题讨论】:

    标签: ruby-on-rails model-view-controller devise


    【解决方案1】:

    我会使用 usersroles 的久经考验的真实模式。

    基本上您的User 类负责身份验证(身份),用户有许多Roles 可用于授权(权限)。

    class User < ActiveRecord::Base
      has_many :roles
    
      def has_role?(role)
        roles.where(name: role)
      end
    end
    
    class Role < ActiveRecord::Base
      belongs_to :user
      validates_uniqueness_of :name, scope: :user_id
    end
    

    因此,“影响者”实际上只是一个附加了角色(名称:“影响者”)的用户。真正的强大和灵活性在于它使得从 Web GUI 实现授予/撤销角色变得微不足道。

    而且您不必纠结于 Devise/Warden 如何处理身份验证来支持可能会变得非常混乱的多个类。

    最好的部分是Rolify gem 让设置变得非常简单。

    如果您需要设置特定端点 (influences/registrations) 来注册“影响者”,您可以简单地覆盖 Devise 控制器中的 build_resource 方法:

    class InfluencerRegistrationsController < Devise::RegistrationsController
    
      def resource_class
        User
      end
    
      def build_resource
        super
        self.resource.roles.new(name: :influencer)
      end
    end
    

    【讨论】:

    • 如果您绝对需要,您可以使用 STI 或 MTI。但就复杂性和性能而言,缺点是相当大的。
    • 什么是 STI 或 MTI?你是对的,我们正在使用用户角色,其中一个是影响者。但是,由于影响者有额外的数据成员,我们将他们设为自己的表格。我在问是否有办法让 InfluencersController 注册用户而不从 Devise::RegistrationsController 继承。
    • 单表继承和多表继承。是的,您可以从头开始创建一个注册用户的控制器 - 它与任何其他 CRUD 控制器没有太大区别,只是您调用 sign_in @user 让 Warden 在重定向之前将 id 存储在会话中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多