Forum: Ruby on Rails [ANN] SuperImage plugin

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
D0cd6b10e01bacb976b3b815a9c660bc?d=identicon&s=25 Alex Wayne (Guest)
on 2006-04-27 03:33
Greetings all,

This is the first release of the SuperImage plugin.  The idea is you
upload images to the database, and then pull them out at any size you
want. Combine this with caching and it will stay light and fast.

More info and instructions are here:
http://beautifulpixel.textdriven.com/articles/2006...

svn: http://beautifulpixel.textdriven.com/svn/plugins/s...



That's all well and good and useable, but there are 2 things I would
like to improve. I am stuck on them, however.

First, the included migration is an ugly hack

  def self.up
    create_table :super_images, :force => true do |t|
      t.column :data, :binary, :size => 10000000, :null => false
      t.column :created_at, :datetime
    end
    execute "ALTER TABLE `super_images` MODIFY `data` MEDIUMBLOB"
  end

I just could not get the ruby definition for :data to create a
MEDIUMBLOB on mysql.  The size parameter seems to have been completely
disregarded.  The clomun sets up as BLOB with a size limit of 16K, which
is far to small for most image uploading needs.



Second, the "show_image" action is currently included in via "include
SuperImagePlugin::Show"

This works, but it means the action name that performs the image
retrieval is locked in to be "show_image".  I would like to have it
works this way:

  class MyImagesController < ...
    image_action :foo
  end

Then you can access the images via "/my_images/foo/12".  Sadly though,
metaprogramming like this still makes my head spin.


If anyone has ideas about alleviating these 2 points, it sure would be
appreciated.
6076c22b65b36f5d75c30bdcfb2fda85?d=identicon&s=25 Ezra Zygmuntowicz (Guest)
on 2006-04-27 17:24
(Received via mailing list)
Hi!

On Apr 26, 2006, at 6:33 PM, Alex Wayne wrote:

> svn: http://beautifulpixel.textdriven.com/svn/plugins/s...
>

Nice idea.


>       t.column :created_at, :datetime
>
Not sure there is a prettier way to handle this part.
>   end
>
> Then you can access the images via "/my_images/foo/12".  Sadly though,
> metaprogramming like this still makes my head spin.
>
>
> If anyone has ideas about alleviating these 2 points, it sure would be
> appreciated.
>

I have taken the liberty of implementing image_action :foo for you.
And I also made the data= method on ActiveRecord::Base in a different
way. I commented the way this stuff works so you can learn how to do it.

This code is untested so it may need some slight adjustment, but
hopefully not ;)

----init.rb---
require 'super_image'
require 'RMagick'

ActionController::Base.send :include, SuperImagePlugin::Show
ActiveRecord::Base.send :include, SuperImagePlugin::SetImage


--super_image.rb----

module SuperImagePlugin
   module Show
     # when we get included into the ApplicationController in init.rb
     # we extend that class with the methods in our ClassMethods module
     def self.included(base)
       base.extend(ClassMethods)
     end

     module ClassMethods
       # The image_action method will become a class method of
       # ApplicationController. This allows it to be used as a
       # macro like before_filter & friends. It takes one symbol
       # or string and uses define_method to create an instance
       # method that is in the same scope as controller actions.
       # You can use it in any controller class to define and
image_method:
       #  image_action :show
       def image_action(meth)
         define_method(meth) {
           @headers['Cache-Control'] = 'public'
           img = SuperImage.find(params[:id])
           if img
             if params[:size]
               data = Magick::Image.from_blob(img.data)[0]
               data.change_geometry!("#{params[:size]}x#{(params
[:size]).to_i}") do
                 |cols, rows, img|
                 img.resize!(cols, rows)
               end
             else
               data = Magick::Image.from_blob(img.data)[0]
             end

             send_data data.to_blob,
                       :type => 'image/jpeg',
                       :disposition => 'inline'
           else
             render :text => 'Image Disabled!'
           end
           GC.start
         }
       end

     end # ClassMethods

   end # Show

   module SetImage
     # when we get included into ActiveRecord::Base, a data= method
     # is defined.
     def self.included(base)
       base.include(ModelMethods)
     end

     module ModelMethods
       def data=(file)
         if file.size > 0
           img = Magick::Image.from_blob(file.read)[0]
           img.format = 'JPG'
           self[:data] = img.to_blob
         end
         GC.start
       end
     end # InstanceMethods
   end # SetImage
