# Injecting image= method into model classes

**URL:** <https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376>\
**Category:** Rails\
**Created:** [December 3, 2005, 1:15am UTC](https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376 "2005-12-03T01:15:28Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![johanatan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8491ac/32.png) [@johanatan](https://www.ruby-forum.com/u/johanatan)\
**Post date:** [December 3, 2005, 1:15am UTC](https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376/1 "2005-12-03T01:15:28Z")

</div>

hi All,

I’ve been trying to wrestle dynamic code generation into place for a  
week now with no success. What I want is a module or class (started  
trying to use module but finished up trying to use a class) which can  
inject a method into its consumer which will allow:

user.image = #Ruby:File

as you would get from a file upload. (This eliminates any need for  
special image handling code in the view or controller and lets the image  
field act like any other). It uses the RMagick library to convert all  
images to jpg’s and resize them to a consumer-defined size. What I was  
hoping the group could help with was moving all the code out of the  
model and into my ImageBlob class (which will inject necessary code into  
the model (i.e., consumer)). Here’s what I currently have (which  
works):

## model.rb

def image=( file )  
write\_attribute( ‘image’, ImageBlob.getBlob( file, 225 ))  
end  
def thumbnailImage=( file )  
write\_attribute( ‘thumbnailImage’, ImageBlob.assignAttrib( file, 125  
))  
end

## ImageBlob.rb

require ‘RMagick’  
include Magick

class ImageBlob  
def ImageBlob.getBlob( file, maxImageSize )  
#omitted code which resizes and reformats image and returns blob  
end  
end

I was hoping to have an initialize function in ImageBlob which would  
take the consumer class and inject the necessary methods into it (image=  
and thumbnailImage=). Here’s my best attempt at that (which fails for  
an unknown reason):

def initialize( attributesAndSizesHash, consumerClass )  
attributesAndSizesHash.each\_pair {|attributeName, maxImageSize|  
code = “class #{consumerClass}  
def #{attributeName}=( file )  
write\_attribute( ‘#{attributeName}’, ImageBlob.getBlob(  
file, #{maxImageSize} ))  
end  
end”  
eval( code ) }  
end

I also tried making code define a module and calling  
consumerClass.extend( moduleName ). Neither of these approaches are  
working.

Of course, if this implemention could work, then consumers of the  
ImageBlob class could simply call:

ImageBlob.new( { “image” =\> 225, “thumbnailImage” =\> 125 }, self )

anywhere in their class definition to have the functionality added (with  
any number of image fields each with their own size).

Can anyone out there provide the last piece of this puzzle? If it is  
provided, I will post the entire source for this module and it should  
prove to be useful.

Regards,  
Jonathan

---

<div class="post-metadata">

**Author:** ![johanatan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8491ac/32.png) [@johanatan](https://www.ruby-forum.com/u/johanatan)\
**Post date:** [December 4, 2005, 2:39am UTC](https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376/2 "2005-12-04T02:39:48Z")

</div>

Anyone have an idea? A simple example of how to inject code into a  
generic class would probably suffice. Can you possibly do a mixin  
dynamically and, if so, how?

Much thanks.

---

<div class="post-metadata">

**Author:** ![johanatan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8491ac/32.png) [@johanatan](https://www.ruby-forum.com/u/johanatan)\
**Post date:** [December 4, 2005, 5:28am UTC](https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376/3 "2005-12-04T05:28:46Z")

</div>

Hi !

2005/12/3, Jonathan [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) \<removed\_email\_address@domain.invalid.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Anyone have an idea? A simple example of how to inject code into a  
> generic class would probably suffice. Can you possibly do a mixin  
> dynamically and, if so, how?

Have you looked at FileColumn ? It does what you want, except it uses  
the file system. If you were to create a way to store in the DB  
instead, I’m sure Sebastian would include that in a future release.

See [http://www.kanthak.net/opensource/file\_column/](http://www.kanthak.net/opensource/file_column/)

Bye !

---

<div class="post-metadata">

**Author:** ![johanatan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8491ac/32.png) [@johanatan](https://www.ruby-forum.com/u/johanatan)\
**Post date:** [December 4, 2005, 2:03pm UTC](https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376/4 "2005-12-04T14:03:34Z")

</div>

On 12/4/05, Jonathan [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) \<removed\_email\_address@domain.invalid.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Anyone have an idea? A simple example of how to inject code into a  
> generic class would probably suffice. Can you possibly do a mixin  
> dynamically and, if so, how?

well, I don’t have to plug my file\_column plugin anymore since  
Francois was already so nice to do so 🙂 However, you might want to  
take a look at the plugin’s source code as it does exactly this:  
adding methods to a model dynamically.

Instead of creating strings and evaluating them, I would suggest you  
take a look at Module#define\_method that let’s you dynamically define  
methods using ruby’s nice block syntax. A small example from  
file\_column, that defines the “image=” method. (where the name of the  
attribute is stored in the local variable attr).

```
 define_method "#{attr}=" do |file|
    state = send(state_method).assign(file)
    instance_variable_set state_attr, state
    if state.options[:after_upload] and state.just_uploaded?
      state.options[:after_upload].each do |sym|
        self.send sym
      end
    end
  end

```

“state\_method” is a Symbol that contains the name of another generated  
method that will return an object that does all the heavy lifting for  
file uploads/image manipulation.

As a last note I wanted to give the reason why I decided to store  
files in the filesystem and not in the database: Simply put, rails’  
support for large binary columns is very poor and inefficient  
(somebody correct me please if that has changed since I last checked)  
and since the filesystem is very good at storing files I decided to  
leverage this.

Sebastian

---

<div class="post-metadata">

**Author:** ![johanatan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8491ac/32.png) [@johanatan](https://www.ruby-forum.com/u/johanatan)\
**Post date:** [December 3, 2005, 1:23am UTC](https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376/5 "2005-12-03T01:23:58Z")

</div>

Oops. The thumbnailImage= method should have been defined as this:

def thumbnailImage=( file )  
write\_attribute( ‘thumbnailImage’, ImageBlob.getBlob( file, 125 ))  
end

---

<div class="post-metadata">

**Author:** ![johanatan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8491ac/32.png) [@johanatan](https://www.ruby-forum.com/u/johanatan)\
**Post date:** [December 5, 2005, 2:34am UTC](https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376/6 "2005-12-05T02:34:16Z")

</div>

skanthak wrote:

> On 12/4/05, Jonathan [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) \<removed\_email\_address@domain.invalid.  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > Anyone have an idea? A simple example of how to inject code into a  
> > generic class would probably suffice. Can you possibly do a mixin  
> > dynamically and, if so, how?
> 
> well, I don’t have to plug my file\_column plugin anymore since  
> Francois was already so nice to do so 🙂 However, you might want to  
> take a look at the plugin’s source code as it does exactly this:  
> adding methods to a model dynamically.
> 
> Instead of creating strings and evaluating them, I would suggest you  
> take a look at Module#define\_method that let’s you dynamically define  
> methods using ruby’s nice block syntax. A small example from  
> file\_column, that defines the “image=” method. (where the name of the  
> attribute is stored in the local variable attr).
> 
> ```
> define_method "#{attr}=" do |file|
> state = send(state_method).assign(file)
> instance_variable_set state_attr, state
> if state.options[:after_upload] and state.just_uploaded?
> state.options[:after_upload].each do |sym|
> self.send sym
> end
> end
> end
> 
> ```
> 
> “state\_method” is a Symbol that contains the name of another generated  
> method that will return an object that does all the heavy lifting for  
> file uploads/image manipulation.
> 
> As a last note I wanted to give the reason why I decided to store  
> files in the filesystem and not in the database: Simply put, rails’  
> support for large binary columns is very poor and inefficient  
> (somebody correct me please if that has changed since I last checked)  
> and since the filesystem is very good at storing files I decided to  
> leverage this.
> 
> Sebastian

Thank you very much. 🙂 define\_method should do the trick. In my case,  
the client has requested that files be stored in the database to  
eliminate file permission complexities. How does your plugin work with  
file permissions (i.e., which user owns the files and where are they  
stored)?

---

<div class="post-metadata">

**Author:** ![johanatan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8491ac/32.png) [@johanatan](https://www.ruby-forum.com/u/johanatan)\
**Post date:** [December 5, 2005, 2:59am UTC](https://www.ruby-forum.com/t/injecting-image-method-into-model-classes/49376/7 "2005-12-05T02:59:27Z")

</div>

I actually decided try class\_eval first (which David Black suggested on  
the Ruby list). It worked, so I had no need to investigate further. I  
figured I’d share the results with everyone in case someone else can  
find a use for this (it actually should be a fairly common task).

Here it is:

## ImageBlob.rb

require ‘RMagick’  
include Magick

class ImageBlob

def ImageBlob.inject\_attrib\_assign\_methods( attr\_and\_sizes\_hash,  
consumer\_class )  
attr\_and\_sizes\_hash.each {|attr\_name, max\_size|  
code = %{  
def #{attr\_name}=( file )  
write\_attribute( ‘#{attr\_name}’, ImageBlob.getBlob( file,  
#{max\_size} ))  
end  
}  
consumer\_class.class\_eval code }  
end

def ImageBlob.getBlob( file, max\_image\_size )  
begin  
img = Image.from\_blob( file.read ).first  
if not img  
raise  
end

```
  img.format = "JPG"

  if img.rows > max_image_size or img.columns > max_image_size
    if img.rows > img.columns
      factor = max_image_size / img.rows.to_f
    else
      factor = max_image_size / img.columns.to_f
    end

    img = img.scale( factor )
  end

  retVal = img.to_blob
  GC.start
  return retVal
rescue
  return nil
end

```

end  
end

To use the class, from your model do:

ImageBlob.inject\_attrib\_assign\_methods( { “image” =\> 225,  
“thumbnailImage” =\> 125 }, self )

–Jonathan
