Post GeoJSON 数据和表单数据到 Rails 4 个应用

Post GeoJSON data with form data to Rails 4 app

我有一个创建 "Activity." 的网页 使用简单的表单,用户填写一些关于 activity 的基本信息:

#new.html.erb
<%= simple_form_for @activity do |f| %>
    <%= f.input :name, label: "Activity name", input_html: { id: "create_activity_name_field" }, hint: "At least 7 characters" %>
    <%= f.input :type, label: "Activity type", input_html: { id: "create_activity_type_field" }, as: :select, :include_blank => false, collection: Activity.types.keys.to_a %>
    <%= f.input :date_field, input_html: { id: "create_activity_date_field" }, as: :string %>
    <%= f.input :time_field, input_html: { id: "create_activity_time_field" }, as: :string %>
    <% f.button :submit, :class => "btn btn-primary" -%>
<% end %>

不过,我也在用MapBox来显示地图。用户将单击地图上的点来为 activity 制定路线。当用户完成路线绘制后,我可以为这条路线提取 GeoJSON 数据。

我想将 javascript 用于 POST 带有表单数据的 GeoJSON 数据。在后端,我将 rails 将 GeoJSON 转换为 KML 文件,并使用 Paperclip 将其上传到 Amazon S3。其余数据可以保存,Paperclip 会给我一个 URL 到 KML 文件,我可以将其与 activity.

相关联

我是一个 Rails 菜鸟,我不知道该怎么做,也不知道如何解决这个问题。我考虑过使用 javascript 的 FormData。我对这种方法很感兴趣,因为实现看起来很简单,但显然它只能真正处理 key/value 对,而不是复杂的嵌套 JSON 数据。

非常感谢任何建议或策略。如果有人能给出详细的答案,我将不胜感激,因为就像我说的,我刚刚接触 rails 和网络开发几周。

您可能想在这里做的是防止在 JS 中使用表单的默认行为:

$('form').submit(function(e) { 
 e.preventDefault();
 var form = $('form');
 var form_data_json = JSON.stringify(form.serializeArray());
 form_plus_geojson = form_data_json.concat(Geojson);

在 JS 中获取数据(这应该很容易,但您并没有真正说明如何从 mapbox 中提取数据)。

然后通过AJAX发回数据(不要忘记两端验证)

if (my_data_is_not_good/empty/whatever) { 
    console.log('nop')
 } else {
         $.ajax({ 
         type: 'post',
         url: Yourcontrollerpostaction, 
         data: form_plus_geojson,
         dataType: "JSON",

发送数据后,您希望恢复正常的表单提交 post 行为并提交表单。

         complete: function() { 
            this.off('submit');
            this.submit();
         }
     });
 }

});

那么你只需要在你的控制器中解析数据即可。

def post_controller
  if request.xhr?
    my_hash = JSON.parse(params[:mydata]) 
  else 
    normal post behavior 
  end
end

一切都是快速的伪代码,您可能需要修复一些东西,因为我还没有测试过它,但它应该可以工作。 显然,现在我们正在做 ajax 中的所有事情,您不需要完整的函数回调,可以删除那部分。

感谢@jDay 为我指明了正确的方向——特别是连接 JSON 数据。但是,我无法让他的特定解决方案在我的应用程序上运行,于是我开始尝试另一种方法,在我看来,这种方法更直接一些。

我使用 Rails simple_form_for gem 制作表格,指定远程 post 调用:

#new.html.erb
<%= simple_form_for @activity, :url => '/activities', :method => :post, :remote => true, html: {id: :activity_create_form, "data-type" => :json} do |f| %>
    <%= f.input :name, label: "Activity name", input_html: { id: "create_activity_name_field" }, hint: "At least 7 characters" %>
    <%= f.input :type, label: "Activity type", input_html: { id: "create_activity_type_field" }, as: :select, :include_blank => false, collection: Activity.types.keys.to_a %>
    <%= f.input :date_field, input_html: { id: "create_activity_date_field" }, as: :string %>
    <%= f.input :time_field, input_html: { id: "create_activity_time_field" }, as: :string %>
    <%= f.button :submit, :class => "btn btn-primary", input_html: {id: "create_activity_submit_btn"} -%>
<% end %>

然后我使用 jQuery 来劫持表单提交按钮并附加一个带有 GeoJSON 数据的不可见表单元素。但是,数据必须进行字符串化才能发送:

#activity_new.js
$("form").submit( function (e) {
        e.preventDefault();

        $('<input />')
                    .attr('type', 'hidden')
                    .attr('name', 'routeGeoJson')
                    .attr('value', JSON.stringify(polyline.toGeoJSON()))
                    .appendTo(this);
        return true;
});

(这里,"polyline"是我在地图上画的LeafletL.polyline对象。)

在控制器中,您将获得如下参数:

{"utf8"=>"✓", "activity"=>{"name"=>"A jaunt in the woods", "type"=>"walk", "date_field"=>"2015-09-08", "time_field"=>"07:00"}, "routeGeoJson"=>"{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[-118.38855654001236,33.95361274499209],[-118.36624056100845,33.97681937760982]]}}", "commit"=>"Create Activity", "controller"=>"activities", "action"=>"create"}

由于 "routeGeoJson" 数据仍然是字符串形式,我通过使用 JSON gem(我相信包含默认在 Rails 4):

def create
   geojson = JSON.parse(params[:routeGeoJson])
   # do something...
end

你得到你的 GeoJSON 散列:

{"type"=>"Feature", "properties"=>{}, "geometry"=>{"type"=>"LineString", "coordinates"=>[[-118.42014223337173, 33.98407904797006], [-118.37825685739517, 33.956175751601826]]}}