[英]Create associated model at the same time as Devise model
I would like to create a Contractor
at the same time I am creating a User
when signing up with Devise
and then, associate the newly created Contractor
to the freshly created User
. 我想在与
Devise
注册时创建User
的同时创建一个Contractor
,然后将新创建的Contractor
与新创建的User
关联。 Any ideas how to do it? 有什么想法怎么做? (as I have no access to the controller creating the user with Devise if I'm right) Should I use build, and how?
(因为我没错,所以我无法访问使用Devise创建用户的控制器)我应该使用build吗?如何使用?
I have read Profile model for Devise users? 我已经阅读了Devise用户的个人资料模型吗? , Creating Profile for Devise users , How to create a profile for devise user?
, 为Devise用户 创建配置文件 , 如何 为devise用户 创建配置文件? and tried several things but I am still stuck.
尝试了几件事,但我仍然陷于困境。
Here is what I have: 这是我所拥有的:
view - devise/registrations/new.html.erb 视图-devise / registrations / new.html.erb
<% @title = "Sign up" %>
<div id="main" class="devise-1">
<div class="container-fluid">
<div class="row">
<header class="text-center">
<h1><%=app_name%></h1>
<p class="p-0 m-0 text-uppercase">Sign Up</p>
</header>
</div>
<div class="row mt-5">
<div class="col-12 col-md-6 mr-auto ml-auto">
<div class="card">
<div class="card-body">
<div class="container">
<% resource.build_contractor %>
<%= form_for resource, as: resource_name, url: registration_path(resource_name),
html: { class: "form-horizontal", novalidate: true } do |f| %>
<%= f.error_notification %>
<div class="form_group.row">
<%= f.fields_for :contractor, class: "row" do |contractor_form| %>
<%= contractor_form.label :name, class: "form-label" %>
<%= contractor_form.text_field :name, class: "form-control" %>
<% end %>
</div>
<%= f.form_group :email, class: "row" do |f| %>
<%= f.label :email, class: "form-label" %>
<%= f.email_field :email, autofocus: true, class: "form-control" %>
<%= f.error_messages %>
<% end %>
<%= f.form_group :password, class: "row" do |f| %>
<%= f.label :password, class: "form-label" %>
<%= f.password_field :password, class: "form-control" %>
<%= f.error_messages %>
<% end %>
<%= f.form_group :password_confirmation, class: "row" do |f| %>
<%= f.label :password_confirmation, class: "form-label" %>
<%= f.password_field :password_confirmation, class: "form-control" %>
<%= f.error_messages %>
<% end %>
<div class="row d-flex align-items-center mt-5">
<%= link_to "Log in?", new_session_path(resource_name) %>
<%= f.submit "Sign up", class: "btn btn-primary ml-auto" %>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
</div>
model - user.rb 模型-user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one :contractor
accepts_nested_attributes_for :contractor
has_many :clients, through: :contractor
has_many :construction_projects, through: :contractor
# DOES WORK TO CREATE A NEW CONTRACTOR WHEN SIGNING UP BUT CREATES EMPTY CONTRACTORS
# PER CONTRACTOR OF THE SEED, NEED TO FIND ANOTHER SOLUTION
# after_create :create_contractor
# Model validations
validates_associated :clients
validates_associated :construction_projects
validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP }
def option_projects
unless self.contractor.nil?
projects = self.contractor.construction_projects.map{ |cp| [cp.name, cp.id] }
projects << ["Add a new project", "Add a new project"]
projects
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :remember_me, :user_attributes)
end
# DOES WORK TO CREATE A NEW CONTRACTOR WHEN SIGNING UP BUT CREATES EMPTY CONTRACTORS
# FOR CONTRACTORS OF THE SEED, NEED TO FIND ANOTHER SOLUTION
# def create_contractor
# @contractor = Contractor.create(user: self)
# end
end
model - contractor.rb 模型-Contractor.rb
class Contractor < ApplicationRecord
belongs_to :user
has_many :workgroup_libraries
has_many :construction_projects, dependent: :destroy
has_many :clients, dependent: :destroy
has_many :documents, through: :construction_projects, dependent: :destroy
has_many :resources
has_many :resource_quantities, through: :resources
has_many :workgroups
mount_uploader :logo, LogoUploader
end
Thanks for your help! 谢谢你的帮助!
You definitely don't want to build the contractor in your view file. 您绝对不希望在您的视图文件中构建承包商。
You can use an ActiveRecord::Callbacks
https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html on your User
model 您可以在
User
模型上使用ActiveRecord::Callbacks
https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
I'd suggest using after_create
: 我建议使用
after_create
:
after_create :generate_contractor
private
def generate_contractor
# Using the bang method will make sure to raise an error if
# creating the contractor fails for whatever reason
contractor.create!(...attributes)
end
Alternatively, if you want to perform this action in your controller you can do something like this: Override devise registrations controller 另外,如果您想在控制器中执行此操作,则可以执行以下操作: 覆盖devise registrations控制器
You can override the default behaviour by creating an after_sign_in_path_for
method in your ApplicationController
and have it return the path for the page you want ( doc ) 您可以通过在
ApplicationController
创建after_sign_in_path_for
方法来覆盖默认行为, after_sign_in_path_for
方法返回所需页面的路径( doc )
def after_sign_in_path_for(resource_or_scope)
@contractor = Contractor.create(contractor_params)
current_user
end
Provide contractor_params
method in ApplicationController to sanitise contractor params. 在ApplicationController中提供
contractor_params
方法以清理承包商参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.