All threads / How to make rails associations work

Ask A Question

Notifications

You’re not receiving notifications from this thread.

How to make rails associations work

Kasper Valentin asked in Rails

I have this set up, but noting gets saved to the db when I try to save a practitioner.
The tables are users, clinics and practitioners. The user should be able to create multiple clinics and each clinic should be able to add multiple practitioners to the specific clinic.

I can't seem to figure out, what I should do to make it work. I can see it says that user.rb is missing practitioners_attribute
but practitioners is associated to clinic and not user, that's why I've put it in clinic.rb, and even if I put accepts_nested_attributes_for :practitioners, reject_if: :all_blank, allow_destroy: true in user.rb it still doesn't work.

I get this error:
ActiveModel::UnknownAttributeError in RegistrationStepsController#update
unknown attribute 'practitioners_attributes' for User.
@user = current_user
# Change @user.attributes(user_params) by @user.update_attributes(user_params)
@user.update_attributes(user_params)
render_wizard @user
end

This is how I have tried to make it work so far:

User has many clinics

clinics belongs to user

clinics has many practitioners

practitioners belongs to clinics

I’ve added a foreign user key to connect clinics table with users table

I’ve added a foreign clinic key to connect practitioners table with clinics table

user.rb

class User < ApplicationRecord        
has_many :clinics, dependent: :destroy
accepts_nested_attributes_for :clinics, reject_if: :all_blank, allow_destroy: true
end

clinic.rb

class Clinic < ApplicationRecord
belongs_to :user
has_many :practitioners
    accepts_nested_attributes_for :practitioners, reject_if: :all_blank, allow_destroy: true
end

practitioner.rb

class Practitioner < ApplicationRecord
belongs_to: clinic
end

add clinics foreign key to practitioners

class AddClinicReferenceToPratitioners < ActiveRecord::Migration[5.2]
def change
add_reference :practitioners, :clinic, foreign_key: true
end
end

add users foreign key to clinics

class AddUserReferenceToClinics < ActiveRecord::Migration[5.2]
def change
add_reference :clinics, :user, foreign_key: true
end
end

practitioners_general.html.rb

<div class="content">
<div class="content practitioner">
<h2 class="page-title">Generel information</h2>

<%= simple_form_for @user, url: wizard_path, method: :put do |f| %>

<%= f.simple_fields_for(:practitioners) do |p| %>
<%= render 'practitioners/practitioners_fields', :f => p %>
<% end %>
</div>
<div class="submit-container">
<%= f.submit "Gem", :class => 'btn blue' %>

</div>
<% end %>

</div>

practitioners_fields.html.erb

<div class="nested-fields">
  <div class="basic-section">

    <div class="info-group">
      <div class="field-group">
        <div class="field text-field">

          <%= f.input_field :practitioner_first_name, required: true, autofocus: true, autocomplete: "Fornavn", placeholder: "Fornavn" %>
        </div>
        <div class="field text-field">
          <%= f.input_field :practitioner_last_name, required: true, autofocus: true, autocomplete: "Efternavn", placeholder: "Efternavn" %>
        </div>
      </div>

    </div>
  </div>
  <div class="about-section">
    <div class="field text-field">
      <%= f.input_field :practitioner_description, :as => :text, :input_html => { 'rows' => 5}, autofocus: true, autocomplete: "Beskrivelse af behandler", placeholder: "Beskrivelse af behandler" %>
    </div>

  </div>
  <div class="field-group contact-section">
    <div class="field text-field">
      <%= f.input_field :practitioner_mail, input_html: { autocomplete: 'email' }, autofocus: true, placeholder: "E-mail" %>
    </div>
    <div class="field text-field">
      <%= f.input_field :practitioner_phone, autofocus: true, autocomplete: "Tlf. nr.", placeholder: "Tlf. nr." %>
    </div>
    <div class="field text-field">
      <%= f.input_field :practitioner_website, required: false, autofocus: true, autocomplete: "Hjemmeside", placeholder: "Hjemmeside" %>
    </div>
  </div>

</div>

registration_steps_controller.rb

class RegistrationStepsController < ApplicationController

    include Wicked::Wizard
    steps :company_general, :company_images, :practitioners_general, :practitioners_professions, :practitioners_educations

    def create
      @practitioner = Practitioner.new(params[:practitioners])
      @practitioner.save
    end

    def show
     @user = current_user    
    render_wizard 
    end

    def update
      @user = current_user
      # Change @user.attributes(user_params) by @user.update_attributes(user_params)
      @user.update_attributes(user_params)
      render_wizard @user
    end



