I recently refactored my DataMapper code, slowly rolling it out, and got it working on one database, but now I'm encountering problems when rolling it out to my expense database. Couldn't find the answer anywhere, and I've tried lots of fiddling.
I have a form (using Sinatra) that takes several inputs, prepended with "expense_", and it should take that data, send it to the database, and upload a receipt image to S3. But I'm getting an id of nil, and a LocalJumpError if I turn on DataMapper error reporting.
Here's my code:
DB update method:
def dm_update(method_list,model,params,param_prefix,use_last_entry_if_param_empty=true)
model_data = model.new
method_list.each do |meth|
# e.g. param is :expense_date, db column is :date
param_name = (param_prefix + meth.to_s).to_sym
param = params[param_name]
if use_last_entry_if_param_empty
# If true, use most recent entry from db - for use in settings changing
data = param.empty? ? model.last[meth] : param
else
data = param
end
model_data.send("#{meth}=", data)
end
model_data.save
end
Taking params and sending to method:
file_name = ("#{params[:expense_date]}_#{params[:expense_time].gsub(/:/, '')}_#{params[:expense_receipt_file][:filename]}")
temp_file = params[:expense_receipt_file][:tempfile]
expense_column_list = [:date,:time,:price,:currency,:description,:source,:receipt_filename]
params[:expense_receipt_filename] = file_name
dm_update(expense_column_list,Expense,params,"expense_",false)
upload(file_name, temp_file, "foo_bucket")
Datamapper class:
class Expense
include DataMapper::Resource
property :id, Serial, :required => true, :key => true
property :date, Date, :required => true
property :time, Time, :required => true, :default => Time.now
property :price, Float, :required => true
property :currency, String, :required => true, :default => "GBP"
property :description, String, :required => true
property :source, String, :required => true
property :receipt_filename, String
end
Ok, the answer to this was fairly simple when it came down to it.
I defactored the code, and went through it line by line.
The date param was stored in the format yyyy-mm-dd, and the time param was stored as hh:mm. Datamapper didn't like that time, which I'd fixed in the original version, but had failed to in the refactored version.
The fix ended up being to add the line:
temptime = Time.parse(params[:date] + " " + params[:time])
params[:time] = temptime
prior to calling the dm_update method. This fixed it, and it now works!