Lee McAlilly
Lee McAlilly

Reputation: 9316

How to create an association between two rails models

This is a newbie question, but I'm still learning how to create an association between two models in rails. I have a user model and a journal_entry model. The journal entries belong to the user and the user has_many journal entries. I've created migrations that look like this:

class AddJournalEntriesToUsers < ActiveRecord::Migration
  def change    
    add_column :journal_entries, :user_id, :integer
  end
end

class AddIndexToJournalEntries < ActiveRecord::Migration
  def change
    add_index :journal_entries, [:user_id, :created_at]
  end
end

Here's what my User model looks like:

class User < ActiveRecord::Base
  authenticates_with_sorcery!

  attr_accessible :email, :password, :password_confirmation

  has_many :journal_entries, dependent: :destroy

  validates_confirmation_of :password, :message => "should match confirmation", :if => :password
  validates_length_of :password, :minimum => 3, :message => "password must be at least 3 characters long", :if => :password
  validates_presence_of :password, :on => :create
  validates_presence_of :email
  validates_uniqueness_of :email

end

And here's what my journal_entry model looks like:

class JournalEntry < ActiveRecord::Base
  attr_accessible :post, :title, :user_id

  belongs_to :user

  validates :user_id, presence: true

  default_scope order: 'journal_entries.created_at DESC'
end

But when I go to create a new journal entry at /journal_entries/new I just a validation error that says "User can't be blank". So the user_id is not getting added to the journal entry even though I'm logged in and there is a user_id column in my db/schema.rb:

create_table "journal_entries", :force => true do |t|
    t.string   "title"
    t.text     "post"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
    t.integer  "user_id"
  end

Also, this is the form that I'm using on journal_entries/new to create the journal entry:

<%= form_for(@journal_entry) do |f| %>
  <% if @journal_entry.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@journal_entry.errors.count, "error") %> prohibited this journal_entry from being saved:</h2>

      <ul>
      <% @journal_entry.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :post %><br />
    <%= f.text_area :post %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

What am I missing here? Do I need to add the user_id as a hidden field on the form?

Upvotes: 0

Views: 3693

Answers (5)

Galuga
Galuga

Reputation: 541

you have it right this time. You added the user association to the journal model which loads the user in the controller before displaying it in the view. You do need the hidden fields in your form which you added, since you are using a stateless protocol. On the update/create action, double check that the user posting is the user using and save.

Upvotes: 0

Lee McAlilly
Lee McAlilly

Reputation: 9316

Ok, so I got this working by adding the user to the create action in my journal_entries_controller.rb. Here's the code I used, but is this the "rails way" to do this?

def create
  @user = current_user
  @journal_entry = @user.journal_entries.build(params[:journal_entry])
  if @journal_entry.save
    flash[:success] = "Journal entry created!" 
  end
end

Upvotes: 0

Jakub Kuchar
Jakub Kuchar

Reputation: 1665

i bet, that u forget something like

def create
    @journal_entry = @user.journal_entries.build(params[:journal_entry])
    # @journal_entry = current_user.journal_entries.build(params[:journal_entry])
    if @journal_entry.save
    ..

Upvotes: 2

Bhushan Lodha
Bhushan Lodha

Reputation: 6862

journal_entry model should look like

class JournalEntry < ActiveRecord::Base
  attr_accessible :post, :title, :user_id
  belongs_to :user
  validates :user_id, presence: true
  default_scope order: 'journal_entries.created_at DESC'
end

This should work!

Upvotes: 2

DGM
DGM

Reputation: 26979

You need to add user_id to your attr_accessible call, if you look at your logs it is probably warning you that it can't mass assign it.

Upvotes: 0

Related Questions