ruby.split(/\n/) separate into multiple array - ruby-on-rails

I need to Separate multiple Array entries with a newline.
the names in the aray value. Again I want to split the array like seperate names.
Eg. names="alice\nbob"
and I want names=alice&names=bob. How can I get that??

Try this:
names="alice\nbob"
names = names.split("\n").map{|item| "names=#{item}"}.join("&")
#=> "names=alice&names=bob"

If intention is to have it in form of query parameters, I will suggest using Addressable::URI:
require "addressable/uri"
def return_query(str)
uri = Addressable::URI.new
uri.query_values = {:names => str.split("\n") }
uri.query
end
return_query("alice\nbob") #=> "names=alice&names=bob"
return_query("alice in wonderland\nbob") #=> "names=alice%20in%20wonderland&names=bob"
return_query("alice&wonderland\nbob") #=> "names=alice%26wonderland&names=bob"

Related

Writing custom method for a hash on Ruby? on rails

i'm trying (and actually succeded, but i don't understand how it works) to write a custom method for a hash in my model (I'm working on Ruby on Rails 6).
My hash looks like this
my_hash = {
[['name_1', 'slug_1']=>value_1],
[['name_2', 'slug_2']=>value_2],
[['name_1', 'slug_1']=>value_3],
[['name_2', 'slug_2']=>value_4]
}
So basically a hash of arrays. You notice that the 'keys' are arrays that repeat themselves many times, but with different values. What i want to achieve is to write a custom method that "joins" all the keys in only one key, which will have an array of values assigned, so basically i should be able to get:
my_hash = {
['name_1', 'slug_1']=>"values": [value_1, value_3],
['name_2', 'slug_2']=>"values": [value_2, value_4]
}
For that, I have this piece of code, which i use many times:
my_hash.inject({}) do |hash, record|
# each record has the following format => [["unit_name", "axis.slug"]=>average_value(float)]
keys, value = record
# now keys has ["unit_name", "axis.slug"] and values equals average_value
hash[keys.first] ||= {}
hash[keys.first][keys.last] = value.to_f
hash
end
Since I use this many times, i wanted to write a custom method, so i did:
def format_hash_data my_hash
my_hash.inject({}) do |hash, record|
# each record has the following format => [["unit_name", "axis.slug"]=>average_value(float)]
keys, value = record
# now keys has ["unit_name", "axis.slug"] and values equals average_value
hash[keys.first] ||= {}
hash[keys.first][keys.last] = value.to_f
hash
end
end
And used it like: my_hash = format_hash_data(my_hash) with no success(it threw an error saying that 'format_hash_data' was not a valid method for the class).
So I fiddled around and added 'self' to the name of the method, leaving:
def self.format_hash_data my_hash
my_hash.inject({}) do |hash, record|
# each record has the following format => [["unit_name", "axis.slug"]=>average_value(float)]
keys, value = record
# now keys has ["unit_name", "axis.slug"] and values equals average_value
hash[keys.first] ||= {}
hash[keys.first][keys.last] = value.to_f
hash
end
end
Which, to my surprise, worked flawlessly when using my_hash = format_hash_data(my_hash)
I don't really understand why adding 'self' makes my code works, maybe anyone can shed some light? I tried using things like send() or instance_eval first, to just send the piece of code to the actual hash as a method (something like my_hash.instance_eval(my_method)) but I couldn't get it working.
I'm sorry about the long explanation, I hope i was clear enough so any of you who had this same dilemma can understand. Thanks in advance.
Prepending self. to the method name makes it a class method instead of an instance method. If you are not sure of the difference, you should look it up as it is fundamental to properly defining and using classes and methods.
As a class method, you would use it as:
my_hash = MyHash.format_hash_data(my_hash)
Or if you're in scope of the class, simply my_hash = format_hash_data(my_hash), which is why it worked in your case with the self. prepended (class method definition).
If you want to define it as an instance method (a method that is defined for the instance), you would use it like so:
my_hash = my_hash.format_hash_data
And the definition would use the implicit self of the instance:
def format_hash_data
self.inject({}) do |hash, record|
# each record has the following format => [["unit_name", "axis.slug"]=>average_value(float)]
keys, value = record
# now keys has ["unit_name", "axis.slug"] and values equals average_value
hash[keys.first] ||= {}
hash[keys.first][keys.last] = value.to_f
hash
end
end

Nice array from pluck

I have a model and I love the pluck method I can use. If I do this:
#x = AwesomeModel.all.pluck(:column_one, :column_two)
then I get a multidimensional array: #x[][]. With my sad skills, I work with them using the numbers:
#x[0][1]
how can I can use pluck or a similar method to access the array something like this:
#x[0][:column_two]
If you are concerned about the structure of what you get back from the db, you should simply do:
#x = AwesomeModel.all.select(:column_one, :column_two)
Then you'd keep the fast db query advantage + have AwesomeModel instances, but with only column_one and column_two filled
Or if you desire to do it manually:
#x = AwesomeModel.all.pluck(:column_one, :column_two).map do |array|
OpenStruct.new({column_one: array[0], column_two: array[1] }) }
end
Then you can use it like a regular model:
#x[0].column_one
# or even
#x[0][:column_two]
You could do
class ActiveRecord::Base
def self.pluck_hash(*args)
plucked = pluck(*args)
plucked.map {|ary| Hash[args.zip ary]}
end
end
AwesomeModel.all.pluck_hash(:column_one, :column_two)
#=> [{:column_one => 'value', :column_two => 'value}, {...}, ... ]
First of all, don't use .all.pluck, because it returns an array of values, and that makes you loose all the advantages of ActiveRecord::Relation.
Instead use AwsomeModel.method directly, it would create the query but not run it until you need it, AwsomeModel.select(:column_1, :column_2) would create a
select (awesome_models.column_1, awsome_models.column_2)
query, and the result would be an array of ActiveRecord::Relation objects, which are still chainable, and values are still under keys of the column name eg:
AwsomeModel.select(:column_1, :column_2).first.column_1
Instead of
AwesomeModel.all.pluck(:column_1, :column_2).first[0] # or .first.first

