rubyruby-on-rails-3activerecordcarrierwavedci

Extending a ruby eigenclass to load CarrierWave


Update: I've simplified my question; you can see the full history by checking out my editing revisions. Thanks to iain and bernardk for getting me this far.


I want to load carrierwave functionality into an instance of my User < ActiveRecord::Base model.

require 'uploaders/avatar_uploader'

module HasAnAvatar
  def self.extended(host)
    if host.class == Class
      mount_uploader :avatar, AvatarUploader
    else
      class << host
        mount_uploader :avatar, AvatarUploader
      end
    end
  end
end

Executing:

(user = User.first).extend(HasAnAvatar).avatar

Results in:

NoMethodError: undefined method new' for nil:NilClass from /Users/evan/.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/carrierwave-0.6.2/lib/carrierwave/mount.rb:306:in uploader'

I suspect the problem is that mount_uploader in HasAnAvatar is not being invoked properly on the eigenclass for user, such that the uploaders hash isn't populated.

Any thoughts on how to get this working?


Here is an example Rails app for this issue: https://github.com/neezer/extend_with_avatar_example


Solution

  • Ok, I think I found out what was causing my issues...

    In https://github.com/jnicklas/carrierwave/blob/master/lib/carrierwave/mount.rb, in the definition of CarrierWave::Mount::Mounter, there are three references to record.class. This rightly references back to the main User class, which doesn't have the extended methods I loaded into the user's metaclass. So, I changed those to this: https://gist.github.com/4465172, and it seemed to work.

    Also seems to continue to work if used normally like in the CarrierWave docs, so that's good too. Will continue testing it, though.