Reputation: 1021
I get a wonderful error in a rails project. I have a controller => prdocuts_controller.rb. I use options_from_collection_for_select
when I want create a new product. Every things are ok when I create a new product, and I can do this, but when I add file_field
to upload a picture to product, I get below error:
NoMethodError in Products#create
undefined method `map' for nil:NilClass
and when I remove file.field
, every thing are ok again and new product is save to database.
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
views/products/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 %>
log of system:
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>
I use 'paperclip', '~> 3.0' in this project. Any one can help me to find the problem?
Upvotes: 0
Views: 839
Reputation:
The cause of the error is @categories
is nil. Your product cannot save because of the ImageMagick errors so when you go back to show the view @categories
is not defined.
You need to include
@categories = Category.all
in your create
method in the case where the save fails. Alternatively consider a before_filter
in the controller so you can avoid having to repeat code in all your actions.
Why you are getting ImageMagick errors in the first place is another matter, but this is the cause of your map
error. Paperclip will throw a NotIdentifiedByImageMagickError
error where ImageMagick cannot parse the file - normally because it is not a valid image. You can test this out at the command line.
Upvotes: 1
Reputation: 12412
#map
could be called internally when processing this line from new.html.erb
:
<%= options_from_collection_for_select(@categories,:id, :name,@product.category_id) %>
I'd guess that it's called on @categories
.
Here is the problem:
When the user requests the /new
page, the new
action is processed and @categories
is normally initialized.
However, when you render 'new'
in create
, Rails will render that template without going through the action in the controller, thus @categories
will be nil
.
Try with:
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
Upvotes: 0