使用 Mongoid ORM 在 Rails API 中为 GeoJson 数据创建模型的确切方法是什么?

What is the exact way of creating a model for GeoJson data in Rails API using Mongoid ORM?

我只是好奇如何使用 mongoid 处理嵌套的 json 对象,相信这是可能的。 这是来自我的前端应用程序的示例 GeoJson 数据:

{
    "type": "Feature",
    "properties": {
        "name": "A Cool Feature",
        "amenity": "A Cool Label",
        "popupContent": "This is a cool area.."
    },
    "geometry": {
        "type": "polygon",
        "coordinates": [
            {
                "lat": 41.47566020027821,
                "lng": 269.65942382812506
            },
            {
                "lat": 40.17047886718111,
                "lng": 266.81396484375006
            },
            {
                "lat": 38.41055825094609,
                "lng": 268.86840820312506
            },
            {
                "lat": 38.24680876017446,
                "lng": 270.91186523437506
            },
            {
                "lat": 40.871987756697415,
                "lng": 271.57104492187506
            }
        ]
    }
}

这是我的控制器(非常基本的)

class Api::V1::GeoDataController < ApplicationController

  # GET /geo_data
  def index
    @geo_data = GeoDatum.all
    render json: @geo_data
  end
  
  # POST /geo_data
  def create
    @geo_datum = GeoDatum.new(geo_datum_params)
    if @geo_datum.save
      render json: @geo_datum
    else
      render error: { error: 'Unable to create GeoDatum.' }, status: 400
    end    
  end
  
  private

  def geo_datum_params
    params.require(:geo_datum).permit(:type, :properties, :geometry)
  end

end

模特在这里:

class GeoDatum
  include Mongoid::Document
  include Mongoid::Timestamps
  field :type, type: String
  field :properties, type: Property
  field :geometry, type: Geometry

  embeds_one :properties, class_name: "Property"
  embeds_one :geometry, class_name: "Geometry"
end

class Property
  include Mongoid::Document
  field :name, type: String
  field :amenity, type: String
  field :popupContent, type: String

  embedded_in :geo_datum, class_name: "GeoDatum"
end

class Geometry
  include Mongoid::Document
  field :type, type: String
  field :coordinates, type: Array

  embeds_many :coordinates, class_name: "LatLng"
  embedded_in :geo_datum, class_name: "GeoDatum"
end

class LatLng
  attr_reader :longitude, :latitude

  def initialize(lng, lat)
    @longitude = lng
    @latitude = lat
  end

  embedded_in :geometry, class_name: "Geometry"
end

这是 POST 请求的控制台日志:

Started POST "/api/v1/geo_data" for 192.168.1.209 at 2020-07-13 21:58:53 +0000
Processing by Api::V1::GeoDataController#create as */*
  Parameters: {"type"=>"Feature", "properties"=>{"name"=>"A Cool Feature", "amenity"=>"A Cool Label", "popupContent"=>"This is a cool area.."}, "geometry"=>{"type"=>"polygon", "coordinates"=>[{"lat"=>41.47566020027821, "lng"=>269.65942382812506}, {"lat"=>40.17047886718111, "lng"=>266.81396484375006}, {"lat"=>38.41055825094609, "lng"=>268.86840820312506}, {"lat"=>38.24680876017446, "lng"=>270.91186523437506}, {"lat"=>40.871987756697415, "lng"=>271.57104492187506}]}, "geo_datum"=>{"type"=>"Feature", "properties"=>{"name"=>"A Cool Feature", "amenity"=>"A Cool Label", "popupContent"=>"This is a cool area.."}, "geometry"=>{"type"=>"polygon", "coordinates"=>[{"lat"=>41.47566020027821, "lng"=>269.65942382812506}, {"lat"=>40.17047886718111, "lng"=>266.81396484375006}, {"lat"=>38.41055825094609, "lng"=>268.86840820312506}, {"lat"=>38.24680876017446, "lng"=>270.91186523437506}, {"lat"=>40.871987756697415, "lng"=>271.57104492187506}]}}}
Unpermitted parameters: :properties, :geometry
MONGODB | [11] 172.17.0.1:27017 #1 | leaflet.insert | STARTED | {"insert"=>"geo_data", "ordered"=>true, "documents"=>[{"_id"=>BSON::ObjectId('5f0cd91d44041302afa3ea2a'), "type"=>"Feature", "updated_at"=>2020-07-13 21:58:53.921377228 UTC, "created_at"=>2020-07-13 21:58:53.921377228 UTC}], "$db"=>"leaflet", "lsid"=>...
MONGODB | [11] 172.17.0.1:27017 | leaflet.insert | SUCCEEDED | 0.005s
Completed 200 OK in 14ms (Views: 0.7ms | MongoDB: 0.0ms | Allocations: 1098)

重点是 Unpermitted parameters: :properties, :geometry 正在发生,这些属性根本没有被提供。 任何帮助将不胜感激。

如果你想要嵌套对象,那么你可以将它包装在一个散列或数组中......就像这样

params.require(:foo).permit(:type, :properties => [:name, :amenity, :popUpContent], geometry: [:type, { coordinates: [:lat, :lng] }])

doc