添加:multipart => true throws未定义方法“name”错误

时间:2011-08-14 04:49:50

标签: ruby-on-rails file-upload paperclip

我在这个上画了一个空白。这是我的问题:

短版

我的image#create操作在image.save来电失败并投掷Undefined method "name" for nil:NilClass。 Image模型包括通过paperclip gem上传文件。

投掷我的部分:

只有在提交表单中包含:multipart => true时才会出现错误

当我拿出它时,表单完美无缺,当然图像文件没有上传。有关失败位置的详细信息,请参阅下面的堆栈跟踪。在尝试为INSERT语句引用某些内容时,它看起来像是一个零值,但我无法弄清楚是什么。我的控制器参数看起来没问题,我通过记录器检查以确保新的Image实例在它到达保存调用之前正确构建。

额外详情

我会尝试包含我能想到的所有细节,按重要性排序:

  • 我正在使用paperclip并尝试通过S3进行存储,但是当我在我的图像模型中完全注释掉has_attached_file行时仍会出现此问题。

  • Image是Collection中的嵌套资源,它在to_param方法中以slug引用。

  • 我有多租户系统的基础知识(又名Basecamp风格的用户子域,通过中心用户模型实现,范围涵盖所有组件)。

传递给控制器​​的参数

{"utf8"=>"✓",
 "authenticity_token"=>"JYCMky7851j5cW4ChSWUCCL/02iePf6i/QWAgR8q5tE=",
 "image"=>{"name"=>"My testerific image 2",
 "slug"=>"my-testerific-image-2",
 "description"=>"w",
 "collection_id"=>"2",
 "sort"=>"3",
 "picture_file_name"=>#<ActionDispatch::Http::UploadedFile:0x00000101b3f540 @original_filename="David's pic 005.jpeg",
 @content_type="image/jpeg",
 @headers="Content-Disposition: form-data; name=\"image[picture_file_name]\"; filename=\"David's pic 005.jpeg\"\r\nContent-Type: image/jpeg\r\n",
 @tempfile=#<File:/var/folders/df/mvsv5cs137gbyl8r7h428zp40000gn/T/RackMultipart20110814-64770-duz6wu>>},
 "commit"=>"Create Image",
 "collection_id"=>"my-new-collection"}

完整堆栈跟踪

activesupport (3.0.9) lib/active_support/whiny_nil.rb:48:in 'method_missing'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:20:in 'block in initialize'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'yield'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'default'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'block in initialize'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'yield'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'default'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'block in initialize'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'yield'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'default'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'block in initialize'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'yield'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'default'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:22:in 'block in initialize'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:63:in 'yield'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:63:in 'default'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:63:in 'accept'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:325:in 'block in dump_ivars'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:323:in 'each'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:323:in 'dump_ivars'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:85:in 'visit_Object'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:63:in 'accept'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:36:in '<<'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych.rb:165:in 'dump'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/core_ext.rb:13:in 'psych_to_yaml'
activerecord (3.0.9) lib/active_record/connection_adapters/abstract/quoting.rb:34:in 'quote'
activerecord (3.0.9) lib/active_record/connection_adapters/sqlite3_adapter.rb:45:in 'quote'
arel (2.0.10) lib/arel/visitors/to_sql.rb:327:in 'quote'
arel (2.0.10) lib/arel/visitors/to_sql.rb:70:in 'block in visit_Arel_Nodes_Values'
arel (2.0.10) lib/arel/visitors/to_sql.rb:69:in 'map'
arel (2.0.10) lib/arel/visitors/to_sql.rb:69:in 'visit_Arel_Nodes_Values'
arel (2.0.10) lib/arel/visitors/visitor.rb:15:in 'visit'
arel (2.0.10) lib/arel/visitors/to_sql.rb:59:in 'visit_Arel_Nodes_InsertStatement'
arel (2.0.10) lib/arel/visitors/visitor.rb:15:in 'visit'
arel (2.0.10) lib/arel/visitors/visitor.rb:5:in 'accept'
arel (2.0.10) lib/arel/visitors/to_sql.rb:18:in 'block in accept'
activerecord (3.0.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:111:in 'with_connection'
arel (2.0.10) lib/arel/visitors/to_sql.rb:16:in 'accept'
arel (2.0.10) lib/arel/tree_manager.rb:20:in 'to_sql'
arel (2.0.10) lib/arel/select_manager.rb:217:in 'insert'
activerecord (3.0.9) lib/active_record/relation.rb:14:in 'insert'
activerecord (3.0.9) lib/active_record/persistence.rb:274:in 'create'
activerecord (3.0.9) lib/active_record/timestamp.rb:47:in 'create'
activerecord (3.0.9) lib/active_record/callbacks.rb:277:in 'block in create'
activesupport (3.0.9) lib/active_support/callbacks.rb:414:in '_run_create_callbacks'
activerecord (3.0.9) lib/active_record/callbacks.rb:277:in 'create'
activerecord (3.0.9) lib/active_record/persistence.rb:250:in 'create_or_update'
activerecord (3.0.9) lib/active_record/callbacks.rb:273:in 'block in create_or_update'
activesupport (3.0.9) lib/active_support/callbacks.rb:429:in '_run_save_callbacks'
activerecord (3.0.9) lib/active_record/callbacks.rb:273:in 'create_or_update'
activerecord (3.0.9) lib/active_record/persistence.rb:40:in 'save'
activerecord (3.0.9) lib/active_record/validations.rb:43:in 'save'
activerecord (3.0.9) lib/active_record/attribute_methods/dirty.rb:21:in 'save'
activerecord (3.0.9) lib/active_record/transactions.rb:240:in 'block (2 levels) in save'
activerecord (3.0.9) lib/active_record/transactions.rb:292:in 'block in with_transaction_returning_status'
activerecord (3.0.9) lib/active_record/connection_adapters/abstract/database_statements.rb:139:in 'transaction'
activerecord (3.0.9) lib/active_record/transactions.rb:207:in 'transaction'
activerecord (3.0.9) lib/active_record/transactions.rb:290:in 'with_transaction_returning_status'
activerecord (3.0.9) lib/active_record/transactions.rb:240:in 'block in save'
activerecord (3.0.9) lib/active_record/transactions.rb:251:in 'rollback_active_record_state!'
activerecord (3.0.9) lib/active_record/transactions.rb:239:in 'save'
app/controllers/images_controller.rb:42:in 'block in create'
actionpack (3.0.9) lib/action_controller/metal/mime_responds.rb:264:in 'call'
actionpack (3.0.9) lib/action_controller/metal/mime_responds.rb:264:in 'retrieve_response_from_mimes'
actionpack (3.0.9) lib/action_controller/metal/mime_responds.rb:191:in 'respond_to'
app/controllers/images_controller.rb:40:in 'create'
actionpack (3.0.9) lib/action_controller/metal/implicit_render.rb:4:in 'send_action'
actionpack (3.0.9) lib/abstract_controller/base.rb:150:in 'process_action'
actionpack (3.0.9) lib/action_controller/metal/rendering.rb:11:in 'process_action'
actionpack (3.0.9) lib/abstract_controller/callbacks.rb:18:in 'block in process_action'
activesupport (3.0.9) lib/active_support/callbacks.rb:451:in '_run__867212960703161301__process_action__2360218484576085785__callbacks'
activesupport (3.0.9) lib/active_support/callbacks.rb:410:in '_run_process_action_callbacks'
activesupport (3.0.9) lib/active_support/callbacks.rb:94:in 'run_callbacks'
actionpack (3.0.9) lib/abstract_controller/callbacks.rb:17:in 'process_action'
actionpack (3.0.9) lib/action_controller/metal/instrumentation.rb:30:in 'block in process_action'
activesupport (3.0.9) lib/active_support/notifications.rb:52:in 'block in instrument'
activesupport (3.0.9) lib/active_support/notifications/instrumenter.rb:21:in 'instrument'
activesupport (3.0.9) lib/active_support/notifications.rb:52:in 'instrument'
actionpack (3.0.9) lib/action_controller/metal/instrumentation.rb:29:in 'process_action'
actionpack (3.0.9) lib/action_controller/metal/rescue.rb:17:in 'process_action'
actionpack (3.0.9) lib/abstract_controller/base.rb:119:in 'process'
actionpack (3.0.9) lib/abstract_controller/rendering.rb:41:in 'process'
actionpack (3.0.9) lib/action_controller/metal.rb:138:in 'dispatch'
actionpack (3.0.9) lib/action_controller/metal/rack_delegation.rb:14:in 'dispatch'
actionpack (3.0.9) lib/action_controller/metal.rb:178:in 'block in action'
actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:62:in 'call'
actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:62:in 'dispatch'
actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:27:in 'call'
rack-mount (0.6.14) lib/rack/mount/route_set.rb:148:in 'block in call'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:93:in 'block in recognize'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:68:in 'optimized_each'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:92:in 'recognize'
rack-mount (0.6.14) lib/rack/mount/route_set.rb:139:in 'call'
actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:493:in 'call'
warden (1.0.5) lib/warden/manager.rb:35:in 'block in call'
warden (1.0.5) lib/warden/manager.rb:34:in 'catch'
warden (1.0.5) lib/warden/manager.rb:34:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/best_standards_support.rb:17:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/head.rb:14:in 'call'
rack (1.2.3) lib/rack/methodoverride.rb:24:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/params_parser.rb:21:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/flash.rb:182:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/session/abstract_store.rb:149:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/cookies.rb:302:in 'call'
activerecord (3.0.9) lib/active_record/query_cache.rb:32:in 'block in call'
activerecord (3.0.9) lib/active_record/connection_adapters/abstract/query_cache.rb:28:in 'cache'
activerecord (3.0.9) lib/active_record/query_cache.rb:12:in 'cache'
activerecord (3.0.9) lib/active_record/query_cache.rb:31:in 'call'
activerecord (3.0.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:354:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/callbacks.rb:46:in 'block in call'
activesupport (3.0.9) lib/active_support/callbacks.rb:416:in '_run_call_callbacks'
actionpack (3.0.9) lib/action_dispatch/middleware/callbacks.rb:44:in 'call'
rack (1.2.3) lib/rack/sendfile.rb:107:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/remote_ip.rb:48:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/show_exceptions.rb:47:in 'call'
railties (3.0.9) lib/rails/rack/logger.rb:13:in 'call'
rack (1.2.3) lib/rack/runtime.rb:17:in 'call'
activesupport (3.0.9) lib/active_support/cache/strategy/local_cache.rb:72:in 'call'
rack (1.2.3) lib/rack/lock.rb:11:in 'block in call'
<internal:prelude>:10:in 'synchronize'
rack (1.2.3) lib/rack/lock.rb:11:in 'call'
actionpack (3.0.9) lib/action_dispatch/middleware/static.rb:30:in 'call'
railties (3.0.9) lib/rails/application.rb:168:in 'call'
railties (3.0.9) lib/rails/application.rb:77:in 'method_missing'
railties (3.0.9) lib/rails/rack/log_tailer.rb:14:in 'call'
rack (1.2.3) lib/rack/content_length.rb:13:in 'call'
rack (1.2.3) lib/rack/handler/webrick.rb:52:in 'service'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/httpserver.rb:111:in 'service'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/httpserver.rb:70:in 'run'
/Users/daw/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/server.rb:183:in 'block in start_thread'

更新

根据要求,型号代码:

class Image < ActiveRecord::Base
  belongs_to :collection
  belongs_to :user

  before_save :create_slug

  has_attached_file :picture,
    #:styles => { 
        #   :thumb => '100x100>', 
        #   :full => '800x800>' 
        #},
        :storage => :s3,
        :s3_credentials => Rails.root.join( 'config', 's3.yml' ),
        :path => ":id/:style/:filename"


  def to_param
    self.name.parameterize
  end
  private
  def create_slug
    self.slug = self.to_param
  end
end

更新2

我将使用Image构建的:multipart => true实例与没有它的实例进行了比较,并确认唯一的区别是文件上传字段picture_file_name。没有:multipart => true,它是一个带文件名的字符串(不足为奇)。有了它,它就是ActionDispatch::Http::UploadedFile的一个实例。鉴于堆栈跟踪显示在to_yaml调用期间失败,可能问题在于UploadedFile实例转换为YAML?

4 个答案:

答案 0 :(得分:7)

好吧,我终于屈服了,通过记录器输出跟踪了我的ActiveRecord源代码。事实证明,正如我所怀疑的那样,它无法保存UploadedFile,因为它无法将其转换为YAML。

然而,这是因为我犯了一个愚蠢的错误。在我的提交表格中,我有:

<%= f.file_field :picture_file_name %>

应该是:

<%= f.file_field :picture %>

paperclip gem知道:picture是上传的文件,并使用背景魔法将文件名保存到正确的字段。我只是低估了我的易用性!

通常情况下,我会删除这个微不足道的问题,但看到我犯了这个错误,其他人可能会在将来,并且很少有人指出我的解决方案。所以我会继续帮助将来搜索类似密集的开发人员!

答案 1 :(得分:1)

经过大量的搜索和调试。这个问题的主要症状是带有文件字段的表单被制作为多部分表单而rails 3.2无法保存数据,因为它试图保存数据库中不存在的其他参数(文件的归档)对象)。

获取适当的值并将它们保存到某个变量并从params中删除文件哈希似乎解决了这个问题!

以下是使用rails 3.2

保存在数据库中的工作代码示例
file = params[:document][:file].tempfile.read
params[:document].delete(:file)
@document = Document.new(params[:document])   
respond_to do |format|
  if @document.save
@document.file = file
@document.save
    format.html { redirect_to @document, notice: 'Document was successfully created.' }
    format.json { render json: @document, status: :created, location: @document }
  else
    format.html { render action: "new" }
    format.json { render json: @document.errors, status: :unprocessable_entity }
  end
end

答案 2 :(得分:0)

您没有发布,但我认为您应该在表单中使用:html => { :multipart => true }而不只是:multipart => true,例如:

form_for object, :html => { :multipart => true } do |o|
    ...

答案 3 :(得分:0)

即使我有正确的字段,我也花了大约一个星期来处理相同的错误。

导致我所有头痛的愚蠢只是视图中标签的顺序。

导致错误

NoMethodError in DatenightsController#create undefined methodname' for nil:NilClass

<%= f.file_field :photo %>
<%= f.text_field :name %>

以上引用错误的解决方案(这里的序列/顺序很重要)

<%= f.text_field :name %>
<%= f.file_field :photo %>

由于这个问题耗费了我很多甜蜜的时间,我认为这对你有帮助。