#<FritkotsController 错误消息的未定义局部变量或方法“fritkot”

Undefined local variable or method `fritkot' for #<FritkotsController error message

请耐心等待,因为我仍在努力学习 JS、Ajax 和 RoR。

如果您不想通读所有这些废话,TL;DR:我在尝试将来自常规 ruby 模型的 geojson 数据合并到地图中时遇到问题 (mapbox.js) ,添加标记弹出窗口并使用 Js 和 AJAX.

我正在尝试将 mapbox.js(版本 2.2.2)库包含到 Rails (4.2.4) 中,但我不断收到此错误消息:

Undefined local variable or method `fritkot' for FritkotController

这是我控制器中的代码:

# GET /fritkots
# GET /fritkots.json

 def index
   @fritkots = Fritkot.all
   @geojson = Array.new
   build_geojson(fritkot, @geojson) ## Where the error appears

   respond_to do |format|
     format.html
     format.json { render json: @geojson }
   end
 end

 # FIX: To be extracted into a class method (.self_geojson)?

 def build_geojson(fritkots, geojson)
   fritkots.each do |fritkot|
     geojson << GeojsonBuilder.build_fritkot(fritkot)
   end
 end

此刻,我创建了一个 GeojsonBuilder class,但我想这应该是一个模块或一个扩展或包含我的 Fritkot 模型的助手?或者是周围的其他方式? (很抱歉,如果我把事情搞混了,只是最近几天我一直在研究这个问题,一切都变得混乱了)。

代码如下:

 class GeojsonBuilder

  def build_fritkot(fritkot, geojson)
    geojson << {
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [fritkot.longitude, fritkot.latitude]
      },
      properties: {
        title: fritkot.title,
        address: fritkot.address,
        :"marker-color" => "#f86767",
        :"marker-size" => "medium",
        :"marker-symbol" => "circle", #fast_food
      }
    }
  end
end

map.js

