用Devise跟踪多个注册路径 [英] Rails multiple registration paths with Devise
问题描述
我在Rails中使用devise,并且尝试创建第二个注册路径,用户的默认注册路径(完美运行)以及第二个注册路径,用户可以通过该第二个注册路径在单个动作作为入门"动作(想想Freelancer.com或非用户可以通过一个动作注册和创建他们的第一个项目的任何市场).
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).
我经历了很多线程,但是它们似乎都想替换现有的注册操作.我想保留现有的注册操作,并向现有的User::Registration
控制器添加getting_started_new
和getting_started_create
动作,或者使用new
和create
的方法创建一个新的GettingStarted
控制器,该方法随后将允许嵌套表单(针对用户及其新项目).
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).
我最新的迭代看起来像这样:
My latest iteration looks something like this:
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
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
但是当我尝试实际提交表单时,它会从新控制器加载get
动作,并从devise注册控制器加载post
动作.
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.
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)
我认识到,除简单地记录用户数据外,devise还完成了很多其他工作,因此最好将这些动作移至Devise User::RegistrationController
,然后调整可接受的参数.但是,如何覆盖Devise,以便它不会在您单击提交"按钮的第二秒内自动使用devise create
方法,而是使用getting_started_create
操作?
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. 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?
推荐答案
首先,getting started
对于控制器来说是一个非常可怕的名称,因为它不是名词.您不能说入门.因此,将其更改为 QuickstartsController .
First off getting started
is a pretty horrible name for a controller since it is not a noun. You can't say a getting started. So lets change it to 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.
如果您看一下Devise控制器,几乎所有动作的行都像这样:
If you look at the Devise controllers almost all the actions have a line like:
yield resource if block_given?
您可以通过使用一个块调用super
来利用原始实现的流程:
Which lets you tap into the flow of the original implementation by calling super
with a block:
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
但是您如何覆盖Devise,以便它不会自动使用devise 创建方法,第二次单击提交按钮,然后 而是使用Getting_started_create操作?
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?
通过将url
选项传递给form_for
,将表单指向正确的控制器.
Point the form to the correct controller - by passing the url
option to form_for
.
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 %>
这篇关于用Devise跟踪多个注册路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!