Вложенный массив изменяется на строку значений, переходящих из JavaScript в Rails

#javascript #ruby-on-rails #openlayers

#javascript #ruby-on-rails #openlayers

Вопрос:

Использование OpenLayers (хотя я думаю, что это проблема JS / Rails) Я рисую прямоугольник,

 var source = new VectorSource();

function addInteraction() {
  var draw = new Draw({
    source: source,
    type: 'Circle',
    geometryFunction: createBox()
  });
  map.addInteraction(draw);
  draw.on('drawend', function(event) {
    var boxCoords = event.feature.getGeometry().getCoordinates()
    console.log(" boxCoords: ", boxCoords);
    document.getElementById('year_snippet_extent').innerHTML = boxCoords;
  });
}

addInteraction();
 

Вывод журнала консоли (четыре угла прямоугольника, но возвращается к началу, именно так OpenLayers обрабатывает поля рисования, т. Е. Это многоугольник):

  boxCoords:  
 [Array(5)]
 0: Array(5)
 0: (2) [977.8497980044467, 710.486212043731]
 1: (2) [1341.059647947079, 710.486212043731]
 2: (2) [1341.059647947079, 754.3238572469668]
 3: (2) [977.8497980044467, 754.3238572469668]
 4: (2) [977.8497980044467, 710.486212043731]
 

Что записывается в year_snippet_extent поле в форме редактирования: 977.8497980044467,710.486212043731,1341.059647947079,710.486212043731,1341.059647947079,754.3238572469668,977.8497980044467,754.3238572469668,977.8497980044467,710.486212043731

Я хочу сохранить это в Postgres в виде массива. Тип данных Postgres — text [], тип данных Rails тот же, хотя моя миграция была array , add_column :years, :snippet_extent, :text, array:true .

Поле в редактировании <%= form.input :snippet_extent, label: 'Automatically filled when snippet is drawn' %>

Что такое переформатирование массива? Или я должен использовать другой подход?

Я не мог понять, как box_coords сохранить snippet_extent напрямую, поэтому придумал этот обходной путь. Я мог бы проанализировать то, что сохранено для моих целей, но подумал, что смогу сделать эту работу правильно.

Вот что я написал, чтобы получить то, что я считаю правильным форматом (мне нужны только нижний левый и верхний правый углы):

  var minx = Math.round(boxCoords.[0].[0].[0])
 var miny = Math.round(boxCoords.[0].[0].[1])
 var maxx = Math.round(boxCoords.[0].[2].[0])
 var maxy = Math.round(boxCoords.[0].[2].[1])
 var snippetExtent = "{[["   String(minx)   ","   String(miny)   "],["   String(maxx)   ","   String(maxy)   "]]}"
 

Не так сложно, но я надеялся, что это не обязательно. Я округляю, чтобы упростить чтение, а точность не имеет смысла.

Комментарии:

1. Да, вы обнаружили, что объект массива не является HtmlString . Но поскольку движок JavaScript тоже это знает, он делает все возможное, чтобы интерпретировать ваши намерения: он строит ваш массив для вас. Если вам нужен определенный формат, лучшим подходом было бы предоставить строку там, где она требуется.

2. Итак, мне нужно проанализировать массив и сделать его любой строкой, которую я хочу? Это то, что я сделал изначально, но затем мне пришлось «разобрать» его, чтобы использовать, и это показалось мне большой проблемой, поскольку Rails, JavaScript и Postgres знают о массивах. Но если это то, чего хочет JS!

3. Первое, что нужно понять при вычислениях клиент / сервер, это то, что они не связаны напрямую. Им нужен протокол связи (на самом деле несколько), чтобы помочь перенести информацию с клиента на сервер. Этот протокол HTTP — Hyper_TEXT_ — это то, что передает протокол. На этом фоне one понимает, что структуры данных на клиенте должны быть сериализованы в строки перед отправкой с использованием протокола. также понятно, что текст должен быть переведен обратно в соответствующую структуру данных на другом конце. JavaScript и Ruby используют один и тот же инструментарий: JSON.*

4. Спасибо. Это хорошее напоминание. В Rails и JavaScript много волшебства, и это продолжается только до сих пор. Я переписываю его сейчас.

Ответ №1:

Мы используем листовку, но делаем что-то очень похожее: при рисовании геометрии мы показываем модальную форму с формой и устанавливаем скрытое текстовое поле, содержащее геометрию.

Мы используем postgis, поэтому мы сразу сохраняем представление geojson в этом скрытом поле. Не совсем уверен, возможно ли это с помощью OpenLayers (уверен, что это так, просто не сразу его нашел). Но, возможно, это не самый простой формат для вас? Если вы используете postgis и activerecord-postgis gem, вы можете просто назначить geojson геометрии.

Но если нет, вам придется самостоятельно проанализировать geojson (что не слишком сложно, но определенно немного сложнее).

Итак, как упоминалось в комментариях: JSON — гораздо лучший формат обмена, всегда используемый в API, поскольку и JS, и Rails очень хорошо с ним справляются.

Итак, в вашем JS вы могли бы написать:

 document.getElementById('year_snippet_extent').innerHTML = JSON.stringify(boxCoords);
 

и в конце rails вы должны преобразовать его обратно в то, что было помещено в него следующим образом:

 box_coords = JSON.parse(params[:year_snippet_extent])
 

Комментарии:

1. Рэнди Касберн: Спасибо, что указали мне правильное направление, и особенно спасибо @nathanvda за конкретику. Мне пришлось провести много рефакторинга, поскольку я устроил такой беспорядок, пытаясь делать разные вещи. Также пришлось создать столбец замены как:json. Когда я все заработаю, я покажу решение, хотя оно в значительной степени соответствует приведенному выше. КСТАТИ, хранение в (скрытом) поле — это просто JS и Rails. У меня установлен PostGIS, потому что я думал, что он мне понадобится, но до сих пор использовал с Postgres. Однако я должен попробовать PostGIS.