end # SuperImagePlugin



I removed your comments just to make it clear what I did. Just add
them back if this works for you. I haven't looked at the rest of it
yet, but this should get you started.

Cheers-
-Ezra
2d1a6a800524db3dd5a6bd7c79ea0e7b?d=identicon&s=25 Peter (Guest)
on 2006-04-27 19:35
Hey Ezra, you tha man !
2d1a6a800524db3dd5a6bd7c79ea0e7b?d=identicon&s=25 Peter (Guest)
on 2006-04-27 19:38
Peter wrote:
> Hey Ezra, you tha man !

How rude of me.

Thank you Alex Wayne.
Db303dc84d03a992b33cd3ac978f89ae?d=identicon&s=25 Benjamin Curtis (Guest)
on 2006-04-28 04:24
(Received via mailing list)
Now published at http://agilewebdevelopment.com/plugins/show/102. :)

--
Benjamin Curtis
http://www.tesly.com/ -- Collaborative test case management
http://www.agilewebdevelopment.com/ -- Resources for the Rails community
61b533b3b2330585c25c761ce28d45ec?d=identicon&s=25 Robert Wagner (Guest)
on 2006-04-28 14:21
(Received via mailing list)
this is nice, *but* isn't it quite dangerous in regards on generating
a huge load, while automatically GET /show_image?size=$autoincrement
-robert

2006/4/28, Benjamin Curtis <rails@bencurtis.com>:
71c85a662af0764df3a77cc00db166c9?d=identicon&s=25 Raphael Bauduin (Guest)
on 2006-04-28 14:57
(Received via mailing list)
On 4/27/06, Alex Wayne <rubyonrails@beautifulpixel.com> wrote:
> Greetings all,
>
> This is the first release of the SuperImage plugin.  The idea is you
> upload images to the database, and then pull them out at any size you
> want. Combine this with caching and it will stay light and fast.
>


Why use the database as image store and not the file system? I rather
agree with these arguments:
http://mysqldump.azundris.com/archives/36-Serving-...
linked from the lighttpd blog
(http://blog.lighttpd.net/articles/2006/03/10/servi...)

Raph
Ea627ef000ec92c6cdd5a4c14075e740?d=identicon&s=25 Dan Kubb (Guest)
on 2006-05-03 19:08
(Received via mailing list)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Alex,

> I just could not get the ruby definition for :data to create a
> MEDIUMBLOB on mysql.  The size parameter seems to have been completely
> disregarded.  The clomun sets up as BLOB with a size limit of 16K,
> which
> is far to small for most image uploading needs.

I've been thinking about this for a while, and I don't understand
why Rails can't be made to handle this sort of thing automatically.

Right now with Migrations Rails takes what you say literally, if
you specify :binary its mapped onto a BLOB.  If you sat :integer
its mapped onto INT.

What I think *should* happen is to use :binary as a reference
to a *class* of columns (BLOB, MEDIUMBLOB, etc), and the :limit
parameter should be used to select the best column from the
class -- ideally the smallest column that will still fit whatever
size of data :limit specifies.

The biggest place this would help is with integers.  If I say I
want :integer, with a :limit of 2, it should use TINYINT rather
than INT.  Its a waste to use something like an INT when a
TINYINT will do.

This would require the connection adapters to know how to
"negotiate" the correct column size, but I think it is doable.
I'd be willing to write the MySQL logic if others were willing
to do patches for other databases... drop me a line if you're
interested in collaborating on this.

We'd get two benefits with this approach:  Space would be conserved
and when it is needed (as in this case) and larger columns would be
selected automatically based on the size needs specified.

- --

Thanks,

Dan
__________________________________________________________________

Dan Kubb
Autopilot Marketing Inc.

Email: dan.kubb@autopilotmarketing.com
Phone: 1 (604) 820-0212
Web:   http://autopilotmarketing.com/
vCard: http://autopilotmarketing.com/~dan.kubb/vcard
__________________________________________________________________



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (Darwin)

iD8DBQFEU4PE4DfZD7OEWk0RAv+SAJ9tUAHS5OFrk0JYdIztEZ1JVuDJrQCgrnXh
VrIXKTIBhBGVFAxfol4vJkI=
=t2xo
-----END PGP SIGNATURE-----
This topic is locked and can not be replied to.