【问题标题】:Rails connecting to jBuilder连接到 jBuilder 的 Rails
【发布时间】:2020-06-21 22:43:47
【问题描述】:

Chrome 错误:

jquery.js:8678 GET http://localhost:3000/people/locations/location_data.geojson 404 (Not Found)
send @ jquery.js:8678
ajax @ jquery.js:8327
jQuery.<computed> @ jquery.js:8464
getJSON @ jquery.js:8448
makeMapTwo @ mapPersonLeaflet.js:22
(anonymous) @ mapPersonLeaflet.js:10

我正在尝试通过has_many :through 关系获取值。三个主要数据库:人员、位置(包含街道地址和其他信息)和连接表years,它将人员链接到特定日期的特定地址。

# models/person.rb
class Person < ApplicationRecord
  has_many :years, dependent: :destroy 
  has_many :locations, through: :years

# models/location.rb
class Location < ApplicationRecord
  has_many :years
  has_many :people, through: :years

# models/year.rb
class Year < ApplicationRecord
  belongs_to :location
  belongs_to :person

years 将该人链接到特定日期的特定地址。

来自views/people/show.html.erb(当然是特定人的页面,我希望显示有关此人的详细信息,包括与他们相关联的位置)。

<div id="map" class="map"></div>  
  <%= javascript_pack_tag 'mapPersonLeaflet' %>
<div>

来自javascript/packs/mapPersonLeaflet.js

document.addEventListener('DOMContentLoaded', function () {
  makeMapTwo(); // LINE 10 in Chrome error above
});
function makeMapTwo(){
  var mapVar = L.map("map", { center: [34.040951, -118.258579], zoom: 13 });
  L.tileLayer('https://crores.s3.amazonaws.com/tiles/bkm/{z}/{x}/{y}.png').addTo(mapVar);
  $.getJSON("locations/location_data.geojson", function (data_data) { // LINE 22 in Chrome error above

我将 jBuilder 文件放在文件夹 views/people/locations/ 中,因为如果我将它放在 /people 中,则会出现错误:

ActiveRecord::RecordNotFound - Couldn't find Person with 'id'=location_data:
  app/controllers/people_controller.rb:118:in `set_person'

views/people/locations/location_data.json.jbuilder

json.type "FeatureCollection"
json.features @person.years do |year|
# Person has_many :locations, through: :years  
  json.type "Feature"    
  json.properties do
    json.set! "marker-color", "#C978F3" # will make this different for resto and resid a
     # json.title year.resto
    json.name year.full_name
  end
  json.geometry do
     json.type "Point"
     json.coordinates [year.location['longitude'], year.location['latitude']]
  end # json.geometry
end # features

永远不会访问上述文件。在 $.getJSON("locations/location_data.geojson", function (data_data) { 失败,终端出现错误

Started GET "/people/locations/location_data.geojson" for ::1 at 2020-03-09 18:47:05 -0700

NameError - uninitialized constant People:

我不知道它指的是哪个People。我知道它没有进入 .jbuilder 文档,因为如果我删除该文档中的所有内容,我会得到同样的错误。

我的路径有问题。在某处打错字?

来自routes.rb我有这行get 'people/locations/location_data', :defaults =&gt; { :format =&gt; 'json' }

PS。几个月前我尝试将其作为 OpenLayers 脚本,但由于我在 Leaflet 上取得了成功并希望回到我遇到相关问题的 OpenLayers Rails passing variable to jBuilder

【问题讨论】:

    标签: ruby-on-rails leaflet jbuilder


    【解决方案1】:

    你的路由没有指定它映射到的控制器和动作,添加:to参数来解决这个问题:

    get 'people/locations/location_data', :to => 'people#location_data', :defaults => { :format => 'json' }
    

    我假设路由器对路由的解释不同。

    【讨论】:

      【解决方案2】:

      我将首先创建一个嵌套路由,该路由提供 JSON 以填充地图:

      resources :people do
        # ...
        resources :locations, only: [:index], module: :people
      end
      

      然后设置一个控制器:

      module People
        class LocationsController < ApplicationController
          before_action :set_person
          # GET /people/1/locations.json
          def index
            respond_to do |f|
              f.json
            end
          end
      
          private
          def set_person
            @person = Person.eager_load(:locations)
                            .find(params[:person_id])
            @locations = @person.locations
          end
        end
      end
      

      您可以将模板重命名为/people/locations/index.json.jbuilder

      然后设置 map 元素,让它有一个 data 属性,告诉 javascript 从哪里加载 JSON:

      <%= content_tag :div, "",
              class: "map personal-map",
              data: { src: person_locations_path(@person, format: :json) }
      %>
      

      同时摆脱&lt;%= javascript_pack_tag 'mapPersonLeaflet' %&gt; - 对内联脚本标签说不

      然后,您可以在资产管道中创建一个脚本,查找具有 personal-map 类的元素并对其进行扩充:

      function personalMap(el){
        var map = L.map(el, { center: [34.040951, -118.258579], zoom: 13 });
        L.tileLayer('https://crores.s3.amazonaws.com/tiles/bkm/{z}/{x}/{y}.png')
          .addTo(map);
        $.getJSON(el.dataset.src).done(function(data){
          L.geoJSON(data).addTo(map)
        });
        return map;
      }
      
      document.addEventListener('DOMContentLoaded', function () {
        // you could also use $('.personal-map').each or the less sucky ES6
        // equivilent
        var personalMaps = Array.prototype.map.call(
          document.getElementsByClassName('personal-map'), 
          personalMap
        );
      });
      

      如果您想将任何其他信息从视图传递到地图(如边界或缩放),请使用地图元素上的数据属性。

      【讨论】:

      • 我故意选择不使用 geoJSON 内容类型。它无论如何都可以与 JSON 一起使用,并且需要更少的摆弄。
      • 感谢您提升我的知识。 content_tag 未正确解析。我进入页面{:class=&gt;"map personal-map", :data=&gt;{:src=&gt;"/people/108/locations.json"}},当然geojson 没有构建,地图也没有显示。 rails routes => ` person_locations GET /people/:person_id/locations(.:format) people/locations#index` apidock.com/rails/ActionView/Helpers/TagHelper/content_tag 没有为我提供任何线索
      • 是的,我应该意识到它需要带有内容(或块)的第二个参数。这就是为什么它将选项视为内容。已编辑。此外,官方 Rails 文档位于 http://api.rubyonrails.org。 apidock 只是一个令人讨厌的网站,其中包含大量谷歌果汁。
      • &lt;div class="map personal-map" data-src="/people/108/locations.json"&gt;&lt;/div&gt;locations.json 尚未构建。 Chrome 和终端都没有错误。我将模块置于关注点,但include LocationsController 然后导致错误wrong argument type Class (expected Module) 这表明这不是引入模块的正确方法。错误是include,因为清空关注文件会导致相同的错误。
      • “未建成”究竟是什么意思?是否正在发送 ajax 请求(检查 chrome 中的网络选项卡)?回应是什么?
      猜你喜欢
      • 1970-01-01
      • 2018-09-01
      • 2013-07-01
      • 1970-01-01
      • 2013-01-29
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 2014-08-17
      相关资源
      最近更新 更多