private
def user_params
  params.require(:user)
  .permit(:gender, :first_name, :last_name, :email, :password, :password_confirmation, :phone, 
    :clinic_logo, 
    :practitioner_image,
    :public_health_insurance, 
    clinic_images: [], 
    profession_ids: [], 
    speciality_ids: [], 
    services_attributes: [:id, :description, :name, :duration, :price, :_destroy], 
    educations_attributes: [:id, :name, :place, :year, :_destroy],
    membership_ids: [],
    awards_attributes: [:id, :name, :year, :_destroy],
    clinics_attributes: [:id, :clinic_logo, :clinic_name, :clinic_address, :clinic_zip_code, :clinic_municipality, :clinic_about, :clinic_mail, :clinic_phone, :clinic_website, :clinic_city, :_destroy],
    practitioners_attributes: [:id, :practitioner_first_name, :practitioner_last_name, :practitioner_description, :practitioner_mail, :practitioner_phone, :practitioner_website, :_destroy])

end

end

ApplicationController.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

    before_action :authenticate_user!, :configure_permitted_parameters, if: :devise_controller?

    protected

    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: 
        [:gender, :first_name, :last_name, :email, :password, :password_confirmation, :phone, 
        :clinic_logo, 
        :practitioner_image,
        :public_health_insurance, 
        clinic_images: [], 
        profession_ids: [], 
        speciality_ids: [], 
        services_attributes: [:id, :description, :name, :duration, :price, :_destroy], 
        educations_attributes: [:id, :name, :place, :year, :_destroy],
        membership_ids: [],
        awards_attributes: [:id, :name, :year, :_destroy],
        clinics_attributes: [:id, :clinic_logo, :clinic_name, :clinic_address, :clinic_zip_code, :clinic_municipality, :clinic_about, :clinic_mail, :clinic_phone, :clinic_website, :clinic_city, :_destroy],
        practitioners_attributes: [:id, :practitioner_first_name, :practitioner_last_name, :practitioner_description, :practitioner_mail, :practitioner_phone, :practitioner_website, :_destroy]])


        devise_parameter_sanitizer.permit(:account_update, keys: 
          [:gender, :first_name, :last_name, :email, :password, :password_confirmation, :phone, 
            :clinic_logo, 
            :practitioner_image, 
            :public_health_insurance, 
            clinic_images: [], 
            profession_ids: [], 
            speciality_ids: [], 
            services_attributes: [:id, :description, :name, :duration, :price, :_destroy], 
            educations_attributes: [:id, :name, :place, :year, :_destroy],
            membership_ids: [],
            awards_attributes: [:id, :name, :year, :_destroy],
            clinics_attributes: [:id, :clinic_logo, :clinic_name, :clinic_address, :clinic_zip_code, :clinic_municipality, :clinic_about, :clinic_mail, :clinic_phone, :clinic_website, :clinic_city, :_destroy],
            practitioners_attributes: [:id, :practitioner_first_name, :practitioner_last_name, :practitioner_description, :practitioner_mail, :practitioner_phone, :practitioner_website, :_destroy]])



    end


    def after_sign_in_path_for(resource)
      rails_admin_path
    end

  end

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 "userprofiles/user_info" => "userprofiles#user_info", as: "user_info"
  get "userprofiles/clinic_info" => "userprofiles#clinic_info", as: "clinic_info"
  get "userprofiles/practitioner_info" => "userprofiles#practitioner_info", as: "practitioner_info"


  patch "userprofiles/user_info" => "userprofiles#update"
  patch "userprofiles/clinic_info" => "userprofiles#update"
  patch "userprofiles/practitioner_info" => "userprofiles#update"


  devise_scope :user do 
    scope module: :users do
      resources :registrations, only: [] do
        member do
          delete :delete_image_attachment
        end
      end
    end
  end

end

I fixed it by changing the params from

    clinics_attributes: [:id, :clinic_logo, :clinic_name, :clinic_address, :clinic_zip_code, :clinic_municipality, :clinic_about, :clinic_mail, :clinic_phone, :clinic_website, :clinic_city, :_destroy],
        practitioners_attributes: [:id, :practitioner_first_name, :practitioner_last_name, :practitioner_description, :practitioner_mail, :practitioner_phone, :practitioner_website, :_destroy])

end

to

clinics_attributes: [:id, :clinic_logo, :clinic_name, :clinic_address, :clinic_zip_code, :clinic_municipality, :clinic_about, :clinic_mail, :clinic_phone, :clinic_website, :clinic_city, :_destroy,
    practitioners_attributes: [:id, :practitioner_first_name, :practitioner_last_name, :practitioner_description, :practitioner_mail, :practitioner_phone, :practitioner_website, :_destroy]])

end
Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 34,885+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

    © 2020 GoRails, LLC. All rights reserved.