I have a problem getting attachments to work in a specific case…
I have the following data model (this is a relevant subset of it):
- a log can have many journals
- a journal belongs to a log and can have many attachments
- an attachment belongs to a journal
When adding on a new journal to an existing log the new journal form and
the corresponding controller handle the attachment as well and it works
just fine.
The user can also create a brand new log, and I included the journal
_form partial so that the user can at once add a journal and an
attachment when creating the new log – this doesn’t work so well.
Here’s what params[:attachment] looks like for the journal/attachment
controller:
{“attachment”=>#<File:C:/DOCUME~1/ELVIS.PRESLEY/LOCALS~1/Temp/CGI.3208.2>,
“comment”=>“asfd”}
And here’s what params[:attachment] looks like for
log/journal/attachment:
{“attachment”=>“random.jpg”, “comment”=>“asdf”}
As you can see, the one working correctly passes an actual file object
whereas the broken one just passes a string.
Here are the relevant files:
models/attachment.rb:
class Attachment < ActiveRecord::Base
belongs_to :journal
def attachment=(attachment_field)
self.name = base_part_of(attachment_field.original_filename)
self.content_type = attachment_field.content_type.chomp
self.data = attachment_field.read
end
def base_part_of(file_name)
name = File.basename(file_name)
name.gsub(/[^\w._-]/, ‘’)
end
end
controllers/journal_controller.rb:
…
def new
@journal = Journal.new
@attachment = Attachment.new
session[:log_id] = params[:id]
end
def create
@journal = Journal.new(params[:journal].merge(:user_id =>
session[:user_id], :log_id => session[:log_id]))
session[:log_id] = nil
@journal.attachments = [ Attachment.new(params[:attachment]) ]
unless params[:attachment][:attachment] == “”
if @journal.save
flash[:notice] = ‘Journal was successfully created.’
#redirect_to :action => ‘list’
redirect_to :controller => ‘log’, :action => ‘show’, :id =>
@journal.log_id
else
render :action => ‘new’
end
end
…
controllers/log_controller.rb:
…
def new
@log = Log.new
@logtypes = Type.find(:all).collect { |l| [l.name, l.id] }
@systems = System.find(:all).collect { |s| [s.name, s.id] }
@subsystems = Subsystem.find(:all).collect { |s| [s.name, s.id] }
@clients = Client.find(:all).collect { |c| [c.name, c.id] }
@companies = Company.find(:all).collect { |c| [c.name, c.id] }
@states = State.find(:all)
@journal = Journal.new
@attachment = Attachment.new
end
def create
@company = Company.find_by_name(params[:company][:name])
@client = Client.find_by_name(params[:client][:name])
if not @company
@company = Company.new(params[:company])
@company.save
end
if not @client
@client = Client.new(params[:client])
@client.save
end
params[:log][:company_id] = @company.id
params[:log][:client_id] = @client.id
@log = Log.new(params[:log])
@log.journals = [ Journal.new(params[:journal].merge(:user_id =>
session[:user_id])) ]
@log.journals[0].attachments = [ Attachment.new(params[:attachment])
] unless params[:attachment][:attachment] == “”
if @log.save
flash[:notice] = ‘Log was successfully created.’
redirect_to :action => ‘list’
else
render :action => ‘new’
end
end
…
views/journal/_form.rhtml:
<%= error_messages_for ‘journal’ %>
Content
<%= text_area 'journal', 'content' %>
Attachments
Comment: | <%= text_field("attachment", "comment") %> |
Upload your attachment: | <%= file_field("attachment", "attachment") %> |
views/log/_form.rhtml:
…
<%= render :partial => “journal/form” %>
…