Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mongoid Embedded Documents don't save images #81

Closed
anlek opened this issue Jun 21, 2010 · 31 comments
Closed

Mongoid Embedded Documents don't save images #81

anlek opened this issue Jun 21, 2010 · 31 comments

Comments

@anlek
Copy link

anlek commented Jun 21, 2010

When having a CarrierWave uploader mounted in an embedded document, it doesn't fire (save) at all, but when I move it to the parent, it saves correctly.

There is no error or message in the embedded document saving.

@perezd
Copy link

perezd commented Jul 5, 2010

any ETA on a solution to this? This will be a blocker bug for me really soon :(

@subdigital
Copy link

I ran into this as well. I'd be happy to contribute a fix, but right now Rails3, Mongoid, and CarrierWave are new to me, so I need to be pointed in the right direction :)

@anlek
Copy link
Author

anlek commented Jul 19, 2010

I'm pretty sure it's the way Mongoid saves the document, you need the ability to call save on the embedded object during save of parent object so that CarrierWave can be triggered to do it's work. I'm not 100% sure if that correct but it's a good place to start.

@subdigital
Copy link

That's what I'm thinking as well, but it doesn't make sense to have to call "save" on an object that's already being saved. What about another carrierwave method in the mongoid adapter, something like:

accepts_nested_file_uploads_for :children, :class=>ChildClass

And then the before_save, after_save hooks could be wired up to the parent, but act on the children.

I'm not entirely sure how to accomplish this though, this is just a thought.

@anlek
Copy link
Author

anlek commented Jul 19, 2010

Well, why not add an before save hook to the parent object that calls all the embedded children objects save command, which really should do nothing (maybe run validations) except that's what I'm assuming CarrierWave alias. Not really sure how CarrierWave works when it comes to saving an object.

@subdigital
Copy link

It adds 3 hooks to the model's save/delete events:

  after_save "store_#{column}!".to_sym
  before_save "write_#{column}_identifier".to_sym
  after_destroy "remove_#{column}!".to_sym

The parent could execute these on it's children directly, you'd just need to loop over them & send those particular messages to each instance.

@anlek
Copy link
Author

anlek commented Jul 19, 2010

I'm not sure what you mean by this. What is "The Model" you're referring to, a parent or child?

@subdigital
Copy link

In our case, this is the child object. But if we added another method on the parent that would execute these methods "store_#{column}!", etc on each child I think it would work.

@anlek
Copy link
Author

anlek commented Jul 19, 2010

I would rather see it in the child as the parent shouldn't care that a child would have a file or not (also, developers won't know to look in the parent for a child's function). So we need a way for the parent to always fire a method when it's being saved and embedding it's children, then attached save_#{column}! to that?

@subdigital
Copy link

...or ask the mongoid folks if there's a way for an embedded document to get notified when the parent is saved.

@subdigital
Copy link

(actually I think we're saying the same thing)

@anlek
Copy link
Author

anlek commented Jul 19, 2010

I've added the issue to Mongoid:
http://github.com/durran/mongoid/issues/#issue/194

@durran
Copy link
Contributor

durran commented Jul 30, 2010

The main issue here is that the callbacks on the children are not firing in mongoid anymore if you called save on the parent... If you call save on the embedded document it will properly save as callbacks bubble up, but not down. (this is by design.)

I am trying to figure out a workaround for this that I can put in Mongoid... More info as I get there.

@subdigital
Copy link

Makes sense, but hoping for a workaround for these scenarios. Thanks, durran!

@durran
Copy link
Contributor

durran commented Aug 4, 2010

While I am looking into this - your current workaround is to make the save call on the embedded document itself. That will save the file. For example, if you have a person that embeds many addresses, and you have an uploader mounted on address, calling save on the address will save the file. Calling save on person will not.

@zerobearing2
Copy link

I created a hack to bubble down the callbacks from the parent model to the embedded associations of a mongoid document. I created this to get Carrierwave working correctly. Here is quick example of what I did: http://gist.github.com/566242 -- CAUTION, only tested it locally; using Rails 3.0.

@mcasimir
Copy link

Hack from zerobearing2 doesn't work for me since the prototype of function run_callbacks in the snippet is different from run_callbacks(kind, *args, &block) in ActiveSupport::Callbacks. Also validation callbacks are not supported this way since they are triggered directly by the valid? method. Here i've changed the gist from zerobearing2 to fit my needs: http://gist.github.com/574705. Rails 3 + MongoID 2.0.0beta17

@zerobearing2
Copy link

mcasimir: you should be able to add 'validates_associated :name_of_assocation' to the parent model and have it then validate each association when the parent is validated.

thanks for fixing the run_callback method signature too -- i've updated my hack locally and works nicely. cheers! :-)

@mcasimir
Copy link

It seems i've discovered another issue. When i use mount_uploader in embedded documents upload works nice and attachments are saved correctly, but for some reason filename remains blank.. is there anyone that has experienced the same issue?

@trevorturk
Copy link
Contributor

Is this still an issue? I'd like to close if possible...? Let me know. mcasimir, it sounds like you've identified another separate issue - could be good to create a new ticket. Thanks!

@mcasimir
Copy link

Yes, i think it's a different issue, i'm tring to understand if this affects only s3 uploaders or not. I'll open a new ticket anyway.

@mcasimir
Copy link

I've changed idea:
I'think the new issue identified depends strictly on this issue and on the solution purposed in zerobearing gist, is it ok to reference this issue into the new ticket?

i've solved that with an after_save callback in embedded document model:

    after_save :extract_filename

    def extract_filename
      self.class.skip_callback(:save, :after, :extract_filename)

      @photo_original_filename = photo.instance_variable_get("@original_filename")
      if @photo_original_filename.present?
        self.update_attributes :photo_filename => @photo_original_filename
      end

      self.class.set_callback(:save, :after, :extract_filename)
    end

..but i suppose that this still remains an issue, is it correct?

It seems that carrierwave actually writes nil into the filename attribute since if i use before_save instead of after_save filename is set correctly at the end of the callback but then it turns back to blank after save.

I can't find a better solution since looking into the sources i can't figure out where and how uploader filenames are set.

That's all, please tell me if it's needed to open another ticket.
Maurizio

@Lewy
Copy link

Lewy commented Nov 22, 2010

After 5 months it is still issue for me. Uploader doesent work in embeded document but if I save object manualy upload works but dosen't set proper filename

@perezd
Copy link

perezd commented Nov 22, 2010

Does the author have any input on this issue?

@jnicklas
Copy link
Member

I haven't had a need to get this fixed myself. IMHO it's more about an architectural decision in mongoid that may not be the best. If someone can find an elegant workaround, I'd love to accept a patch, but it's not likely that I'll invest my time to fix this. Sorry.

@trevorturk
Copy link
Contributor

I'm closing this issue as it seems settled.

From what I gather, there is a workaround for this known limitation as mentioned by durran. I'm adding that information to the wiki now. I'd appreciate it if someone would look at the wiki, and possibly provide some code examples etc to help others who may be hit with the same limitation.

If there's concern about this information being easily found, I can add a note to the readme as well. I'm adding a link to the wiki to the top of the readme now.

If someone would like take a shot at providing a pull request to improve Carrierwave, we can have another look.

@scomma
Copy link

scomma commented Aug 17, 2011

Since this issue ranks pretty highly on Google I'd like to add that this gem https://github.com/alexeypetrushin/mongoid_misc patches this perfectly and gets embedded Mongoid documents to play nice with CarrierWave. Hope this helps someone.

@trevorturk
Copy link
Contributor

@scomma please update the wiki!

@Arjeno
Copy link
Contributor

Arjeno commented Oct 25, 2011

This issue is pretty easily solved using cascade_callbacks. See https://github.com/mongoid/mongoid/pull/1058 for the pull request. All you need to do is:

embeds_many :photos, :cascade_callbacks => true

@Goltergaul
Copy link

the cascading callbacks only work if fields in the embedded document have changed. so if you change the attached file by uploading a new one and at the same time changing other fields, then the new attachment is saved.

BUT if you only upload a new file, the file is saved in the uploads directory but not in the embedded document. after reloading the object, it still points to the old file. i think there is still something wrong, mongoid seems not to regognize a change in the model if only the file changes

@faraazc
Copy link

faraazc commented Apr 18, 2015

is this issue fixed?..can i get it in the latest version of carrierwave?

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests