我在rails 5.2中使用devise,并尝试在nested fields
中添加一些user signup
。我正在尝试创建一个名为second registration path
的quickstarts
,用户可以在一个操作中注册并创建一个患者。我遵循了此线程Rails multiple registration paths with Devise
问题是nested fields
没有显示在注册页面上,并且我无法弄清楚为什么它不起作用,所以将不胜感激。
routes.rb
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users, controllers: {:registrations => "users/registrations"
}
resources :registration_steps
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'pages#index'
get 'about', to: 'pages#about'
get 'team', to: 'pages#team'
get 'faqs', to: 'pages#faqs'
get 'faqspractitioners', to: 'pages#faqspractitioners'
get 'faqsusers', to: 'pages#faqsusers'
get 'login', to: 'pages#login'
get 'signup', to: 'pages#signup'
get 'search', to: 'pages#search'
get 'practitioner', to: 'pages#practitioner'
resources :clinics do
resources :practitioners
end
devise_scope :user do
scope module: :users do
resources :registrations, only: [] do
member do
delete :delete_image_attachment
end
end
end
end
# This is the mapping for the "quickstarts" 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
user.rb
class User < ApplicationRecord
has_one :patient, dependent: :destroy
accepts_nested_attributes_for :patient, reject_if: :all_blank, allow_destroy: true
end
Patient.rb
class Patient < ApplicationRecord
belongs_to :user
end
quickstarts_controller.rb
class QuickstartsController < Devise::RegistrationsController
# GET /quickstarts/new
def new
# This block is passed to the super class implementation:
super do |resource|
resource.build_patient
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)
root_path
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(:id, :first_name, :last_name, :email, :password, :password_confirmation, :phone,
patient_attributes: [
:user_id, :id, :patient_first_name,
:patient_last_name, :patient_phone, :patient_mail,
:patient_address, :patient_zip_code, :patient_municipality,
:patient_city
]
)
end
end
new.html.erb
<h2>Getting Started</h2>
<%= simple_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>
<legend>Patient</legend>
<% f.simple_fields_for :patient do |f| %>
<div class="field text-field">
<%= f.input_field :patient_first_name, autofocus: true, autocomplete: "Klinikkens navn", placeholder: "Klinikkens navn" %>
</div>
<div class="field text-field">
<%= f.input_field :patient_last_name, autofocus: true, autocomplete: "Adresse", placeholder: "Adresse" %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
patients_controller.rb
class PatientsController < ApplicationController
before_action :set_patient, only: [:show, :edit, :update, :destroy]
def index
@patient = Patient.all
@user = current_user
end
def show
@patient = Patient.find(params[:id])
@user = current_user
end
def edit
@patient = Patient.find(params[:id])
@user = current_user
end
def new
@resource.patients.build
end
def create
@patient = @resource.patients.new(patient_params)
respond_to do |format|
if @patient.save
format.html { redirect_to @patient, notice: 'patient was successfully created.' }
format.json { render :show, status: :created, location: @patient }
else
format.html { render :new }
format.json { render json: @patient.errors, status: :unprocessable_entity }
end
end
end
def update
if @patient.update(patient_params)
redirect_to root_path
else
render :edit
end
end
def destroy
@patient.destroy
respond_to do |format|
format.html { redirect_to patients_url, notice: 'patient was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_patient
@patient = Patient.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
params.require(:patient).permit(:user_id, :id, :patient_first_name, :patient_last_name, :patient_phone, :patient_mail, :patient_address, :patient_zip_code, :patient_municipality, :patient_city)
end
end
这是错误的一般方法。 Devise::RegistrationsController
是从头开始构建的,可以处理用户注册自己的情况。如果您正在尝试注册其他用户,那么您将不会从中获得任何帮助,因为您只是在与一个非常复杂的野兽战斗,以使其执行其并非为之准备的任务。
您实际上不必注册其他用户。您只需创建它们。
您正在做的实际上是Devise::Invitable
设计的目的。它使您可以通过“邀请”其他用户记录来创建其他用户记录,然后发送电子邮件以使他们可以通过令牌声明其帐户。这样可以避免您被黑客入侵的解决方案带来的巨大问题,即创建记录的用户必须了解新患者密码,并以某种方式将该知识传递给他们正在注册的患者。