How do you get the parent of a polymorphic object before saving it?

I have a standard polymorphic relationship, and I need to know who his parent is before I save it.

Class Picture < AR::Base belongs_to :attachable, :polymorphic => true end Class Person < AR::Base has_many :pictures, :as => :attachable end Class Vehicle < AR::Base has_many :pictures, :as => :attachable end 

I upload photos through Paperclip, and I create a processor that needs to do different things for different images (for example, Person images should look like Polaroid, and images on the vehicle should have an overlay). My problem is that before the image is saved, I do not know if it is associated with a Person or a Vehicle.

I tried putting a β€œmarker” in Person and Vehicle so that I could tell them appart, but when I am in the Paperclip processor, the only thing I see is the Picture class. :( My next thought is to go up the stack to try to get parent caller, but that seems pretty smelly to me. How would you do that?

+4
source share
3 answers

I β€œsolved” this problem and wanted to post it here so that it would help someone else. My solution was to create a β€œparent” method in the Picture class, which went up on the stack and found something similar to a parent.

WARNING This is crap code and probably should not be used under any circumstances. It worked for me, but I cannot guarantee that it will not cause bodily harm someday in the future.

 caller.select {|i| i =~ /controller.rb/}.first.match(/\/.+_controller.rb/).to_s.split("/").last.split("_").first.classify.constantize 

What this code does is walk through the caller tree, looking for the ancestor named *_controller.rb . If he finds one (and he should), then he parses the name into a class, which should be the parent class of the calling code. hmm

BTW: I reset Paperclip and started using CarrierWave . It makes it much easier, and I was able to get it to work in half the cases. Yea CarrierWave!

+1
source

You should be able to get it from a polymorphic association.

 Class Picture < AR::Base belongs_to :attachable, :polymorphic => true before_create :apply_filter private def apply_filter case attachable when Person #apply Person filter when Vehicle #apply Vehicle filter end end end 

Or you can just ask it the type of association so you don’t create and compare objects, but simply compare strings.

 Class Picture < AR::Base belongs_to :attachable, :polymorphic => true before_create :apply_filter private def apply_filter case attachable_type when "Person" #apply Person filter when "Vehicle" #apply Vehicle filter end end end 
+5
source

I created interpolation to solve it. My clip model is Asset, and Project is the parent model. There are other models, such as articles, that are under the project model and may have attachments.

 Paperclip.interpolates :attachable_project_id do |attachment, style| attachable = Asset.find(attachment.instance.id).attachable if attachable.is_a?(Project) project_id = attachable.id else project_id = attachable.project.id end return project_id end Paperclip.interpolates :attachable_class do |attachment, style| Asset.find(attachment.instance.id).attachable.class end 

And used it in a model, for example:

  has_attached_file :data, :path => "private/files/:attachable_project_id/:attachable_class/:id/:style/:basename.:extension", :url => "/projects/:attachable_project_id/:attachable_class/:id/:style", :styles => { :small => "150x150>" } 
0
source

Source: https://habr.com/ru/post/1339036/


All Articles