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

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

精简版

我的image#create image.save动作在image.save调用时失败,并Undefined method "name" for nil:NilClass抛出Undefined method "name" for nil:NilClass 。 Image模型包括通过paperclip gem上传的文件。

扔我的部分:

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

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

额外细节

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

  • 我正在使用paperclip并试图通过S3进行存储,尽管当我在我的Image模型中完全注释掉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=#>}, "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' :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  { # :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

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

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

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

 <%= f.file_field :picture_file_name %> 

什么时候应该是:

 <%= f.file_field :picture %> 

paperclipgem理解:picture是上传的文件,用于将文件名保存到正确的字段。 我只是低估了易用性!

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

经过大量的搜索和调试。 这个问题的主要症状是带有文件字段的表单被制作为多部分表单而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 

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

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

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

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

导致错误

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 %> 

由于这个问题花了很多我的甜蜜时光,我认为它可能对你有所帮助。