DaveG
DaveG

Reputation: 1203

Create a new record that has a belongs_to relationship, passing the ID of the model it belongs to

I'm trying to create a new contact object from an account object's "show" page. I know the below codes isn't correct. If I'm on the "show" page of the account how do I pass that accounts ID to the New contact form so I can create a new contact that belongs to that account?

Contact belongs_to Account

Account has_many Contacts

Account "Show" view where I have a link to a new contact

<%= link_to "Add Contact", new_account_contact_path(@account), class: 'btn' %>

Contact Controller with Suggested Edits "New, Create" Actions

class ContactsController < ApplicationController
  before_filter :authenticate_user!
  before_filter :load_account
  respond_to :html, :json

...

  def create
    @contact = @account.contacts.new(params[:contact])
     if @contact.save
       redirect_to account_path(params[:account]), notice: "Successfully created Contact."
     else
       render :new
     end

  end

  def new
    @contact = @account.contacts.new
  end
...

end

New Contact Form

<%= simple_form_for(@contact) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :firstname %>
    <%= f.input :lastname %>
    <%= f.input :email %>
    <%= f.input :phone %>
    <%= f.input :note %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

ERROR

undefined method `contacts_path' for #<#<Class:0x007f86c0c408d0>:0x007f86c0be7488>
Extracted source (around line #1):

1: <%= simple_form_for(@contact) do |f| %>
2:   <%= f.error_notification %>
3: 
4:   <div class="form-inputs">

Upvotes: 0

Views: 218

Answers (3)

Zach Kemp
Zach Kemp

Reputation: 11904

Judging by the existence of new_account_contact_path(@account), I will assume you have something like this in your routes.rb:

resources :accounts do
  resources :contacts
end

If that is the case, your contacts#create route (and every contact route) will include an :account_id param. You can add a before_filter to automatically load the account in every action in the ContactsController, so you always have the relevant account object:

before_filter :load_account

def load_account
  @account = Account.find(params[:account_id])
end

Then in your new and create actions, it's a simple matter of building the object on the relation:

def new
  @contact = @account.contacts.new
end 

def create
  @contact = @account.contacts.new(params[:contact])
  ....
end

Also, I've never used simple_form_for, but it strikes me you might also need to pass in @account as a parameter so the form knows what url to post to.

Upvotes: 2

Gosha A
Gosha A

Reputation: 4570

I'm assuming your routes look something like

resources :accounts do
  resources :contacts
end

This way, new_account_contact_path(@account) would produce an URL like /accounts/SOME_ID/contact/new.

In ContactsController, then, you will have access to account id via params[:account_id], so the proper way to create a contact for already know account would be

def new
  @account = Account.find(params[:account_id])
  @contact = @account.contacts.build(params[:contact])
end

def create
  @account = Account.find(params[:account_id])
  @contact = @account.contacts.build(params[:contact])
  # some stuff
end

Upvotes: 0

Anezio Campos
Anezio Campos

Reputation: 1555

You should change in your new action:

def new
  @account = Account.find(params[:account])
  @contact = Contact.new
end

and in your new form:

<%= simple_form_for(@contact) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :firstname %>
    <%= f.input :lastname %>
    <%= f.input :email %>
    <%= f.input :phone %>
    <%= f.input :note %>
    <%= f.input :account_id, :as => :hidden, :input_html => { :value => @account.id } %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

Upvotes: -1

Related Questions