I have an array of custom objects in it. Those objects have a parameter called name which is a concatenation of 2 strings having a delimiter in between. Eg: name could be Some#Data where 'Some' is first string and 'Data' is another and # is a delimiter.
My intention is update the name parameter for all the objects inside the array such that the param would only have 'Data' (i.e. remove 'Some#') and store the objects inside another array after updating. Below is the code:
final_array = array1.select do |object|
object.name = object.name.match(/#(.*?)$/)
end
When I print object.name.match(/#(.*?)$/) this gives me output as:
#<MatchData "#Data" 1:"Data">
Out of this output, how do I get "Data" from this MatchData. I tried object.name.match(/#(.*?)$/)[1] but it didn't work. Or do I need to change my regex?
I would use #each and #gsub methods:
array.each do |object|
object.name = object.name.gsub(/^.+#/, '')
end
Related
I have a method do_stuff that takes a string as a value. However, an array of two strings is occasionally passed in. In this situation, I need to convert the array to a single string (without commas). So for example, ["hello", "world"] should become "hello world".
So, if value = array, join the two strings, otherwise leave it alone.
The following line I have does what I want, but I am struggling with actually "saving" the value before passing it to the method do_other_stuff.
def do_stuff(value)
value.join("") if value.is_a? Array
do_other_stuff(value)
end
So I think i am close, but what would be the best way to ensure value is manipulated before passing it to do_other_stuff ?
join does not change your object, you're wasting its return value
value = value.join if value.is_a? Array
Note that "" is the default for the join parameter, so I got rid of it
Replace
value.join("") if value.is_a? Array
With
value = value.join("") if value.is_a? Array
Basically you need to reassign result back to value
Use duck typing instead of checking the class:
def do_stuff(value)
do_other_stuff(value.try(:join, '') || value)
end
.try is from ActiveSupport and will return nil if the object does not respond to the method. In plain old ruby you would write this as:
def do_stuff(value)
do_other_stuff(value.respond_to?(:join) ? value.join("") : value)
end
I save an array of strings to my rails database, but when I go to use it in the view, I believe it is printing the string definition of the array. Am I dealing with JSON here? (aka when it saves to the database is it just an array wrapped in a string?)
How do I have it so that in my view, it simply displays the items?
<%= record.items %>
displays inside my html tag:
["item1", "item2", "item3"]
I tried iterating through record.items.each do |item| but that did not work.
If you're saving an "exact" array as a String, then Array#each won't work, because isn't a method in the String class.
Maybe isn't the best option, but you could use JSON.parse and this way get your array and be able to iterate over each object inside:
require 'json'
str = '["item1", "item2", "item3"]'
JSON.parse(str).each { |item| p item }
# "item1"
# "item2"
# "item3"
In order this work your string must be an array, in your example the second item is missing its double quote.
You could consider working with serialization or array data types depending on you current database.
A better approach to your issue is to serialize your items column. I think by default it's Array but you can use Hash or JSON.
class Record < ActiveRecord::Base
serialize :items
end
Calling record.items returns the data exactly the way you need. If you go with this you'll have to update your old records to support it.
for example, I have an array which is structured as follow:
my_array = [["..\\..\\..\\Source\\file1.c"], ["..\\..\\..\\Source\\file2.c"]]
This array is produced by this code:
File.open(file_name) do |f|
f.each_line {|line|
if line =~ /<ClCompile Include="..\\/
my_array << line.scan(/".*.c"/)
end
}
end
Later in the code I'm working on the array:
my_array .each {|n| f.puts n.gsub(/\\/,"//")}
As you can see, would like to replace all the backslashes with forward slashes on the elements within the array. The elements presents paths to source files. On the end I will output these paths within an other file.
I get this error:
undefined method `gsub' for [["..\\..\\..\\Source\\file1.c"], ["..\\..\\..\\Source\\file2.c"]]:Array (NoMethodError)
Any idea?
You have an array of arrays, so if you want to keep it like that, you would need to have 2 loops.
Otherwise, if you change your variable to this: my_array = ["..\\..\\..\\Source\\file1.c", "..\\..\\..\\Source\\file2.c"] your code should work.
UPDATE
if you can not control my_array, and it is always an array of one item arrays, perhaps this is cleanest:
my_array.flatten.each {|n| puts n.gsub(/\\/,"//")}
What it does is transforms two-dimensional array in one-dimensional.
my_array.flatten.each { |n| f.puts n.tr('\\', '/') }
As others have pointed out, you are calling gsub on an array, not the string within it. You want:
my_array.each {|n| puts n[0].gsub(/\\/,"//")}
I want to display value of collection by passing their respective attribute name.
#mandates is the result of an active-record query.
#tabattributes contains array of attribute names previously selected by users.
The code below show field attributes but I want the value of these field instead.
I've tried several syntaxes but errors occurs each time.
How can I modify my code to do that?
#mandates.map do |f|
#tabattributes.each { |att| " #{att} "}
end
If #mandates is a result set that contains models with attributes a, b, and c and #tabattributes is the array %w{a b} (i.e. you want to extract a and b from each element of #mandates) then:
a = #mandates.map { |m| m.attributes.slice(*#tabattributes) }
will give you an array of hashes with keys 'a' and 'b'. For example:
#tabattributes = %w{id created_at}
slices = #mandates.map { |m| m.attributes.slice(*#tabattributes) }
# slices is now like [ { 'id' => ..., 'created_at' => ... }, ... ]
If you only want the values and don't care about the keys then perhaps this will work for you:
#mandates.map { |m| m.attributes.slice(*#tabattributes).values }
That would give you an array-of-arrays. The first array-of-hashes would probably be easier to work with though.
If you can get at #mandates before accessing the database then you could slice out just the columns you're interested inside the database with something like this:
#mandates = Mandate.select(#tabattributes)
slices = #mandates.map(&:attributes)
If I understand you right, you have an array of elements, and you want to have an array containing the name of each element, is that it ? If yes, then array.map {|elem| elem.name} should do it. There is a shorter form (array.map(&:name)) which does the same, if you're interested in how this is working, I can detail.
I am new to Ruby, and I am having some problems with hashes.
I have XML returned from the YouTube API that I converted into a hash. Here is the hash returned by Hash.from_xml(): http://pastebin.com/9xxE6iXU
I am trying to grab specific elements from the hash for each result, such as the title, link, author, etc. Whenever I try to loop through the hash or grab a specific element, I receive a "can't convert String into Integer" error.
Here is the code I am using for the loop:
#data["feed"]["entry"]["title"].each do |key, value|
"<p>"+key+" "+value+"</p>"
end
I have also tried grabbing specific elements, such as #data["feed"]["entry"]["title"][0].
How do I loop through the hash and grab specific elements out?
That's happening because #data["feed"]["entry"] is array of hashes:
puts #data["feed"]["entry"].class # => Array
Each element-hash inside this array has "id", "category", "title" etc. values.
For grabbing each title try to use following snippet:
#data["feed"]["entry"].each do |entry|
puts entry["title"]
end
# => "TABE test adult basic education"
"WhatCollegesHopeYouWon'tFindOutAboutACTSATTestPrep..."
....