上的代码
 $(document).on("ready", function() {
  L.mapbox.accessToken = "pk.eyJ1IjoiZHNvbGlzIiwiYSI6ImViNzgwOGZmZmVlMmVjYzg5ZjZhNzYxNDE3MWE0ZTFhIn0.0E-Z_FCmS8VHPRY07tVSEQ";
 var map = L.mapbox.map("map", "dsolis.ni76oel2", { zoomControl: false }.setView([50.854975, 4.3753899], 7);

  map.featureLayer.on("ready", function(e) {
  getEvents(map);
  });
});

function getevents(map) {
  var $loading_wheel = $("#spinning-wheel")
  $loading_wheel.show();
  $.ajax({
    dataType: 'text',
    url: '/events.json',
    success:function(events) {
    $loading_wheel.hide();
      var geojson = $.parseJSON(events);
      map.featureLayer.setGeoJSON({
        type: "FeatureCollection",
        features: geojson
      });
      addEventPopups(map);
     },
    error:function() {
      $loading_wheel.hide();
      alert("Opps something went wrong.");
    }
  });
}

function addEventPopups(map) {
  map.featureLayer.on("layeradd", function(e) {
    var marker = e.layer;
    var properties = marker.feature.properties;
    var popupContent = '<div class="marker-popup">' + '<h3>' + properties.title + '</h3>' +
                     '<h4>' + properties.address + '</h4>' + '</div>';
    marker.bindPopup(popupContent, {closeButton: false, minWidth: 300});
   });
 }

如有任何帮助,我们将不胜感激。谢谢。

编辑 1: 添加错误截图

ScreenShot of where I get the error

编辑 2: 在出现错误信息的地方添加评论

编辑 3: 根据@snkashis 的建议修复一些代码。

编辑 4: 这是 public gist 和代码。

但是,我仍然无法 load/view 在地图上显示我的对象。打开控制台时出现此类错误:

Uncaught Error: Invalid LatLng object: (NaN, NaN)o.LatLng @ leaflet-src.js:1122o.extend.coordsToLatLng @ leaflet-src.js:6206o.extend.geometryToLayer @ leaflet-src.js:6160L.FeatureGroup.extend._initialize @ feature_layer.js:94L.FeatureGroup.extend._initialize @ feature_layer.js:85L.FeatureGroup.extend.setGeoJSON @ feature_layer.js:37$.ajax.success @ map.self-9667db8b4bdc056a4ee3b0d7d005cf31e80d182ed0fc56a57b58ef94a30dd618.js?body=1:25jQuery.Callbacks.fire @ jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1:3149jQuery.Callbacks.self.fireWith @ jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1:3261done @ jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1:9315jQuery.ajaxTransport.options.send.callback @ jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1:9719

这是更新后的代码

控制器:

  # GET /fritkots
  # GET /fritkots.json
  def index
    @fritkots = Fritkot.all
    # @geojson = Array.new
    # build_geojson(fritkot, @geojson)

    @geojson = @fritkots.map do |fritkot|
      GeojsonBuilder.build_fritkot(fritkot)
    end

    respond_to do |format|
      format.html
      format.json { render json: @geojson }
    end
  end

  # FIX: To be extracted into a .self_geojson?
  def build_geojson(fritkots, geojson)
    fritkots.each do |fritkot|
      geojson << GeojsonBuilder.build_fritkot(fritkot)
    end
  end

  # GET /fritkots/1
  # GET /fritkots/1.json
  def show
    @fritkot = Fritkot.find(params[:id])
  end

map.js:

$(document).on("ready", function() {
  L.mapbox.accessToken = "pk.eyJ1IjoiZHNvbGlzIiwiYSI6ImViNzgwOGZmZmVlMmVjYzg5ZjZhNzYxNDE3MWE0ZTFhIn0.0E-Z_FCmS8VHPRY07tVSEQ";
  var map = L.mapbox.map("map", "dsolis.ni76oel2", { zoomControl: false }).setView([50.846026, 4.3491641], 13);

    map.featureLayer.on("ready", function(e) {
      getEvents(map);
    });
  });

  function getEvents(map) {
    var $loading_wheel = $("#spinning-wheel")
    $loading_wheel.show();
    $.ajax({
      dataType: 'text',
      url: '/fritkots.json',
      success:function(fritkots) {
        $loading_wheel.hide();
        var geojson = $.parseJSON(fritkots);
        map.featureLayer.setGeoJSON({
          type: "FeatureCollection",
          features: geojson
        });
        addEventPopups(map);
      },
      error:function() {
        $loading_wheel.hide();
        alert("Oops something went wrong.");
      }
    });
  }

  function addEventPopups(map) {
    map.featureLayer.on("layeradd", function(e){
      var marker = e.layer;
      var properties = marker.feature.properties;
      var popupContent = '<div class="marker-popup">' + '<h3>' + properties.title + '</h3>' +
                         '<h4>' + properties.address + '</h4>' + '</div>';
      marker.bindPopup(popupContent, {closeButton: false, minWidth: 300});
    });
  }

GeojsonBuilder:

class GeojsonBuilder

  def self.build_fritkot(fritkot)
    geojson = {
        type: "Feature",
        geometry: {
          type: "Point",
          coordinates: [fritkot.longitude, fritkot.latitude]
        },
        properties: {
          title: fritkot.title,
          address: fritkot.address,
          :"marker-color" => "#FFFFFF",
          :"marker-size" => "medium",
          :"marker-symbol" => "circle", #fast_food
        }
      }
    geojson
  end
end

我离解决这个问题越来越近了。

我根本不了解 geojson,所以如果我跑题了,我深表歉意,但这是我以编程方式看到的内容。

您声明了 2 个变量:fritkotsgeojson。然后,您将 fritkot@geojson 发送到 build_gejson()build_geojson() 接收 fritkotsgeojson 并在 'sequence'(数组?列表?)上运行 fritkot

我的 'guess' 是你应该发送 fritkotsbuild_geojson() - 如果那是错误的,请告诉我,我会删除答案。

[编辑]

另一种可能性,您是否应该将 Fritkot 而不是 fritkot 发送到 build_gejson()

[/edit]

您仍在发送 undefined fritkot to the build_geojson controller method, when it is expecting an array. 其次,我看不出在上一行中创建一个空数组有什么意义。 我建议暂时在您的 index 方法中执行此操作,然后将 GeojsonBuilder 修改为仅采用一个参数和 return 一件事。

@geojson = @fritkots.map do |fritkot|
    GeojsonBuilder.build_fritkot(fritkot)
end

def build_fritkot(fritkot, geojson) 更改为 def build_fritkot(fritkot) 并使其成为 return 它生成的哈希(意思是没有 <<)而不是附加到给定数组。

更进一步,why run this expensive loop 每次有人点击您的 index 时都生成 GeoJSON...我建议您以某种方式缓存它。