Strong parameters permit Array of Arrays

I have data I am trying to POST that looks like { foo: [[:bar, 1], [:baz, 0]] }.
How do I permit that using strong parameters? The closest I can get is
params.permit(foo: [[]]) which returns {"foo"=>[]}
Maletor,
it seems to me that the strong parameters can't handle array of array.
I did read the code of it in github and it deals with Symbol, String and Hash.
For this case you'll have to handle with your own code.
Basically:
def permitted_params
result = params.require(:model).permit(:attributes).to_h # No array of arrays or hashes
result[:model][:array_of_arrays] = params[:model][:array_of_arrays]
result
end
One step further, say you have a Model#json and you want to store model.json[:array_of_arrays] = [[]]:
def permitted_params
result = params.require(:model).permit(:attributes).to_h # No array of arrays or hashes
result[:json] ||= {}
result[:json].merge!(array_of_arrays: params[:model][:json][:array_of_arrays])
result
end
Make sure you have permitted all your un-trusted params before you call to_h, and be careful what you merge in afterwards.

how to work with array of hashes

[[{"Postponed"=>10}], [{"Low"=>3}], [{"Medium"=>4}], [{"High"=>5}]]
is the array
how can I get the value corresponding to particular value.
say High returns 5 in this.
or how to convert this array of hashes to an array so that searching becomes easy.
I tried:
find_all { |v| v['name'] == "Low" }
but it says:
cant convert String to Integer
please provide some guidance
How about making a single hash out of it for efficient querying?
arr.flatten.reduce(:merge)
#=> {"Postponed"=>10, "Low"=>3, "Medium"=>4, "High"=>5}
If you have some code like:
array = [[{"Postponed"=>10}], [{"Low"=>3}], [{"Medium"=>4}], [{"High"=>5}]]
Then turn it into an ruby hash:
hash = array.inject({}) {|h, e| h.merge(e.first) }
# => {"Postponed"=>10, "Low"=>3, "Medium"=>4, "High"=>5}
So you can find 'Low' value easily :
hash['Low']
# => 3
EDIT: The answer of Mark Thomas is pretty great, and shorter than the inject since it does the same thing. He wrote it before I answered. Nice ;)
In the general case, the hashes won't be unique, so you need to filter rather than pick one via indexing. For example, let's say you have this:
arr = [[{:apple => 'abc'}], [{:banana => 'def'}], [{:coconut => 'ghi'}]]
# => [[{:apple=>"abc"}], [{:banana=>"def"}], [{:coconut=>"ghi"}]]
Now let's suppose you want to get the value corresponding to any hash with a :coconut key. Then just use:
arr.flatten.map { |h| h[:coconut] }.compact
# => ["ghi"]
That gives you the list of answers. In this case there's only one matching key, so there's only one entry in the array. If there were other hashes that had a :coconut key in there, then you'd have something like:
# => ["ghi", "jkl", "mno"]
On the whole, though, that's a very unusual data structure to have. If you control the structure, then you should consider using objects that can return you sensible answers in the manner that you'd like, not hashes.
You could simply call #flatten on the original array. That would give you an array of hashes. What I think you would really want is just one hash.
1.8.7 :006 > [[{"Postponed"=>10}], [{"Low"=>3}], [{"Medium"=>4}], [{"High"=>5}]].flatten
=> [{"Postponed"=>10}, {"Low"=>3}, {"Medium"=>4}, {"High"=>5}]
I would ask, what are you doing to get that original structure? Can that be changed?
How about this?
arr = [
[{"Postponed"=>10}],
[{"Low"=>3}],
[{"Medium"=>4}],
[{"High"=>5}]
]
arr1 = []
arr.each{|a|
arr1.push(a[0])
}
Although I wonder if you really just want to get one hash, which you'd do like so:
myHash = {}
arr.each{|a|
a[0].each{|b, c|
myHash[b] = c
}
}
You would then access it like myHash["Postponed"]

Rails / Strings: How to output a different parts of a string?

I am trying to split a string, and output the different parts, whats the best practice for rails 3 ?
String: "book_page_title"
Seperator: "_"
I want to have book, page and title as seperate variables, so that
I can perform actions on them..
Any help is appreciated.
Also, I am having trouble finding good reference sites, with examples like PHP have, and suggestions ?
To split:
book,page,title = string.split('_')
And to recombine:
string = [book,page,title].join('_')
use
split('_')
method it gives array.
Try ruby+string+doc in google, you will get http://ruby-doc.org/core/classes/String.html as the first result, and you can see a number of string functions in this link. You can see split there.
splitted_array = "book_page_title".split("_")
=> ["book", "page", "title"]
splitted_array.each do |string|
#..do manipulations here
end
"book_page_title".split("_") will return you array of strings. So you can access every element via [].
splitted = "book_page_title".split("_") # ["book", "page", "title"]
puts splitted[0] # gives "book"
puts splitted[1] # gives "page"
puts splitted[2] # gives "title"
a = "book_page_title".split("_")
a.each do |i|
instance_variable_set("##{i}", "value")
end
#book #=> *value*
#page #=> *value*
#title #=> *value*

Resources