我在Ruby on Rails 4.0上有一个带有jruby 1.7.9的表单。我使用Mongoid而不是ActiveRecord。
当我使用DateTime对象和附件(多部分文件)提交表单时,它会抛出错误“无法复制Fixnum”。应用程序将DateTime对象存储为数据库中的Unix时间戳。
如果我在没有DateTime的情况下提交表单,则会成功保存附件。如果我提交没有附件的表单,它会按预期保存DateTime。当两者都实现时,它会抛出错误。
我该如何解决这个问题?
完整错误消息是:
can't dup Fixnum
Extracted source (around line #222):
220 self.data[name] = DateTime.parse(value).to_time.to_i
221 when 'datetime'
222 self.data[name] = DateTime.parse(value).to_time.to_i
223 when 'time'
224 self.data[name] = DateTime.parse(value).to_time.to_i
225 when 'number'
Rails.root: /Users/mehmetdavut/Documents/
Application Trace | Framework Trace | Full Trace
app/models/content.rb:222:in `change_property_types'
app/models/content.rb:214:in `change_property_types'
app/controllers/contents_controller.rb:56:in `update'
Request
Parameters:
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"viv0CO7QKSY8kklTiLAXpdGkqv2W7fiW3Zrf2ZnKjpc=",
"content"=>{"data"=>{"second_datetime"=>"2014-04-07 17:20:00"},
"url"=>"",
"language_id"=>"ffef8bca0000ffd4b4cee70e",
"device_id"=>"52eeb9964d65682809130000",
"template_id"=>"fff02c4d0000a37cc11eed8f",
"layout_id"=>"fff02c760000a37cc11eed90",
"access"=>{"requires_authentication"=>"0",
"requires_ssl"=>"0"},
"discoverability"=>{"title"=>"",
"description"=>"",
"keywords"=>"",
"sitemap_change_frequency"=>"",
"sitemap_priority"=>"",
"exclude_from_search"=>"0"},
"menu"=>{"alias"=>"",
"class"=>"",
"passive"=>"0",
"script"=>"",
"show_in_navigation"=>"0",
"show_in_sitemap"=>"0"},
"taxonomy"=>{"category_id"=>"",
"tags"=>""},
"published_at"=>"2014-03-14T12:01:24-08:00",
"unpublished_at"=>""},
"attachments"=>{"second_file"=>#<ActionDispatch::Http::UploadedFile:0x162cbfcf @original_filename="Screen Shot 2014-03-13 at 00.38.30.png",
@headers="Content-Disposition: form-data; name=\"attachments[second_file]\"; filename=\"Screen Shot 2014-03-13 at 00.38.30.png\"\r\nContent-Type: image/png\r\n",
@tempfile=#<Tempfile:/var/folders/cs/6xmggtv54nq8l2xw77mzhtcr0000gn/T/RackMultipart20140314-18002-csbpyn>,
@content_type="image/png">},
"commit"=>"Update Content",
"page_id"=>"fff02ce20000a37cc11eed96",
"id"=>"fff02ce20000a37cc11eed97"}
这是“change_property_types”方法:
def change_property_types
self.data.each do |name, value|
property = self.page.document.properties.where(name: name).first
unless value.blank?
case property.type
when 'date'
self.data[name] = DateTime.parse(value).to_time.to_i
when 'datetime'
self.data[name] = DateTime.parse(value).to_time.to_i
when 'time'
self.data[name] = DateTime.parse(value).to_time.to_i
when 'number'
self.data[name] = value.to_i
when 'file'
# self.attachments << Attachment.create(file: value)
else
self.data[name] = value
end
end
end
end
答案 0 :(得分:0)
发生此错误是因为value是fixnum。 以下代码的输出是什么?
...
when 'datetime'
raise value.class.inspect
...
你的表格是什么样的?
如果你这样做会发生什么:
unless value.blank?
case property.type
when 'date'
self.data[name] = DateTime.parse(value.to_s).to_time.to_i
when 'datetime'
self.data[name] = DateTime.parse(value.to_s).to_time.to_i
when 'time'
self.data[name] = DateTime.parse(value.to_s).to_time.to_i
when 'number'
self.data[name] = value.to_i
when 'file'
# self.attachments << Attachment.create(file: value)
else
self.data[name] = value
end
end
答案 1 :(得分:0)
您的代码中有很多重复项。这使得它非常密集并且难以追踪您的错误。我可能会这样重构。注意:这是代码未经测试的因素
# DRY up your code :)
def change_property_types
data.each do |name, value|
next if value.blank?
self.data[name] = if get_property_type =~ /file/i
set_attachments(value)
elsif value.present? && check_dateishness
DateTime.parse(value).to_time.to_i
else
value
end
end
end
private
def check_dateishness
%w(date datetime time).include?(get_property_type)
end
# handle the case where attachements may be nil.
def set_attachements(value)
if self.attachments.blank?
self.attachments = [Attachment.create(file: value)]
else
self.attachments << Attachment.create(file: value)
end
end
# You could probably memoize this... i.e. @some_var ||= ...
def get_property_type
page.document.properties.where(name: name).first.type
end
或者您可以更多地分解您的代码。
# Or decompose it to better track down errors
...
def change_property_types
data.each do |name, value|
next if value.blank?
if property_type =~ /file/
# you need to handle the attachments.nil?
attachments << Attachment.create(file: value)
else
data[name] = parse_it(property).to_i
end
end
end
private
def property_type
@property ||= page.document.properties \
.where(name: name).first.type
end
# Really this case statement can be simplified
# as you could check the class of the object, i.e.
# value.is_a?(Date) or value.is_a?(Time) and since
# the only Ruby class that needs to_time is Date
# you simplify the code
def parse_it(value)
case value.type
when 'time' then time_parser(value)
when 'date' then date_parser(value)
when 'datetime' then datetime_parser(value)
else value
end
end
def date_parser(date)
return date.to_time if date.is_a?(Date)
Date.parse(date.to_s).to_time
end
# Time has a to_i function
def time_parser(time)
return time if time.is_a?(Time)
Time.parse(time.to_s)
end
# DateTime has a to_i function
def datetime_parser(datetime)
return datetime if datetime.is_a?(DateTime)
DateTime.parse(datetime.to_s)
end
...