This information is now old. A new version of the plugin can be found here with lots of instructions and examples.

NOTE: Before you update your plugin, install the dsl_accessor gem.

gem install dsl_accessor

Sorry it took so long guys, but FlexImage now has full support for multiple classes with different settings. The problem with class variables (the @@foo variety) is that if they point to the exact same object in all classes that inherit from the class it was defined in. For example:

class A
  @@foo = 'A'
  def self.foo
    @@foo
  end
end
A.foo #=> "A"
class B < A
  @@foo = 'B'
end
A.foo #=> "B" 
B.foo #=> "B"

So changing @@foo in the class B, changes it in class A, as well as it’s siblings.

The solution

There is a great gem out there class dsl_accessor. It provides a way to declare inheritance safe class level variables through an elegant API. I have transitioned all class level variables in FlexImage from the old @@foo style to the new and sexy accessors.

This also means some syntactic sugar (although, still backwards compatible). Where before you had to declare these values like this:

self.file_store = 'path/to/master_images'

Now you can do any of the following:

file_store        'path/to/master_images'
self.file_store   'path/to/master_images'
self.file_store = 'path/to/master_images'

And rest assured that all attributes are safe from their parent and siblings.

Found a bug?

As always, simply post here with any problems you may have and I will assist as best I can.

Happy Flexing!

