srisonti
srisonti

Reputation: 307

Rails 4 - Cannot modify association because of :has_many association

I'm getting the following error when I attempt to submit my nested form.

Cannot modify association 'Appointment#addresses' because the source reflection class 'Address' is associated to 'User' via :has_many

I'm not entirely sure which part of my setup is wrong. To briefly explain, I have Users that have multiple Appointments and multiple Addresses. Each Appointment can happen at a different Address, which is why I'm doing a :has_many association through user (which is correct, right?). Why am I getting this error?

Here are my models:

class User < ActiveRecord::Base
  has_many :addresses, dependent: :destroy
  has_many :appointments, dependent: :destroy
end

class Appointment < ActiveRecord::Base
  belongs_to :user
  has_many :addresses, :through => :user
  accepts_nested_attributes_for :addresses
end

class Address < ActiveRecord::Base
  belongs_to :user
end

And this is the create method from my Appointments controller:

class AppointmentsController < ApplicationController

  ...

  def create
    @appointment = current_user.appointments.build(appointment_params)
    @address = @appointment.addresses.build(appointment_params[:addresses_attributes]["0"])

    respond_to do |format|
      if @appointment.save
        format.html { redirect_to current_user, notice: 'Appointment was successfully created.' }
        format.json { render :show, status: :created, location: current_user }
      else
        format.html { render :new }
        format.json { render json: @appointment.errors, status: :unprocessable_entity }
      end
    end
  end

  ...

  private
    def appointment_params
      params.require(:appointment).permit(:appointment_date, :appointment_start_time, :appointment_end_time, :comments, :phone_number, addresses_attributes: [:user_id, :street_address, :street_address_optional, :city, :state, :zip_code, :primary])
    end

end

And finally, this is my form in my view:

<%= form_for(@appointment, :url => {:controller => "appointments", :action => "create"}, :html => {"data-abide" => ""}) do |f| %>
      <label>
        Appointment Date
      </label>
      <%= f.date_select :appointment_date %>

      <label>
        Appointment Timeframe Start
      </label>
      <%= f.time_select :appointment_start_time %>

      <label>
        Appointment Timeframe End
      </label>
      <%= f.time_select :appointment_end_time %>

  <%= f.fields_for :addresses do |builder| %>
    <%= builder.hidden_field :user_id, :value => current_user.id %>

        <label>
          Street Address
          <%= builder.text_field :street_address %>
        </label>

        <label>
          Street Address (Optional)
          <%= builder.text_field :street_address_optional %>
        </label>

        <label>
          City
          <%= builder.text_field :city %>
        </label>

        <label>
          State
          <%= builder.text_field :state %>
        </label>

        <label>
          Zip Code
          <%= builder.number_field :zip_code %>
        </label>

        <%= builder.check_box :primary %><%= builder.label :primary %>

  <% end %>

      <label>
        Special Instructions
        <%= f.text_area :comments %>
      </label>

      <%= f.submit "Sign Up", :class => "button expand"%>

<% end %>

Thanks in advance for the help :)

Upvotes: 4

Views: 3304

Answers (1)

Jorge de los Santos
Jorge de los Santos

Reputation: 4633

A user can have many appointments, but each one is in one address. (unless he can multilocate himself).

So you should do:

class User
  has_many :appointments

class Appointment
  has_one :address

class Address
  belongs_to :appointments

If you want to retrieve the addresses in which the user has appointments you have to do:

@addresses = current_user.appointments.map {|app| app.address}

Upvotes: 4

Related Questions