Как мне преобразовать эту строку Ruby в массив?

Как лучше всего превратить следующую строку Ruby в массив (я использую ruby 1.9.2 / Rails 3.0.11)

Консоль Rails:

<code>>Item.first.ingredients
=> "[\"Bread, whole wheat, 100%, slice\", \"Egg Substitute\", \"new, Eggs, scrambled\"]"
>Item.first.ingredients.class.name
=> "String"
>Item.first.ingredients.length
77
</code>

Желаемый вывод:

<code>>Item.first.ingredients_a
["Bread, whole wheat, 100%, slice", "Egg Substitute", "new, Eggs, scrambled"]
>Item.first.ingredients_a.class.name
=> "Array
>Item.first.ingredients_a.length
=> 3
</code>

Если я сделаю это, например:

<code>>Array(Choice.first.ingredients)
</code>

Я получаю это:

<code>=> ["[\"Bread, whole wheat, 100%, slice\", \"Egg Substitute\", \"new, Eggs, scrambled\", \"Oats, rolled, old fashioned\", \"Syrup, pancake\", \"Water, tap\", \"Oil, olive blend\", \"Spice, cinnamon, ground\", \"Seeds, sunflower, kernels, dried\", \"Flavor, vanilla extract\", \"Honey, strained/extracted\", \"Raisins, seedless\", \"Cranberries, dried, swtnd\", \"Spice, ginger, ground\", \"Flour, whole wheat\"]"] 
</code>

Я уверен, что должен быть какой-то очевидный способ решить эту проблему.

Для ясности, это будет редактируемым в поле textarea в форме, поэтому должно быть сделано как можно более безопасным.

 Mark Thomas10 мая 2012 г., 03:07
Лучший способ сделать это - изменитьingredients метод.
 Mark Thomas10 мая 2012 г., 03:54
Если вы не можете изменить метод ингредиентов, вы должны хотя бы опубликовать его, чтобы мы могли увидеть, что он выводит. Отмена этого, безусловно, возможна, но мы должны увидеть это, чтобы помочь.

Ответы на вопрос(6)

Решение Вопроса
class Item
  def ingredients_a
    ingredients.gsub(/(\[\"|\"\])/, '').split('", "')
  end
end
strip off the extraneous characters split into array elements using the separating pattern
 10 мая 2012 г., 11:18
+1 это самыйdirect ответ на вопрос.elegant Ответ требует больше информации о том, как массив стал строкой.
 Nathan W10 мая 2012 г., 04:12
Мне очень понравился ответ JSON.parse, но этот, вероятно, должен работать и, вероятно, является самым прямым решением проблемы.
 08 сент. 2016 г., 18:51
отрицательный голос без объяснения причин? :(

просто используйтеJSON.parse()

измените ваш метод ингредиентов, если вы действительно не хотите двух отдельных методов, которые возвращают строку и массив соответственно. Я предполагаю, что вы действительно хотите только вернуть массив. Ради аргумента, скажем, ваш метод ингредиентов в настоящее время возвращает переменную с именемingredients_string, Измените ваш метод так:

def ingredients
  ...
  ingredients_array = ingredients_string.split('"')
  ingredients_array.delete_if { |element| %(", "[", "]").include? element }
  ingredients_array
end
 10 мая 2012 г., 03:52
Для справки, я думаю, что предложение Эндрю Маршалла JSON.parse гораздо более элегантно.

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

class Item << ActiveWhatever
  serialize :ingredients, Array

  ...
end

Больше информации о сериализации здесьhttp://api.rubyonrails.org/classes/ActiveRecord/Base.html

 Nathan W10 мая 2012 г., 03:22
Да, так что я полагаю, что я мог бы потенциально хранить данные в поле сериализуемого массива, но я все еще начинаю со строки, которая выглядит как в формате, указанном выше :) .. поэтому мне нужно преобразовать ее в массив, чтобы получить ее там :).

ingredients метод возвращает.inspect вывод результирующего возвращаемого массива. Это не очень полезный вывод. У вас есть возможность изменить его, чтобы вернуть простой массив?

Что бы яnot сделать это использоватьeval, что только увеличит хакерство уже взломанного кода.

 Nathan W10 мая 2012 г., 04:20
@andrew, я разрешаю редактирование массива через текстовую область в форме. Этот пример показывает, как информация поступает через параметры. Если есть другие, лучшие методы для поддержки массива, было бы здорово услышать.
 10 мая 2012 г., 04:29
@NathanW Тогда я предполагаю этоis JSON отправляется? Если это не так, это должно быть.
 10 мая 2012 г., 03:46
@NathanW Я думаю, что проблема в том, почему ваш массив в строковой форме в первую очередь?
 10 мая 2012 г., 03:56
+1 Хотя это больше похоже на комментарий, он довольно близок к тому, что, вероятно, является правильным ответом с ограниченной информацией.
 Nathan W10 мая 2012 г., 03:18
Я согласен с вами в том, что вы хотите избежать 'eval' apos; если возможно. Я мог бы потенциально переопределить метод или сделать другие вызовы, если это необходимо, но у меня все еще остается вопрос о том, каков наилучший способ преобразования строки в массив, поскольку тип данных может не измениться. Я мог бы потенциально хранить данные в сериализуемом текстовом поле и хранить там массив в некотором формате, который я предполагаю.

JSON.parse "[\"Bread, whole wheat, 100%, slice\", \"Egg Substitute\", \"new, Eggs, scrambled\"]"
#=> ["Bread, whole wheat, 100%, slice", "Egg Substitute", "new, Eggs, scrambled"]

это позволяет избежать многих ужасов использованияeval.

Хотя вы действительно должны подумать о том, почему вы в первую очередь храните свои данные таким образом, и подумайте об их изменении, чтобы вам не пришлось это делать. Кроме того, вероятно, что вы должны анализировать его в массивеingredients так что метод возвращает что-то более значимое. Если вы почти всегда выполняете одну и ту же операцию с возвращаемым значением метода, этот метод неверен.

 10 мая 2012 г., 03:55
@MarkThomas Полностью согласен, но информации оwhy данные представлены в формате строки, так что нужно (к сожалению) делать предположения.
 10 мая 2012 г., 03:52
Я бы сделал это, только если бы это был JSON. Только взгляд наingredients метод скажет.

Ваш ответ на вопрос