Access form_tag submitted params - ruby-on-rails

I've got around 15 parameters being submitted (using tag helpers as no data related to a model). Is there a more efficient way of accessing and maybe storing the params into a hash/array as apposed to having to push all the params into a new array using something like the below:
array = []
array << param["a"]
array << param["b"]
array << param["c"]
array << param["d"]
etc..

If all you want are the values then you can do:
array = hash.values
or more specifically to your question:
param_array = param.values
values returns an array of all the values in the hash.

Related

How to pass an array of arrays in GET API in Ruby on Rails

I am using a GET API, currently passing an array as a string:
def fetch_details ids
url = "#{url}/api/v1/get-info?ids=#{ids.join(',')}"
response = Net::HTTP.get_response(URI.parse(URI.encode(url)))
if response.code.to_i == 200
return Oj.load(response.body)
else
return {}
end
end
On the server-side I am extracting id from this method:
def self.get_details(ids)
ids = ids.split(",").map {|x| x.gsub( " ", "")}
end
For each id, I want to send an array of UUIDs:
ids = [100,21,301]
uuids= {["abc","bca"],["Xyz"],["pqr","345"]}
Something like this
hash=[
100=>[abc,bca],
21=>[xyz],
301=>[pqr,345]
]
The endpoint uses the id and corresponding UUIDs to join two tables in database query so I should be able to extract the id and corresponding UUID at the end.
How do I pass both these values?
To pass an array in the parameters in Rails/Rack you need to add brackets to the name and repeat the parameter:
/api/v1/get-info?ids[]=1&ids[]=2&ids[]=3
You can use Hash#to_query from ActiveSupport to generate the query string:
irb(main):001:0> { ids: [1,2,3] }.to_query
=> "ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=3"
As pointed out by #3limin4t0r you should only use this for one-dimensional arrays of simple values like strings and numbers.
To pass a hash you use brackets but with keys in the brackets:
/api/v1/get-info?foo[bar]=1&foo[baz]=2
Again you can generate the query string with #to_query:
irb(main):002:0> { foo: { bar: 1, baz: 2 } }.to_query
=> "foo%5Bbar%5D=1&foo%5Bbaz%5D=2"
The keys can actually be numbers as well and that should be used to pass complex structures like multidimensional arrays or an array of hashes.

How to iterate through array of strings from database Ruby on Rails

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.

Ruby: How to access object created by send without name? [duplicate]

This question already has answers here:
How to dynamically create a local variable?
(4 answers)
Closed 6 years ago.
What I'm trying to do in Ruby is to create an object with a name that comes from a string (in an array for instance). Then I want to use that object in further code.
So, for example:
array = ["a", "b", "c"]
array.each do |x|
send x + '_data'
x + '_data' = []
x + '_data' << "foo"
end
The above, of course, does not work.
I've racked my brain, the docs, and SO all morning on this. Your help is appreciated!
Any ideas?
Thanks!
Cheers,
Kyle
EDIT for clarity:
Ok, my understanding of send was incorrect.
For each string in the array, I want to create an array.
So the loop above would create three arrays: a_data,b_data,c_data
Then, I want to populate each array with "foo".
So a_data[0] => "foo"
Thanks!
Double edit:
Here's my slightly altered actual code with fuller explanation of what I'm doing:
I have a big json file of thousands of tweets (not just the text, but the full json from twitter api).
I then have an array of hashes based with topics and associated keywords -- e.g. "cooking" -> "utensils", "oven", "microwave".
I want to loop through the array of topic hashes and see if any of the topic keywords match words in the tweet text.
If there's a match, I want to add that tweet to a new array.
# topics is an array of hashes. Each hash contains title and list of keywords
topics.each do |topic|
# create an array with the topic's name to store matches
(topic[:title] + '_tweets') = []
topic[:keywords].each do |kw|
# loop through array of hashes (parsed json) to check for keyword matches in strings
tweets.each do |tweet|
text = tweet["text"]
# if string contains keyword, add to the topic's array
if text.include? kw
(topic[:title] + '_tweets') << tweet
end
end
end
Thanks for y'all's help guys!
Why not create a Hash to keep the data you need?
array = ["a", "b", "c"]
data = {}
array.each do |x|
key = x + '_data'
data[key] ||= []
data[key] << "foo"
end
Also, note data[key] ||= [] trick. It means "look into data[key]. If it is nil, initialize it with empty array". It is idiomatic way to initialize something once.
You can declare data as Hash.new([]). Then you won't need data[key] ||= [] at all, because Hash.new([]) will create a hash that returns an empty array if the value associated with the given key has not been set.
This is much more flexible than using variable variables from PHP
But if you REALLY need something like this, you can do the following:
array = ["a", "b", "c"]
array.each do |x|
instance_variable_set '#' + x + '_data', []
instance_variable_get('#' + x + '_data') << "foo"
end
p #a_data # ["foo"]
Here we create an instance variable in the context of current object instance. Its name MUST begin with #.

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 put data from loop into an array

I have this array that looks like this.
#a = ["foo","bar"].join(",")
But i would like to retrieve the "foo" and "bar" through a loop from my database instead of creating them manually and insert them into the array. How would i do that? For instance i have data, in which i want all the usernames to be put in an array and be seperated by the ",". How can i put all usernames into the array?
#data = Data.all
#data.each do |d|
d.username
end
usernames = Data.all.map(&:username)
joined = usernames.join(',')

Resources