简体   繁体   English

用Devise跟踪多个注册路径

[英]Rails multiple registration paths with Devise

I'm using devise in rails, and I'm trying to create a second registration path, the default registration path for users (which works perfectly), and a second registration path whereby a user registers and creates a project in a single action as a "Getting Started" action (Think Freelancer.com or any marketplace whereby non-users can register and create their first project in one action). 我在Rails中使用devise,并尝试创建第二个注册路径,用户的默认注册路径(完美运行)和第二个注册路径,用户可以通过以下操作在一个动作中注册并创建项目: “入门”操作(想想Freelancer.com或非用户可以通过一个操作注册并创建他们的第一个项目的任何市场)。

I've gone through so many threads but they all seem to want to replace the existing registration action. 我经历了很多线程,但是它们似乎都想替换现有的注册操作。 I want to keep the existing registration action and either add a getting_started_new and getting_started_create actions to the existing User::Registration controller, or create a new GettingStarted Controller with methods for new and create that would then allow the nested form (for a user and their new project). 我想保留现有的注册操作,并向现有的User::Registration控制器添加getting_started_newgetting_started_create动作,或者使用newcreate方法创建一个新的GettingStarted Controller,然后允许嵌套表格(针对用户及其新项目)。

My latest iteration looks something like this: 我最新的迭代看起来像这样:

routes.rb routes.rb

devise_for :users

resources :users do
  resources :projects
end

devise_scope :user do
  get "getting_started" =>'getting_started#new'
  post "getting_started" =>'getting_started#create'
end

getting_started_controller.rb Getting_started_controller.rb

class GettingStartedController < Devise::RegistrationsController

def new
  @user = User.new
  @user.projects.build  
end

def create
  @user = User.new(getting_started_params)
  redirect_to root, notice: "Done"
end

private
  def getting_started_params
    params.require(:user).permit(:first_name, :last_name, :phone, :password, :email, projects_attributes: [:user_id, :project_type_id, :name, :industry_id, :description, :budget_id, :project_status_id, feature_ids:[], addon_ids:[]])
  end

end

But when I try and actually submit the form, it loads the get action from the new controller, and the post action from the devise registration controller. 但是,当我尝试并实际提交表单时,它将从新控制器加载get操作,并从devise注册控制器加载post操作。

Started GET "/getting_started" for ::1 at 2016-10-17 09:15:58 +0200
Processing by GettingStartedController#new as HTML
Rendering getting_started/new.html.erb within layouts/application
Project_type Load (0.5ms)  SELECT "project_types".* FROM "project_types"
Industry Load (1.1ms)  SELECT "industries".* FROM "industries" ORDER BY "industries"."name" ASC
Feature Load (0.5ms)  SELECT "features".* FROM "features" ORDER BY "features"."name" ASC
Addon Load (0.4ms)  SELECT "addons".* FROM "addons"
Budget Load (0.4ms)  SELECT "budgets".* FROM "budgets"
Rendered getting_started/new.html.erb within layouts/application (32.9ms)
Rendered layouts/_header.html.erb (1.9ms)
Rendered layouts/_footer.html.erb (0.7ms)
Completed 200 OK in 97ms (Views: 86.4ms | ActiveRecord: 2.9ms)


Started POST "/users" for ::1 at 2016-10-17 09:16:54 +0200
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hYrC/15zIF3DzPvhpFQH6LVS9H8XbhfHY1aRkgc2iX6Mdfvz33/O4p72XTpmY4X8E6B+dGfOmjZw7IoizvYwSA==", "user"=>{"first_name"=>"John", "last_name"=>"Smith", "phone"=>"0340239402309", "email"=>"test@example.com", "password"=>"[FILTERED]", "project"=>{"name"=>"This is a test", "description"=>"Tester Description", "feature_ids"=>[""], "addon_ids"=>[""]}}, "project"=>{"project_type_id"=>"4", "industry_id"=>"2", "budget_id"=>"1"}, "commit"=>"Create account"}
Unpermitted parameter: project
(0.1ms)  BEGIN
SQL (1.5ms)  INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at", "first_name", "last_name", "phone") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["email", "test@example.com"], ["encrypted_password", "$2a$11$VEVjSrnc5Y5c8ofXvNmlMOHrS.v4tQuBoKMLdHaSOA2S6fiVIHfE."], ["created_at", 2016-10-17 07:16:55 UTC], ["updated_at", 2016-10-17 07:16:55 UTC], ["first_name", "John"], ["last_name", "Smith"], ["phone", "0340239402309"]]
 (139.1ms)  COMMIT
 (0.1ms)  BEGIN
 SQL (0.4ms)  UPDATE "users" SET "sign_in_count" = $1, "current_sign_in_at" = $2, "last_sign_in_at" = $3, "current_sign_in_ip" = $4, "last_sign_in_ip" = $5, "updated_at" = $6 WHERE "users"."id" = $7  [["sign_in_count", 1], ["current_sign_in_at", 2016-10-17 07:16:55 UTC], ["last_sign_in_at", 2016-10-17 07:16:55 UTC], ["current_sign_in_ip", "::1/128"], ["last_sign_in_ip", "::1/128"], ["updated_at", 2016-10-17 07:16:55 UTC], ["id", 17]]
 (0.3ms)  COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 319ms (ActiveRecord: 141.7ms)

