We are a software consultancy based in Berlin, Germany. We deliver
high quality web apps in short timespans.

Upstream Agile GmbH

Hiding attachment_fu from your controllers

April 21, 2008 by alex

Yesterday I was using attachment_fu to attach photos to a couple of models. Since attachment_fu requires you to create an extra model for the photo, you usually have a one to one relationship between the model and the photo.

class Project
  has_one :project_photo
end

But now that you have two models you also have to deal with these in your controller and views, something along the lines of this:

class ProjectsController
  def new
    @project = Project.new
    @project.build_project_photo
  end

  def create
    @project = Project.new params[:project]
    @project.project_photo = @project.build_project_photo params[:project_photo]

  end
end

Sort of ugly if all you want is to add a photo to the Project model. But fear not, after adding the following piece of code to your model, you can transparently assign the photo to your project model in the view:

The tweaked model:

class Project
  has_one :project_photo, :dependent => :destroy # the attachment_fu model


  # a virtual attribute that saves a new photo in the photo model only when there's a new file uploaded

  def photo=(photo)
    self.project_photo = build_project_photo :uploaded_data => photo unless photo.to_s.blank?
  end
end

Now you can use a standard view:

< %- form_for(:project) do |f| -%>
  < %= f.file_field :photo %>
< %- end -%>

And a standard controller:

class ProjectsController
  def new
    @project = Project.new
  end

  def create
    @project = Project.new params[:project]
    @project.save
  end
end

(credits to this railscast for the idea of using a virtual attribute, I only added a bit of sugar for attachment_fu)