0

So I have an assets model which is inherited by images and files as STI. Products has many images as assetable. This polymorphic association is working fine but I can't figure out how to add the user_id to every asset. A asset always belongs to a user no matter if its an image or file. Please look at my code below. I'm pretty sure there's something I need to do within the controllers create method but I'm not sure what? I've tried merging :user_id but this just returns nil when looking at the console log. Ideally what I'd also like to do is @user.images which will display all the images that the user has uploaded or even @user.files

class User < ActiveRecord::Base
  has_many :products
  has_many :assets
end

class Asset < ActiveRecord::Base
  belongs_to :assetable, :polymorphic => true
  belongs_to :user
end

class Image < Asset
  mount_uploader :filename, ImageUploader
  attr_accessible :filename, :assets
end

class Product < ActiveRecord::Base
  belongs_to :user

  has_many :images, as: :assetable
  accepts_nested_attributes_for :images 

  attr_accessible :name, :price, :images_attributes
  validates_presence_of :name
end

class ProductsController < ApplicationController
 def create
   @product = Product.new(params[:product])
   @product.user_id = current_user.id

   params[:product][:images_attributes].each do |key, image|
     # image.user_id = current_user.id
     image.merge(:user_id => 1)
   end

   @product.save
 end
end
Peter
  • 749
  • 10
  • 27
  • What's the problem with the code? Do you get an error or exception? Doesn't `image.user_id = current_user.id` work? – Kashif Umair Liaqat Feb 04 '13 at 13:01
  • I'm not getting any errors. When saving, everything works but the assets table under user_id shows 'null' and the console log shows the MySQL insert for assets as 'user_id = nil'. No the `image.user_id = current_user.id` doesn't work either as it shows as nil. – Peter Feb 04 '13 at 13:44
  • `image.merge!(:user_id => 1)` if you want so and place it before wrapping params. :) But look at the next answer – Valery Kvon Feb 04 '13 at 14:19

1 Answers1

0
def create
  params[:product][:images_attributes].each do |key, image|
    image.merge!(:user_id => current_user.id)
  end

  @product = Product.new(params[:product])
  @product.user_id = current_user.id

  @product.save
end

By the way, you'd better to replace inheritance logic into the model:

class Image < Asset
  mount_uploader :filename, ImageUploader
  attr_accessible :filename, :assets

  before_save do
    self.user = assetable.try(:user)
  end
end

# controller

def create
  @product = Product.new(params[:product])
  @product.user = current_user
  @product.save
end
Valery Kvon
  • 4,438
  • 1
  • 20
  • 15
  • Thanks Valery your `before_save` works really well. Can you explain what its actually doing? Any links to learn from? – Peter Feb 04 '13 at 14:38
  • It creates callback to run before the object get saved. Look API http://api.rubyonrails.org (ActiveRecord::Callbacks) – Valery Kvon Feb 04 '13 at 14:48
  • sorry I meant the `self.user = assetable.try(:user)` line – Peter Feb 04 '13 at 15:13
  • `try(:user)` means that you trying to get :user value of 'assetable': if method responded with value, return value, otherwise return nil, even if 'assetable' is nil. – Valery Kvon Feb 04 '13 at 17:36