I realise that devise does a whole bunch of other stuff besides simply recording the user data, so it may be better to rather move these actions to the Devise User::RegistrationController , and then tweak the accepted params. 我意识到除了简单地记录用户数据外,devise还完成了很多其他工作,因此最好将这些动作移至Devise User::RegistrationController ,然后调整可接受的参数。 But how do you override Devise so that it doesn't auto use the devise create method the second you click the submit button, and would instead use a getting_started_create action? 但是,如何覆盖Devise,以便它不会在您单击“提交”按钮的第二秒内自动使用devise create方法,而是使用getting_started_create操作?

First off getting started is a pretty horrible name for a controller since it is not a noun. 首先, getting started是一个非常糟糕的控制器名称,因为它不是名词。 You can't say a getting started . 你不能说一个入门 So lets change it to QuickstartsController . 因此,让我们将其更改为QuickstartsController

Lets setup the routes for this resource: 让我们为此资源设置路由:

Rails.application.routes.draw do

  # These are your "normal" devise routes
  devise_for :users

  # This is the mapping for the "quickstart" routes
  devise_for :quickstarts,
    class_name: 'User',
    only: [],
    controllers: { registrations: 'quickstarts' }

  # These are the actual routes for quickstarts
  devise_scope :quickstart do
    get   "/quickstarts/new", to: "quickstarts#new", as: :new_quickstart
    post  "/quickstarts",    to: "quickstarts#create", as: :quickstarts
  end
end

Whenever you are overriding a library controller it is important to take some time to study how the class you are superclassing actually works. 每当您重写库控制器时,重要的是花一些时间研究您超类的类是如何实际工作的。

If you look at the Devise controllers almost all the actions have a line like: 如果您看一下Devise控制器,几乎所有操作都具有如下一行:

yield resource if block_given?

Which lets you tap into the flow of the original implementation by calling super with a block: 通过调用带有块的super ,您可以利用它来实现原始实现的流程:

class QuickstartsController < Devise::RegistrationsController

  # GET /quickstarts/new
  def new
    # This block is passed to the super class implementation:
    super do |resource|
      resource.projects.build
    end
  end

  # POST /quickstarts
  def create
    # You can pass a block here too if you want.
    super
  end

  private

  # This should redirect to the newly created project
  def after_sign_up_path_for(resource)
    polymorphic_path( resource.projects.last )
  end

  # This is the method Devise devise calls for the params.
  def sign_up_params
    # Don't write your params sanitiation on one line! Its not cool.
    params.require(:user)
          .permit(
              :first_name, :last_name, :phone, :password, :email,
              projects_attributes: [
                 :user_id, :project_type_id, :name,
                 :industry_id, :description, :budget_id,
                 :project_status_id,
                 feature_ids:[],
                 addon_ids:[]
              ]
          )
  end
end

But how do you override Devise so that it doesn't auto use the devise create method the second you click the submit button, and would instead use a getting_started_create action? 但是,如何覆盖Devise,以便它不会在您单击“提交”按钮的第二秒内自动使用devise创建方法,而是使用geting_started_create操作?

Point the form to the correct controller - by passing the url option to form_for . 将表单指向正确的控制器-通过将url选项传递给form_for

app/views/quickstarts/new.html.erb: app / views / quickstarts / new.html.erb:

<h2>Getting Started</h2>

<%= form_for( resource, as: :user, url: quickstarts_path ) do |f| %>
  <%= devise_error_messages! %>

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

  <fieldset>
    <legend>Project</legend>
    <% f.fields_for :projects do |pf| %>
      <%# ... %>
    <% end %>
  </fieldset>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM