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)