1

I have a custom model which uses attachment model in rails. My attachment model looks something like this

class Attachment < ActiveRecord::Base
  belongs_to :attachable, polymorphic: true
  has_attached_file :file, styles: { logo: ['200x50>',:png] }
end

and the other model that uses the attachment looks something like this

class User < ActiveRecord::Base
  has_many :attachments, as: :attachable, dependent: :destroy
end

I want user model to have another attachment different from the one I have already setup to upload logo, something like this

has_one :user_logo, -> {where attachable_type: "UserLogo"}, class_name: "Attachment", foreign_key: :attachable_id, foreign_type: :attachable_type, dependent: :destroy

but when I try to access attachment.attachable I get

undefined UserLogo as **UserLogo** is not a model.

Can anyone please suggest what changes can I make so that attachment.attachable works for both attachment type.

so for example

when i execute something like this

att = Attachment.find(3) #assume it returns attachable type as User so att.attachable returns user object

but when i execute att = Attachment.find(3) #assume it returns attachable type as UserLogo so att.attachable returns exception wrong constant name UserLogo

how can i access User object from both attachment types. Thanks

opensource-developer
  • 2,826
  • 4
  • 38
  • 88

1 Answers1

2

Keep your attachable type 'User' which will be clean polymorphic. Define type field inside 'Attachment' model having two values logo & file

Association will get updated as below

class User < ActiveRecord::Base

has_many :attachments, -> {where type: "file"}, as: :attachable, dependent: :destroy  
has_one :user_logo, -> {where type: "logo"}, class_name: "Attachment", foreign_key: :attachable_id, foreign_type: :attachable_type, dependent: :destroy

end

I suggest you to have different styles for attachment depends on what type it have (logo/file). Validation for attachment type also vary as per type.

has_attached_file :file, styles: ->(file){ file.instance.get_styles }

validates_attachment_content_type :file, :content_type: [..], if: -> { type == 'logo' }

validates_attachment_content_type :file, :content_type: [..], if: -> { type == 'file' }


def get_styles
  if self.type == 'logo'
    style1
  elsif self.type == 'file'
    style2
  end
end

Please update status or any query you u get further.

Update - answering to further question

First Way: If you are using UserLogo as an attachable_type in Attachment, then it do not follow polymorphic association so define custom association.

belongs_to :resource,
  -> { |attachment| ['User', 'UserLogo'].include? attachment.attachable },
  class_name: 'User',
  foreign_key: :attachable_id

belongs_to :belongs_to :attachable,
  -> { |attachment| ['User', 'UserLogo'].exclude? attachment.attachable_type },
  class_name: :attachable_type,
  foreign_key: :attachable_id

Second Way: Create UserLogo class extending User class. It will find UserLogo with same User data

ray
  • 5,454
  • 1
  • 18
  • 40