how to delete an object's attribute from ruby array - ruby-on-rails

I have a students array like this
[#<Student id: 2, admission_no: "2", gender: "m", blood_group: "A">,#<Student id: 3, admission_no: "3", gender: "m", blood_group: "A">]
I am getting this array via named_scope .... So is there any way to select only required attributes with named scope...
I need to delete admission_no and blood_group from this and return an array only with students id and gender.. How is it possible. Iam using rails2.3

named_scope_result.select('id, gender') will give you your desired result.

You want to have an array of hashes containing only the required fields, starting from your array.
Student.select('id, gender').find(:all)
will do if you want to consider all the Student objects in your database.
Starting from a generic Student array: students, you can achieve what you want by:
result = Array.new
students.each |s| do
data = { "id" => s.id, "gender" => s.gender }
result << data
end

do this
Student.select('id, gender').find(:all)

Related

Method to move arrays into rails ActiveRecord table

Assume a model Fruit with attributes name, price, and weight, and assume three arrays:
name = ["apple", "orange", "pear"]
price = [1.5, 1, 2]
weight = [130, 110, 120]
Is there a method that creates a new record in Rails comprising the i'th element of each array above?
Just out of curiosity:
name.
zip(price, weight).
map(&%i[name price weight].method(:zip)).
map(&:to_h).
map(&Fruit.method(:create))
There is no such a method but you iterate loop to add numbers objects inside Fruit as below,
name.length.times { |i| Fruit.create(name: name[i], price: price[i], weight: weight[i]) }
You can get an array of hashes by:
name.zip(price, weight).map { |a| Hash[[:name, :price, :weight].zip(a)] }
# [{:name=>"apple", :price=>1.5, :weight=>130}, {:name=>"orange", :price=>1, :weight=>110}, {:name=>"pear", :price=>2, :weight=>120}]
.zip merges arrays together. Hash[] is a special constructor method for hashes that takes an array of key/value pair arrays.
To create multiple records at once you can just pass an array of hashes to the create method:
Fruit.create(
name.zip(price, weight).map { |a| Hash[[:name, :price, :weight].zip(a)] }
)

rails array of hashes calculate one column

I have an array and it has many columns and I want to change one value of my one column.
My array is:
[
{
id: 1,
Districts: "Lakhisarai",
Area: 15.87,
Production: 67.77,
Productivity: 4271,
Year: 2015,
Area_Colour: "Red",
Production_Colour: "Orange",
Productivity_Colour: "Dark_Green",
created_at: "2018-07-24T11:24:13.000Z",
updated_at: "2018-07-24T11:24:13.000Z"
},
{
id: 29,
Districts: "Begusarai",
Area: 18.53,
Production: 29.35,
Productivity: 1584,
Year: 2015,
Area_Colour: "Red",
Production_Colour: "Red",
Productivity_Colour: "Orange",
created_at: "2018-07-24T11:24:13.000Z",
updated_at: "2018-07-24T11:24:13.000Z"
},
...
]
This is my sample array and I want my Productivity to be divided by 100 for that I am using one empty array and pushing these hashes to my array like:
j = []
b.map do |k|
if k.Productivity
u = k.Productivity/100
j.push({id: k.id, Productivity: u })
else
j.push({id: k.id, Productivity: k.Productivity })
end
Is there any simple way where I can generate this kind of array and reflect my changes to to one column. Is there any way where I don't need to push name of column one by one in push method.
I want to generate exact same array with one modification in productivity
let's say your array is e, then:
e.each { |item| item[:Productivity] = item[:Productivity]/100}
Example:
e = [{p: 12, d: 13}, {p:14, d:70}]
e.each { |item| item[:p] = item[:p]/10}
output: [{:p=>1, :d=>13}, {:p=>1, :d=>70}]
You could take help of map method here to create a new array from your original array, but with the mentioned changes.
ary.map do |elem|
h = elem.slice(:id)
h[:productivity] = elem[:Productivity] / 100 if elem[:Productivity]
h
end
=> [{:id=>1, :productivity=>42}, {:id=>29, :productivity=>15}]
Note, Hash#slice returns a new hash with only the key-value pairs for the keys passed in argument e.g. here, it returns { id: 1 } for first element.
Also, we are assigning the calculated productivity to the output only when it is set on original hash. Hence, the if condition there.

Rails translate enum in an array

I am currently working on statistics, so I get an array containing all my data. The problem is that this data contains enums and that I would like to translate them without overwriting the rest.
Here is a given example that contains my array (it contains several hundred) :
#<Infosheet id: 90, date: "2018-04-22 00:00:00", number: 7, way: "home", gender: "man", age: "age1", district: "", intercommunal: "", appointment: true, othertype: "", otherorientation: "", user_id: 3, created_at: "2018-04-22 17:51:16", updated_at: "2018-04-22 17:51:16", typerequest_id: 168, orientation_id: 188, info_number: nil, city_id: 105>
I would like to translate the enums of "way" or "gender" or "age", while retaining the rest of the data, because currently, if I make a translation in the console, it crushes everything else.
Do you know how to make that ?
Thanks !
You can just loop over all the enum attributes and get their values. Later you can merge and pass a new hash containing converted values
ENUM_COLUMNS = %i[way gender age] # Equivalent to [:way, :gender, :age]
def convert_enums
overrided_attributes = {}
ENUM_COLUMNS.each { |column| overrided_attributes[column.to_s] = self[column] }
attributes.merge(overrided_attributes)
end
NOTE:
While infosheet.gender returns you male or female
infosheet[:gender] will return you the respective integer value 0 or 1
You can test this if you use translate enum gem :
a = Infosheet.group(:gender).count
{“male”=>30, “female”=>6532}
Create a hash
r = Hash.new
And populate this with :
a.each {|s| puts r[Infosheet.translated_gender(s[0])]=s[1] }
r
result :
{“homme”=>30, “femme”=>6532}

Nested dynamic array rails

I have created an array
steps = [{'title' =>'abc','content' =>'click this', 'target' => 'bca'}]
tours = ['id'=>'tour', 'steps:' => "#{steps}"]
puts tours
Getting following output :
{"id"=>"tour", "steps:"=>"[{\"title\"=>\"abc\", \"content\"=>\"click this\", \"target\"=>\"bca\"}]"}
The structure of the output is right but i don't want these \ in the output.
What should i do to remove these \.
Thanks!
In ruby "#{}" invoke the to_s method on the object. You can check it run the following code: steps.to_s.
Just use:
tours = ['id'=>'tour', 'steps:' => steps]
Because this:
"[{\"title\"=>\"abc\", \"content\"=>\"click this\", \"target\"=>\"bca\"}]"
is a string representation of:
[{'title' =>'abc','content' =>'click this', 'target' => 'bca'}]
Зелёный has the direct answer for you, however, there's a more pressing issue I would point out -- I think you're getting confused between {hashes} and [arrays]
--
An array is a set of unordered data:
array = [3, 4, 5, 6, 0, 5, 3, "cat", "dog"]
Arrays are mainly used for non-sequential collections of data, a good example being product_ids in a shopping cart.
Arrays can only be identified by using the location of the data inside the array:
array[1] # -> 4
array[2] # -> 5
--
A hash is a collection of key:value pairs:
hash = {name: "Greg", type: "cat"}
Hashes are used when you wish to assign multiple values to a single piece of data, and can be called by referencing the "key" of the hash:
hash["name"] #-> Greg
hash["type"] #-> cat
Whilst you can create an array of hashes:
hash_array = [{name: "Greg", type: "cat"}, {name: "Sulla", type: "Dog"}]
... the problem with this is that you cannot call the hashes directly - they have to be through the array:
hash_array["name"] # -> error
hash_array[0]["name"] #-> "Greg"
Thus, I'd use the following in your example:
steps = {'title' =>'abc','content' =>'click this', 'target' => 'bca'}
tours = {id: 'tour', steps: steps}
tours.inspect #-> { id: "tour", steps: { "title" => "abc", "content" => "click this", "target" => "bca" }

match key of hash and then fetch values accordingly in ruby

I have included the given code:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = params[:test] #I get "1,3,7"
I get this, now please guide me how to match keys with #amaze and accordingly fetch its values from #classes i.e USA, France, Delhi.
Since #amaze is just a String, lets first convert it in Array so its easy to enumerate:
#amaze = "1,3,7"
#amaze = #amaze.split(",")
# => ["1", "3", "7"]
Now, since you have all keys extract all values:
#amaze.map { |i| #classes[i.to_i] }
# => ["USA", "France", "Delhi"]
Split #amaze by , and get an array of keys, convert them into Integer, then select only those key/value pairs which key is into this array of keys. Something like this:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = "1,3,7" #I get "1,3,7"
arr = #amaze.split(',').map(&:to_i)
p #classes.select{|el| arr.include? el}
Result:
#> {1=>"USA", 3=>"France", 7=>"Delhi"}
If you want values only use .values:
p #classes.select{|el| arr.include? el}.values
Result:
#> ["USA", "France", "Delhi"]
For what(seemingly) you are asking, the below line will do it:
#amaze.split(",").each { |i| p #classes[i.to_i] }
# If #amaza = "1,3,7", above line will output:
# => "USA"
# "France"
# "UK"
This should work well for you:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = params[:test].split(",").map(&:to_i)
#classes.values_at(*#amaze)
#=> ["USA", "France", "Delhi"]
Hash#values_at accepts an indefinite number of keys and returns their values as an array. The * (splat) operator explodes the array so this call actually becomes #classes.values_at(1,3,7) Docs
Might also want to add a compact to the end in the event a key does not exist. e.g
#amaze = params[:test].split(",").map(&:to_i) # Asssume this returns [1,3,7,9]
#classes.values_at(*#amaze)
#=> ["USA", "France", "Delhi",nil]
#classes.values_at(*#amaze).compact
#=> ["USA", "France", "Delhi"]
I think a clearer understanding of hashes would help you out here.
A Hash is a data structure that is a list of key-value pairs. For example, the following is a Hash object of key-value pairs (your example):
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
If you want to extract a value from #classes, you need to pass the key of the value you want. If we wanted "USA" we would pass the key of 1 to #classes. If we wanted "France", we would pass it the key of 3:
#classes[1] would return "USA" and #classes[3] would return "France".
It's not clear what data structure #amaze is according to your question, but let's say it's the string "1, 3, 7" which we can split to create an array [1, 3, 7].
You could iterate over the array to get each of the values from #classes:
#amaze.split(",").map(&:to_i).each do |key|
puts #classes[key]
end
That would print out each of the corresponding values to keys in #classes.

Resources