Max Wofford
Max Wofford

Reputation: 253

ActiveRecord associations only working in console

I have a User model and an ArtworkIteration model. Users can create ArtworkIterations.

My user model has many artwork_iterations

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :artwork_iterations
end

And my artwork_iterations belongs_to a user

class ArtworkIteration < ActiveRecord::Base
  belongs_to :user
end

Here's the migration which adds the user_id foreign key to my artwork_iteration model

class AddUserIdToArtworkIterations < ActiveRecord::Migration
  def change
    add_column :artwork_iterations, :user_id, :integer
    add_index :artwork_iterations, :user_id
  end
end

When I create a artwork_iteration in rails console it works:

> @art = ArtworkIteration.create(user_id: User.last.id)
> @art.user
# Successfully returns the last user

But when I create an artwork_iteration through my site when logged in, artwork_iteration.user is null.

To get around this I've added a hidden field to my form:

<%= f.hidden_field :user_id, value: "#{current_user.id}" %>

But this seems hacky and is extremely insecure. (Any user could inspect the element and change this value, giving them access to create artwork_iterations as a different user).

Upvotes: 0

Views: 140

Answers (1)

Art
Art

Reputation: 781

You probably know the answer and just don't realize it. We'll need to see your controller and routes most likely, but, in the console you assign a user_id clearly. On your site you are clearly not. If you've nested artwork_iterations under user in your routes you have to have one thing in your controller for new and create and if you didn't you have to have another.

If you are nested, at the top of your artwork_iterations controller you need the following before_action:

before_action :get_user

Then at the bottom you need this as a private method:

def get_user
  @user = User.find(params[:user_id]) # (or current_user as you seem to have that helper)
end

This will pass the params of your localhost/user/1/artworkiterations/new page so the user matches the logged in user. If you have Devise or a "current_user" method you could just use current_user here.

I'm going to assume you've nested it, but, either way, you have to actually declare who the user is for your new and create actions in the artwork_iterations controller. Such that:

def new
  @artworkiteration = @user.artwork_iterations.build
end

Something like that will probably work for you.

Upvotes: 2

Related Questions