首页 > 解决方案 > 与设计模型同时创建关联模型

问题描述

我想在注册Contractor时创建一个,然后将新创建的与新创建的关联起来。任何想法如何做到这一点?(因为如果我是对的,我无法访问使用 Devise 创建用户的控制器)我应该使用构建,以及如何使用?UserDeviseContractorUser

我已阅读设计用户的配置文件模型?,为设计用户创建配置文件,如何为设计用户创建配置文件?并尝试了几件事,但我仍然卡住了。

这是我所拥有的:

查看 - 设计/注册/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>

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

模型 - 承包商.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

谢谢你的帮助!

标签: ruby-on-railsdevise

解决方案


您绝对不想在视图文件中构建承包商。

您可以在模型上使用ActiveRecord::Callbacks https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.htmlUser

我建议使用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

或者,如果您想在控制器中执行此操作,您可以执行以下操作:覆盖设计注册控制器


推荐阅读