<?xml version="1.0" encoding="UTF-8"?>
<post>
  <body>h2. The problem

The simple problem I had was that I wanted to be able to associate a image (and thumbnails) to a article. Although this sounds easy, I had some trouble along the way (hence the post).

h2. Write the Migration models

&lt;pre&gt;&lt;code class="ruby"&gt;

class CreateImages &lt; ActiveRecord::Migration
  
  def self.up
    create_table :images do |t|
      t.column :parent_id,  :integer
      t.column :content_type, :string
      t.column :filename, :string    
      t.column :thumbnail, :string 
      t.column :size, :integer
      t.column :width, :integer
      t.column :height, :integer
      t.column :content_id, :integer
    end
  end

  def self.down
    drop_table :images
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
class CreateContents &lt; ActiveRecord::Migration
  
  def self.up
    create_table :contents do |t|
      t.column :title , :string
      t.column :summary, :text
      t.column :body, :text
      t.column :status, :string
    end
  end

  def self.down
    drop_table :contents
  end
end
&lt;/code&gt;
&lt;/pre&gt;

The only thing to note here is that I have placed a content_id foreign key into the image table, to allow them to be linked.

h2. Write the models

The models are going to have two different associations, both of type __has_one__. The first association has an extra condition that allows it to only return the parent image, the second association returns the parent image and all its associated thumbnails.

&lt;pre&gt;&lt;code class="ruby"&gt;
class Content &lt; ActiveRecord::Base
  has_one :image, :conditions =&gt; 'parent_id is null'
  has_one :all_images, :class_name =&gt; 'Image' # all photos + thumbnails
end
&lt;/code&gt;
&lt;/pre&gt;

The Image model has the standard attachment_fu declaration along side the thumbnail declarations.

&lt;pre&gt;&lt;code class="ruby"&gt;
class Image &lt; ActiveRecord::Base
  has_attachment :content_type =&gt; :image, 
                   :storage =&gt; :file_system,
                   :thumbnails =&gt; { :thumb =&gt; '107x76&gt;'}    
end
&lt;/code&gt;
&lt;/pre&gt;

h2. Write the form view

&lt;pre&gt;&lt;code class="ruby"&gt;
&lt;% form_for(:content, :url =&gt; { :action=&gt;'create'}, 
                      :html =&gt; { :multipart =&gt; true }) do |f| -%&gt;

&lt;p&gt;
  &lt;label for="title"&gt;Title&lt;/label&gt;&lt;br/&gt;
  &lt;%= f.text_field :title %&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;label for="summary"&gt;Summary&lt;/label&gt;&lt;br/&gt;
  &lt;%= f.text_area :summary %&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;label for="title"&gt;Body&lt;/label&gt;&lt;br/&gt;
  &lt;%= f.text_area :body %&gt;
&lt;/p&gt;

 &lt;p&gt;
    &lt;label for="image"&gt;Associate Image:&lt;/label&gt;&lt;br/&gt;
    &lt;%= file_field 'image','uploaded_data' %&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;%= submit_tag 'Create' %&gt;
  &lt;/p&gt;
&lt;% end -%&gt;
&lt;/code&gt;
&lt;/pre&gt;

As you can see I have placed the image in a different hash, as you can&#8217;t associate the file directly to the model. All of the other fields are pretty standard. To test out the update method you just need to change the URL to point to the update method and pass it the content id. I will leave it out here for simplicity.

h2. Write the controller

This is where I was having most trouble. No matter what I did, it just did not save the dam thing. So here is my create and update actions in my contents controller

&lt;pre&gt;&lt;code class="ruby"&gt;
def create
    #Create the content
    @content = Content.new(params[:content])
    respond_to do |format|
      if @content.save
        #Here comes the important bit!
        if !params[:image][:uploaded_data].blank?
          @content.image = Image.create(params[:image])       
        end
        flash[:notice] = 'Content was successfully created.'
        format.html { redirect_to :action=&gt;'show', :id=&gt;@content }
      else
        format.html { render :action =&gt; "new" }
      end
    end
  end  
&lt;/code&gt;
&lt;/pre&gt;

OK that was not that hard :). But I was having problems on the update action. The create action seemed to be working fine. Here is the update action.

&lt;pre&gt;&lt;code class="ruby"&gt;
  def update
      @content = Content.find(params[:id])
      respond_to do |format|
        if @content.update_attributes(params[:content])
          # Heres the important bit!
          if !params[:image][:uploaded_data].blank?
            #find current image
            @image = @content.image ||= Image.new
            @image = @content.image.build(params[:image])
            @image.save       
          end
          format.html { redirect_to :action=&gt;'show', :id=&gt;@content }
        else
          format.html { render :action =&gt; "edit" }
        end
      end
    end
 &lt;/code&gt;
&lt;/pre&gt;

As you can see I am using the build method to create the image. I am not sure why, but If I put the build method into the create method it just fails. Oh yeah and in a real application I would group the image methods into their own respective functions.

h2. The content view

So for all the code we have written we can now show the images that are associated with a specific article.

&lt;pre&gt;
&lt;code class="ruby"&gt;
  &lt;h2&gt;&lt;%=@content.title%&gt; &lt;/h2&gt;
  &lt;p&gt;&lt;%=@content.summary%&gt;&lt;/p&gt;

&lt;%if !@content.image.blank?%&gt; 
  &lt;p&gt;
    Original Image : &lt;%=image_tag @content.image.public_filename %&gt;
  &lt;/p&gt;
  &lt;p&gt;
    Thumbnail : &lt;%=image_tag @content.image.public_filename(:thumb) %&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;%=@content.body%&gt;
  &lt;/p&gt;
&lt;%end%&gt;
&lt;/code&gt;
&lt;/pre&gt;

h2. Outstanding issues

There a few bugs in attachment_fu that I came across, they are :

* The width and the height are not being set for thumbnails when I use ImageScience and attachment_fu.
* The size (in the database field) of the thumbnails are not correct. They just display the original file&#8217;s image size.

I will blog again regarding these issues in the near future.

h2. Code

In writing this post, I made a test rails app so I could make sure that the code I have above is correct and compiles without any errors.  If anyone wants this I can put a link to it here, just leave a comment.

As usual all comments welcome.

Hamza</body>
  <category-id type="integer">1</category-id>
  <comments-count type="integer">47</comments-count>
  <created-at type="datetime">2007-05-12T00:00:00Z</created-at>
  <id type="integer">21</id>
  <live type="boolean">true</live>
  <slug nil="true"></slug>
  <summary>As I mentioned in my previous post I am going to outline my experiences with attachment_fu. I will try to extend the brilliant "tutorial":http://clarkware.com/cgi/blosxom/2007/02/24 that first introduced me to attachment_fu and to ImageScience.</summary>
  <title>Fun with attachment_fu</title>
  <updated-at type="datetime">2008-12-14T19:35:09Z</updated-at>
  <user-id type="integer">1</user-id>
</post>
