Rails translate enum in an array - ruby-on-rails

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}

Related

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.

Ruby on Rails: Check whether a word is matched to any attributes in database

I am doing my Ruby on Rails project now. PostgreSQL is used as database.I have a table called pets, where stores all pets information(name, gender, age, etc.), which are shown as follows.
{Pet id: 1, name: "Jean", gender: "Female", pet_type: "Cat", age: "0", body_weight: 1, breed: "Abyssinian", created_at: "2015-04-26 23:50:01", updated_at: "2015-04-26 23:50:01"}
{Pet id: 2, ...}
...
{Pet id: 10, ...}
Now I am going to check whether there is a Abyssinian breed cat in table pets. If there is, return the Pet id, otherwise return "no such cat found".
Is there anyone know how to do this? Thanks in advance.
To find the first pet where breed == "Abyssinian":
pet = Pet.find_by(breed: "Abyssinian", pet_type: "Cat")
So, to combine that with your required logic:
pet = Pet.find_by(breed: "Abyssinian", pet_type: "Cat")
output = pet ? pet : "no such cat found"
You could simply this even further to:
output = Pet.find_by(breed: "Abyssinian", pet_type: "Cat") || "no such cat found"
Is "breed" a field in the pets table? If so, you could do something like:
if Pet.exists?( breed: "Abyssinian" )
x = Pet.where( breed: "Abyssinian" )
else
x = "No such cat found"
end
The danger in this is that there could be multiple Pets returned. If you want to find one and only one, you could do
if Pet.where( breed: "Abyssinian" ).count == 1
instead.
REVISION
#infused's answer is more succinct, I would encourage an implementation similar to his, assuming a breed column exists.

Rails format object in helper

When I run a simple query of Item.where(:id => id) in my ItemHelper class and it returns
[
{
JDPA: null,
_id: "530e45f43f72fb3dee000001",
category: null,
created_at: "2014-02-26T19:52:20Z",
creator: "5170547c791e4b1a16000001",
detail: "Detail",
event_id: "52d958e73f72fb1e1f000001",
image_content_type: null,
image_file_name: null,
image_file_size: null,
image_updated_at: null,
question: null,
section: null,
title: "Title",
updated_at: "2014-02-26T19:52:21Z",
veh1: 5,
veh10: null,
veh2: 5,
veh3: 6,
veh4: null,
veh5: null,
veh6: null,
veh7: null,
veh8: null,
veh9: null,
version: null
}
]
I want to get an array of :veh1..:veh10 as [5, 5, 6, null, ...]. Having a lot of trouble doing this...
I thought of using JBuilder in my helper, but now I've blown things up...
How can I do something as simple as using .only(:veh1..:veh10 and remove the nulls...then I could probably make an array.
Thoughts, comments, am I being dumb?? Should this be easy? I'm a beginner here. :)
My Answer
This feels really sloppy. Is there a better way to do this?? More elegant??
def item_ppu(id)
item = Item.where(:_id => id)
newitem = item.map{|i| [i.veh1, i.veh2, i.veh3, i.veh4, i.veh5, i.veh6, i.veh7, i.veh8, i.veh9, i.veh10]}
h = Hash.new(0)
newitem[0].each { | v | h.store(v, h[v]+1) }
f = 2*h[2]#lots more math
return f
end
If this is a Mongoid model, and you're only looking for a single object, you can just use find and then map to the attributes you need:
object = Item.find(id)
You can use values_at to retrieve specific values from the object's attributes hash (in Mongoid, the hash's keys are strings):
keys = (1..10).map {|n| "veh#{n}" } #=> ["veh1", "veh2" ...
values = object.attributes.values_at(*keys)
values.compact # removes the nil values from the array
Taken all together:
object.attributes.values_at(*(1..10).map {|n| "veh#{n}" }).compact
EDIT
In the interest of writing clean, understandable code, here's how I would actually write this in a production app:
class Item
# whatever goes here
def ppu
veh_values.inject {|result, value| # ... some calculation }
end
private
def veh_values
attributes.values_at(*veh_keys).compact
end
def veh_keys
(1..10).map {|n| "veh#{n}" }
end
end
This is now an instance method on the Item class, so to call it, your syntax would be:
item.ppu

how to delete an object's attribute from ruby array

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)

Ruby on Rails: Updating data problems

Okay so I'm just trying to write some simple code that updates a record given an ID. This is what it looks like.
def updaterecord
bathroom = Bathroom.find(params[:key])
bathroom.name= params[:name],
#bathroom.bathroomtype = params[:bathroomtype],
bathroom.street = params[:street]
#bathroom.city = params[:city],
#bathroom.state = params[:state],
#bathroom.country = params[:country],
#bathroom.postal = params[:postal],
#bathroom.access = params[:access],
#bathroom.directions = params[:directions],
#bathroom.comment = params[:commment],
#bathroom.avail = params[:avail]
bathroom.save
end
The problem is that although I am trying to update each individual attribute they are all getting concatenated to the name field. For example, this code above sets the name field to the name plus the address. I don't know why?
This is what the console looks like if I try to query after doing the update.
Bathroom Load (0.2ms) SELECT "bathrooms".* FROM "bathrooms" WHERE "bathrooms"."ID" = ? LIMIT 1 [["ID", 4017]]
=> #<Bathroom ID: 4017, name: "--- \n- ttyt\n- 113 some\n", bathroomtype: "0", street: "113 some", city: "Portland", state: "OR", country: "United States", postal: "97217", lat: #<BigDecimal:1109f2890,'0.4558056E2',12(12)>, lon: #<BigDecimal:1109f27c8,'-0.122677857E3',12(16)>, access: "0", directions: "", comment: nil, created: "2012-06-08 17:19:03.420329", modifed: "", avail: "1", slug: "", source: "Squat">
And this is what the post values look like:
post values = key=4017&name=www&bathroomtype=0&street=7540 N Interstate Ave&city=Portland&state=OR&country=United States&postal=97217&access=0&directions=&comment=<null>&avail=1
Why can't I get each field to update individually? Sorry I'm confused as to what is going on?
I think you might an unnecessary comma there at the end of the line.
It should just read:
def updaterecord
bathroom = Bathroom.find(params[:key])
bathroom.name= params[:name]
bathroom.street = params[:street]
bathroom.save
end
it doesn't look like you have correctly urlencoded your post values
a simple
puts params.inspect
or
pp params
should log out the params object. You can also use
render :text => params.inspect
to print it out to your result html

Resources