21 Responses to “FlexImage update: now multi-class safe”

  1. Dustin Schneider Says:

    Thanks for the update!

    Found just one small renaming issue in controller.rb:

    --- vendor/plugins/flex_image/lib/flex_image/controller.rb      (revision 175)
    +++ vendor/plugins/flex_image/lib/flex_image/controller.rb      (working copy)
    @@ -110,7 +110,7 @@
           #   
           def render_flex_image(img)
             img.to_jpg!
    -        send_data(img[img.class.data_field], :type => 'image/jpeg', :disposition => 'inline')
    +        send_data(img[img.class.binary_column], :type => 'image/jpeg', :disposition => 'inline')
             GC.start
           end
    
  2. Alex Wayne Says:

    Committed.

    Thanks for the patch, Dustin!

  3. Simon Russell Says:

    Seems to do the trick, thanks for fixing that.

  4. Michael Carney Says:

    Does this make Single Table Inheritance work now? That is, can I have my base class for the Single Table Inheritance inherit from FlexImage rather than ActiveRecord::Base?

  5. Alex Wayne Says:

    Sorry Michael, I just did a search and read your original post for the first time. Somehow I missed it.

    Well this is a trickier issue. Mainly because there are a few methods that rely on super to default to ActiveRecord::Base for execution. The super method is insanely awesome, and it only available for inherited methods, not mized in ones. To do the same with a mixin would require some messy method aliasing that would give me a headache.

    Also, my personal feeling is that inheritance is that best way to add functionality to a class. Especially for functionality that is only supposed to work with a single pre-defined class. It’s just cleaner and neater.

    That said, I don’t see any reason why that would be impossible to do with a mixin, but I don’t think that is where this plugin will go. You are welcome to convert it on your own, however.

    These are the limitations of Ruby being single inheritance, and STI being implemented via class inheritance. Sometimes you can’t have both.

    If you come up with a solution, post it here. I would love to see it.

  6. Tim Lucas Says:

    You could use Rails’ built-in class_interitable_* methods to get the same effect as with dsl_accessor.

  7. Michael Carney Says:

    Alex.

    No worries… I just stored the image in a different table and use your insanely great plugin for that :-).

  8. Alex Wayne Says:

    Tim Lucas: Yes, I could. In fact, dsl_accessor does use it. But it also allows easy creation of very clean way to set those attributes:

    before:

    self.foo = 'some-data'

    after

    foo 'some-data'
  9. donald Says:

    Rails throws an exception when I try to view an image backed by the filesystem when the image file is missing for whatever reason. I would think the correct thing to do would be to log an error and return a 404 to the user.

  10. Simon Russell Says:

    Back again… with another patch. Is there some sort of other way I can let you know about that sort of thing?

    The patch adds a rmagick_process! method that lets you get access to the RMagick image object to do fancier operations on it. It also changes most of the other resize! etc methods to use it.

    I wrote it before I discovered that the trim! method I wanted already existed :)

    Interested?

  11. Alex Wayne Says:

    donald: This is why I usually advocate having a model dedicated to images and it being associated to other models. If there is no image for a dedicated image model, then you really are in an exceptional situation and should be raised as such. You should be able to check yourself with something like:

    @model = Model.find(params[:id])
    unless File.exists?(@model.file_path)
      render :text => '404!', :status => :not_found
    end
    

    Simon Russel: Sounds interesting. There is a private method call rmagick_image which actually just returns the raw RMagick::Image object. It’s used internally for processing. If what you have done gives a better solution, I would love to see it. Send it to the email the README.

  12. Erik Jacobs Says:

    FYI: dsl_accessor is now REQUIRED if you’re going to use FlexImage—if you install FlexImage and don’t have dsl_accessor and restart your server you get an error msg. I think.

  13. Alex Wayne Says:

    Yes, Erik. Sorry if that wasn’t clear enough. Although the error that you get should be clear. It specifically tells you the gem you need isn’t there and even tells you what to type to install it.

  14. Matze Says:

    First of all thank you for this great plugin!

    I have an image upload service running very well, but now i want to support batch upload via zip files.

    First of all i extract all Files to a temporary folder and want to add each Image via FlexImage to my database. Also of interest will be, that i’m using rubyzip. So, my files are all extract to the filesystem.

    Example:

    File.open("#{dir}/#{entry.name}", 'r') do |imagefile|
      img = Image.new
      img.data = imagefile
      img.save
    end

    In this case I’m getting

    undefined method `size’ for #<file:0x5fbe7f8>

    How to add images via FlexImage through the filesystem?

    Thank you in advance!

    Matze

  15. d3s Says:

    Hi, I have a little problem(!) that makes me work on for 3 weeks :(

    On Dreamhost i can’t make my flex_image work. Only the page with the plugin gives “FlexImage… error” when the plugin isn’t in plugins dir. When i install plugin rails gives application error and does not show page.

    Also after i script/server it works but gives;

    WARNING :: FlexImage :: Your version of RMagick does not support the “crop_resized!” method. Upgrade RMagick to get this functionality.

    Here’s Rmagick, /usr/lib/ruby/gems/1.8/gems/rmagick-1.14.1

    And imagemagick version; ImageMagick 6.2.4

    Please help!!! I have to finish the project!

  16. Carl Says:

    REST Url question?

    I am not sure where to post this so I ll go ahead as comment over here.

    I have the following:

    class myClass < ActiveRecord::Base has_one :logo, :as => :logoable end

    class Logo < FlexImage::Model belongs_to :logoable, :polymorphic => true end

    in myClassController I have: flex_image :action => :logo, :class => Logo

    To access the logo I need the following URL: myClass\logo\:the_id_in_the_many_2_many_table

    Would it not be better to have something of this sort: myClass\:id_of_my_class\logo

    I was even thinking: myClass\:id_of_my_class\logo_:size

    I am posting before I get into the routing and try to write a solution myself. Has anybody come across this? any solutions?

    Regards, Carl

  17. seamus Says:

    Hi,

    I have used fleximage in the past without any problem – however, i have just started a new project, installed the dll_accesor, the flex_image plugin and created a flex image through the generator ruby script/generate flex_image Photo

    when I do a rake i get the following errors – any thoughts or help on this would be greatly appreciated.

    F:\Software\Rails\cmr>rake migrate db—trace (in F:/Software/Rails/cmr)
    • Invoke migrate (first_time)
    • Invoke db:migrate (first_time)
    • Invoke environment (first_time)
    • Execute environment rake aborted! undefined method `assoc’ for class `Magick::ImageList’ f:/ruby/lib/ruby/gems/1.8/gems/rmagick-1.14.1-win32/lib/rmagick.rb:1201:in `unde f_method’ f:/ruby/lib/ruby/gems/1.8/gems/rmagick-1.14.1-win32/lib/rmagick.rb:1201 f:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_re quire’ f:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’ f
  18. Alex Wayne Says:

    Sorry it’s taken me so long to get you guys. Let see how I can help.

    Matze: Ruby’s uploaded file classes are different from the local files classes. I solve this in my tests by using a little MockFile class. I makes a local file look like an uploaded file to FlexImage. Try something like this:

    require 'vendor/plugins/flex_image/test/mockfile'
    file = MockFile.new('/path/to/local/file/jpg')
    @image = MyImage.new(:data => file)
    

    d3s: Your gonna have to talk to dreamhost about that. RMagick must be installed as a gem, so it has to be handled by your shared host. And without a more specific error message besides “FlexImage … error” I can;t really help you there either.

    Carl: You can do this easily.

    #routes.rb
    map.resources :my_class, :member => {:logo => :get}
    
    #environment.rb
    Mime::Type.register "image/jpg", :jpg
    
    formatted_logo_my_class_path(123, :jpg)
    #=> /my_classes/123/logo.jpg
    

    seamus: Sounds like your RMagick install got borked somehow. try this in irb:

    require 'rubygems'
    require 'RMagick'
    Magick::Image.read('/path/to/local/img.jpg').first
    

    If it works, RMagick should be working properly on your machine, if not you may need to reinstall.

  19. seamus Says:

    Hi,

    I had them re-install RMagick and i get through the code you suggested above.

    I now run into a problem when I install the dsl_accessor and flex_image. I get a “Rails application failed to start properly” error message. Without having done the flex-image install i don’t get that. The specific error is:

    /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’: no such file to load - dsl_accessor (MissingSourceFile) from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’ from /usr/lib/ruby/gems/1.8/gems/activesupport

    i am running on Bluehost if that means anything – i don’t have any problem on my local machine (windows) and I see the dsl_Accessor listed when I list gems on the server.

  20. seamus Says:

    i think i have figured the previous post out – I did not have the ENV[‘GEM_PATH’] set up in my environment.rb file

    thanks

  21. Random T. Says:

    This topic is quite hot on the Internet right now. What do you pay the most attention to when choosing what to write about?

Leave a Reply