How to create an association between two rails models
Asked Answered
E

5

0

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?

Encompass answered 6/7, 2012 at 1:26 Comment(5)
Can you post the code in your JournalEntriesController#create ?Convoy
Where do you set the user to the jornal? Post that code pleaseAshely
I edited the question to include the form on journal_entries/new that creates the journal entry.Encompass
yes, you need the user_id in the form!Pittman
Ok, it works properly if I add the user_id to to form like this ` <%= f.hidden_field :user_id, :value => current_user.id %>` but I thought the association was supposed to handle that for you. Shouldn't rails assign the user_id through the association, or do you always need to include the user_id as a hidden field on your forms?Encompass
A
2

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
    ..
Alaska answered 6/7, 2012 at 22:26 Comment(1)
Ok, this was indeed the answer. I needed to add the user to the create action in the journal_entries_controller def create @user = current_user @journal_entry = @user.journal_entries.build(params[:journal_entry]) if @journal_entry.save flash[:success] = "Journal entry created!" endEncompass
E
2

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!

Epifaniaepifano answered 6/7, 2012 at 3:40 Comment(3)
I added :user_id to my attr_accessible but it still is saying user_id can't be blankEncompass
I had to add the user_id as a hidden field on my form like this <%= f.hidden_field :user_id, :value => current_user.id %> in order to get it to work. Is this the rails convention?Encompass
Also, note that I think it's a security concern to list the :user_id as an attr_accessible. You don't want the user_id to be mass_assigned, right? stephensclafani.com/2010/01/04/…Encompass
A
2

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
    ..
Alaska answered 6/7, 2012 at 22:26 Comment(1)
Ok, this was indeed the answer. I needed to add the user to the create action in the journal_entries_controller def create @user = current_user @journal_entry = @user.journal_entries.build(params[:journal_entry]) if @journal_entry.save flash[:success] = "Journal entry created!" endEncompass
P
0

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.

Pittman answered 6/7, 2012 at 1:39 Comment(1)
I edited the question to include the new journal_entry model. Adding user_id to the attr_accessible did not work.Encompass
E
0

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
Encompass answered 7/7, 2012 at 16:9 Comment(1)
99% percent rails way :-), missing 1% because @user variable is useless, enough to use current_user. good luck!Alaska
S
0

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.

Satirize answered 7/7, 2012 at 16:17 Comment(1)
I removed the hidden field from the form and it's working fine. It's posting with the correct user_idEncompass

© 2022 - 2024 — McMap. All rights reserved.