Reputation: 516
What is the best way to turn the following Ruby String into an Array (I'm using ruby 1.9.2/Rails 3.0.11)
Rails console:
>Item.first.ingredients
=> "[\"Bread, whole wheat, 100%, slice\", \"Egg Substitute\", \"new, Eggs, scrambled\"]"
>Item.first.ingredients.class.name
=> "String"
>Item.first.ingredients.length
77
The desired output:
>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
If I do this, for instance:
>Array(Choice.first.ingredients)
I get this:
=> ["[\"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\"]"]
I'm sure there must be some obvious way to solve this.
For clarity, this will be editable in a textarea field in a form, so should be made as secure as possible.
Upvotes: 5
Views: 4776
Reputation: 4479
class Item
def ingredients_a
ingredients.gsub(/(\[\"|\"\])/, '').split('", "')
end
end
Upvotes: 5
Reputation: 96914
What you have looks like JSON, so you can do:
JSON.parse "[\"Bread, whole wheat, 100%, slice\", \"Egg Substitute\", \"new, Eggs, scrambled\"]"
#=> ["Bread, whole wheat, 100%, slice", "Egg Substitute", "new, Eggs, scrambled"]
this avoids a lot of the horrors of using eval
.
Though you should really think about why you're storing your data like that in the first place, and consider changing it so you don't have to do this. Further, it's likely that you should be parsing it to an array in ingredients
so that the method returns something more meaningful. If you're almost always doing the same operation on a method's return value, the method is wrong.
Upvotes: 9
Reputation: 1367
Like Mark Thomas said, modify your ingredients method, unless you really want two separate methods that return a string and an array, respectively. I'll assume you really only want to return an array. For the sake of argument, let's say your ingredients method currently returns a variable named ingredients_string
. Modify your method like so:
def ingredients
...
ingredients_array = ingredients_string.split('"')
ingredients_array.delete_if { |element| %(", "[", "]").include? element }
ingredients_array
end
Upvotes: 1
Reputation: 4622
Not sure if this comes into play, but what happens if you want to use an array as an attribute, you might want to consider serialize..
class Item << ActiveWhatever
serialize :ingredients, Array
...
end
More info on serialize here http://api.rubyonrails.org/classes/ActiveRecord/Base.html
Upvotes: 0
Reputation: 37507
It looks like the ingredients
method returns the .inspect
output of the resulting return array. It is not very useful output that way. Do you have the ability to change it to return a plain array?
What I would not do is use eval
, which will just increase the hackiness of already hacky code.
Upvotes: 1