代码之家  ›  专栏  ›  技术社区  ›  catinahat

NoMethodError-nil的未定义方法“map”:NilClass

  •  0
  • catinahat  · 技术社区  · 6 年前

    我对Rails和使用maps API构建商店定位应用程序很陌生。我有一个商店模型和一个关联的马桶模型,这样用户可以在添加商店时选择商店是否有马桶。但是,当我尝试添加一个商店并为可用的马桶选择“否”时,仍然会出现以下错误:

    NoMethodError in Stores#create
    Showing /mnt/c/Users/Me/Dropbox/coding/SpaetiApp/app/views/stores/_form.html.erb where line #7 raised:
    
    undefined method `map' for nil:NilClass
    Extracted source (around line #7):
    5
    6
    7
    8
    9
    10
    
        <%= f.input :address_line3, label: "Country", input_html: { value: "Germany"} %>
        <%= f.input :beer_cost, label: "Cost of a Berliner Pilsner" %>
        <%= select_tag(:toilet_id, options_for_select(@toilets), :prompt => "Toilet available?" ) %>
        <%= f.input :facilities, label: "Facilities" %>
    
        <%= f.button :submit %>
    
    Trace of template inclusion: app/views/stores/new.html.erb
    

    存储控制器:

    class StoresController < ApplicationController
    
        before_action :find_store, only: [:show, :edit, :update, :destroy]
    
        def index
            if params[:toilet].blank?
                @stores = Store.all.order("created_at DESC")
            else
                @toilet_id = Toilet.find_by(toilet_available: params[:toilet]).id
              @stores = Store.where(:toilet_id => @toilet_id).order("created_at DESC")
            end
        end
    
        def show
        end
    
        def edit
            @toilets = Toilet.all.map{ |t| [t.toilet_available, t.id] }
        end
    
        def update
            @store.toilet_id = params[:toilet_id] 
            if @store.update(store_params)
                redirect_to store_path(@store)
            else
                render 'edit'
            end
        end
    
        def new
            @store = current_user.stores.build
            @toilets = Toilet.all.map{ |t| [t.toilet_available, t.id] }
        end
    
        def create
            @store = current_user.stores.build(store_params)
            @store.toilet_id = params[:toilet_id] 
    
            if @store.save 
                redirect_to root_path
            else
                render 'new'
            end
        end
    
        def destroy
            @store.destroy
            redirect_to root_path
        end
    
        private
    
            def store_params
                params.require(:store).permit(:name, :address, :address_line2, :address_line3, :beer_cost, :toilet_id)
            end
    
            def find_store
                @store = Store.find(params[:id])
            end
    end
    

    Schema.rb模式:

    ActiveRecord::Schema.define(version: 20180814220216) do
    
      create_table "stores", force: :cascade do |t|
        t.string "name"
        t.string "address"
        t.float "beer_cost"
        t.text "facilities"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
        t.float "latitude"
        t.float "longitude"
        t.boolean "toilet"
        t.string "address_line2"
        t.integer "user_id"
        t.integer "toilet_id"
        t.string "address_line3"
      end
    
      create_table "toilets", force: :cascade do |t|
        t.string "toilet_available"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
      end
    
      create_table "users", force: :cascade do |t|
        t.string "email", default: "", null: false
        t.string "encrypted_password", default: "", null: false
        t.string "reset_password_token"
        t.datetime "reset_password_sent_at"
        t.datetime "remember_created_at"
        t.integer "sign_in_count", default: 0, null: false
        t.datetime "current_sign_in_at"
        t.datetime "last_sign_in_at"
        t.string "current_sign_in_ip"
        t.string "last_sign_in_ip"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
        t.index ["email"], name: "index_users_on_email", unique: true
        t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
      end
    
    end
    

    <%= simple_form_for @store,:html => { :multipart => true } do |f| %>
        <%= f.input :name, label: "Spaeti Name" %>
        <%= f.input :address, label: "Address" %>
        <%= f.input :address_line2, label: "City", input_html: { value: "Berlin" } %>
        <%= f.input :address_line3, label: "Country", input_html: { value: "Germany"} %>
        <%= f.input :beer_cost, label: "Cost of a Berliner Pilsner" %>
        <%= select_tag(:toilet_id, options_for_select(@toilets), :prompt => "Toilet available?" ) %>
        <%= f.input :facilities, label: "Facilities" %>
    
        <%= f.button :submit %>
    <% end %>
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Sebastián Palma    5 年前

    当它点击创建操作时,看起来“@store.save”返回false,因此它正在呈现“new”模板。但是,@厕所变量没有在create操作中设置,因此模板将其视为nil。

    将这一行也添加到您的创建操作中,这将删除您看到的错误:

    @toilets = Toilet.pluck(:toilet_available, :id) 
    

    您还可以将其设置为所需操作的“前”操作:

    before_action :set_toilets, except: [:show, :index]
    
    private
    
    def set_toilets 
      @toilets = Toilet.pluck(:toilet_available, :id) 
    end