[英]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_new
和getting_started_create
动作,或者使用new
和create
方法创建一个新的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.