user2570506
user2570506

Reputation: 45

Nested attributes and creating an instance of two separate models in one controller (parent controller)

My app has two models, Tenant (apartment) and User (devise). I've made it so attributes for both models can be set through one form, using nested attributes. The problem is only an instance of Tenant is being created when the form is submitted, not User.

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

  belongs_to :tenant
  # attr_accessible :tenant
end

tenant.rb

class Tenant < ApplicationRecord
  after_create :create_tenant

  has_many :users
  accepts_nested_attributes_for :users

  private

    def create_tenant
      Apartment::Tenant.create(subdomain)
    end
end

tenants_controller (not entire file)

def new
    @tenant = Tenant.new
    @user = User.new
    render layout: false
end

def create
    @tenant = Tenant.new(tenant_params)
    @tenant.update_attribute :subdomain, @tenant.company.downcase
    respond_to do |format|
      if @tenant.save 
        format.html { redirect_to "http://#{@tenant.subdomain}.lvh.me:3000/users/sign_in", notice: 'Domain was successfully created.' }
        #format.html { redirect_to new_user_registration_path, notice: 'Tenant was successfully created.' }
        @user = @tenant.users.create(params[:user])
        format.json { render :show, status: :created, location: @tenant }
      else
        format.html { render :new }
        format.json { render json: @tenant.errors, status: :unprocessable_entity }
      end
    end
  end


private

def tenant_params
      params.require(:tenant).permit(:company, :subdomain,
        user_attributes: [ :email, :first_name, :last_name, :password, :password_confirmation ])
end

tenants/new.html.erb (actually _form.html.erb but its rendered in tenants/new)

<%= form_with(model: tenant, local: true) do |form| %>
  <% if tenant.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(tenant.errors.count, "error") %> prohibited this tenant from being saved:</h2>

      <ul>
      <% tenant.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <%= form.fields_for :user do |f| %>
    <div class="field">
      <%= f.label :first_name %>
      <%= f.text_field :first_name %>
    </div>

    <div class="field">
      <%= f.label :last_name %>
      <%= f.text_field :last_name %>
    </div>

    <div class="field">
      <%= f.label :email %>
      <%= f.text_field :email %>
    </div>

    <div class="field">
      <%= form.label :company %>
      <%= form.text_field :company %>
    </div>

    <%= f.label :password %>
    <%= f.password_field :password %>

    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation %>
  <% end %>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

The error in the CLI is unpermitted parameter :user but the attributes have the proper values from submitting the form:

From CLI - Tenant Create:

Processing by TenantsController#create as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"a6YvYm/RcMI8phxTmOPD4Vi43ooqE
v0piV5tGvucMK4f7FZSWPmlAGcme+f6Wq+S26+m9ni6fmGBW6t6wZ/yFw==", "tenant"=>{"user"=
>{"first_name"=>"John", "last_name"=>"Smith", "email"=>"[email protected]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "company"=>"Pepsi"},
"commit"=>"Create Tenant"}
Unpermitted parameter: :user

Upvotes: 0

Views: 676

Answers (1)

Kamal Pandey
Kamal Pandey

Reputation: 1596

You are permitting user_attributes but getting user as params so,

update

<%= form.fields_for :user do |f| %>

with

<%= form.fields_for :users do |f| %>

also update

 params.require(:tenant).permit(:company, :subdomain,
            user_attributes: [ :email, :first_name, :last_name, :password, :password_confirmation ])

with

params.require(:tenant).permit(:company, :subdomain,
            user_attributes: [:id, :email, :first_name, :last_name, :password, :password_confirmation ])

so that new record will not be created during update.

Upvotes: 1

Related Questions