我在rails项目中遇到了一个很棒的错误。我有一个控制器=> prdocuts_controller.rb。我想在创建新产品时使用options_from_collection_for_select
。当我创建新产品时,每件事情都可以,我可以这样做,但当我添加file_field
将图片上传到产品时,我会收到以下错误:
NoMethodError in Products#create
undefined method `map' for nil:NilClass
当我删除file.field
时,每件事情都会好起来,新产品会保存到数据库中。
products_controller.rb
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
layout "product"
# GET /products
# GET /products.json
def index
@categories = Category.all
@products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
@categories = Category.all
@product = Product.new
end
# GET /products/1/edit
def edit
@categories = Category.all
@product = Product.all
end
# POST /products
# POST /products.json
def create
@product = Product.new(product_params)
@product.responsibility = current_user.responsibility
@product.date_time = Time.now
respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: @product }
else
format.html { render action: 'new' }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if @product.update(product_params)
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
@product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:category_id, :name, :code, :date_time, :describe, :picture)
end
end
product.rb
class Product < ActiveRecord::Base
has_attached_file :picture, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/missing.png"
belongs_to :category
end
视图/产品/ new.html.erb
<%= form_for @product, :html => {multipart: true} do |f| %>
<% if @product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% @product.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="control-group">
<label class="control-label">Product Name</label>
<%= f.text_field :name, :class => "m-wrap span8", :placeholder => "enter product name" %>
</div>
<div class="control-group">
<label class="control-label">Product Code</label>
<%= f.text_field :code, :class => "m-wrap span8", :placeholder => "enter product code" %>
</div>
<div class="control-group">
<label class="control-label" >Category</label>
<div class="controls">
<div class="select2-wrapper">
<select name="product[category_id]" class="select2_category m-wrap span8">
<%= options_from_collection_for_select(@categories,:id, :name,@product.category_id) %>
</select>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">Product Code</label>
<%= f.text_area :describe, :class => "m-wrap span8", :placeholder => "enter describe" %>
</div>
<br/>
<%= f.file_field :picture %>
<br/>
<div class="action">
<%= f.submit "Save change", :class => "btn green" %>
</div>
<% end %>
系统日志:
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 17 ORDER BY "users"."id" ASC LIMIT 1
Command :: identify -format '%wx%h,%[exif:orientation]' "C:/Users/MGH~1.119/AppData/Local/Temp/6f87f43a62513173b9edfea7b58ee2d020140504-660-1luu1b5.jpg[0]" 2>NUL
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: identify -format '%wx%h,%[exif:orientation]' "C:/Users/MGH~1.119/AppData/Local/Temp/6f87f43a62513173b9edfea7b58ee2d020140504-660-1luu1b5.jpg[0]" 2>NUL
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Responsibility Load (3.0ms) SELECT "responsibilities".* FROM "responsibilities" WHERE "responsibilities"."user_id" = ? ORDER BY "responsibilities"."id" ASC LIMIT 1 [["user_id", 17]]
(0.0ms) begin transaction
(0.0ms) rollback transaction
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Rendered products/_form.html.erb (12.0ms)
Rendered products/new.html.erb within layouts/product (13.0ms)
Completed 500 Internal Server Error in 132ms
ActionView::Template::Error (undefined method `map' for nil:NilClass):
27: <div class="controls">
28: <div class="select2-wrapper">
29: <select name="product[category_id]" class="select2_category m-wrap span8">
30: <%= options_from_collection_for_select(@categories,:id, :name,@product.category_id) %>
31: </select>
32: </div>
33: </div>
我使用'paperclip','〜&gt;这个项目中的3.0'。任何人都可以帮我找到问题吗?
答案 0 :(得分:1)
错误的原因是@categories
为零。由于ImageMagick错误导致您的产品无法保存,因此当您返回显示视图时@categories
未定义。
您需要包含
@categories = Category.all
在保存失败的情况下,在create
方法中。或者考虑控制器中的before_filter
,这样您就可以避免在所有操作中重复代码。
为什么首先出现ImageMagick错误是另一回事,但这是导致map
错误的原因。 Paperclip将抛出NotIdentifiedByImageMagickError
错误,其中ImageMagick无法解析文件 - 通常是因为它不是有效图像。您可以在命令行中对此进行测试。
答案 1 :(得分:0)
#map
处理此行时,可以在内部调用 new.html.erb
:
<%= options_from_collection_for_select(@categories,:id, :name,@product.category_id) %>
我猜它是在@categories
上调用的。
问题在于:
当用户请求/new
页面时,系统会处理new
操作,并且@categories
通常会初始化。
但是,当您render 'new'
中的create
时,Rails将在不经过控制器中的操作的情况下呈现该模板,因此@categories
将为nil
。
尝试:
def new
@categories = Category.all
@product = Product.new
end
def create
@product = Product.new(product_params)
@product.responsibility = current_user.responsibility
@product.date_time = Time.now
respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: @product }
else
format.html {
@categories = Category.all
render action: 'new'
}
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end