Overriding Id in JSON object from a mongodb - ruby-on-rails

I am struggling to override the attribute name in one of my models.
I would like to return an object to the front end (via JSON) with a field called id.
Now the problem comes that there is a field called _id (generated by mongo), that I cannot seem to get rid of.
I can override the id fine but is still returned as _id.
[Object]
0: Object
$$hashKey: "007"
_id: 123
I would like it to be
[Object]
0: Object
$$hashKey: "007"
id: 123
I have tried many hash manipulations, reject, except, and looping over and constructing, but cannot simply rename the field, or remove it for that matter.
Thanks

The "_id" field is mandatory in MongoDB documents. The manual says:
If the document does not specify an _id field, then MongoDB will add
the _id field and assign a unique ObjectId for the document before
inserting. Most drivers create an ObjectId and insert the _id field,
but the mongod will create and populate the _id if the driver or
application does not.
So you won't be able to work your way around this one.

Easiest way was to override the as_json method and remove the hash there.
def as_json(*args)
super.tap { |hash| hash["id"] = hash.delete "_id" }
end

Related

Rails merge temporary attributes to model object

I have a Rails model object that has attributes maps to columns in a DB. I compute couple of temporary fields name and age which are not in the DB columns. Is there a way to merge them into the object temporarily without making changes to the model object?
class MyModel < ApplicationRecord
end
I tried using attributes.merge. and tried :
my_obj = my_obj.attributes.merge({ age: compute_age })
my_obj = my_obj.attributes.merge({ name: compute_name })
The second merge however fails with NoMethodError: undefined method `attributes' for #Hash:0x0000000120060010.
Looks like the moment I merge first one it makes the object a Hash. So I need to do
my_obj = my_obj.attributes.merge({ age: compute_age })
my_obj[:name]=compute_name
All the other properties also are accessed as a hash.
However this feels inconsistent and weird to me!
Is there a better option to this than using attributes.merge i.e preserve the object?
I guess it maybe cleaner to add the attr to the model object but those attributes are temporary and should not be accessed outside.
As soon as you call .attributes you turn the MyModel instance into a hash.
To turn it back into a model you can just pass that hash to the MyModel constructor (assuming you have an attr_accessor for the virtual attribute):
my_obj = MyModel.new(my_obj.attributes.merge(age: compute_age))
my_obj = MyModel.new(my_obj.attributes.merge(name: compute_name))
You can also see here for some other options: Rails update_attributes without save?
edit
to clarify a little more. You can turn a model instance into a hash via .attributes. You can turn it back into a model using Model.new(attributes_hash). While it's a hash, you can set whatever key-vals you want - it's just a hash. But in order to convert it back to a model instance, you need to make sure that all the hash keys correspond to actual attributes on the model (be they persisted attributes defined by the schema, or virtual attributes defined by attr_accessor).
If you just want to turn it into a hash and add multiple arbitrary keyvals there, you can do it with a single merge:
attrs = my_obj.attributes.merge({ age: compute_age, name: compute_name })

Group all records by custom method in Rails

I'd like to retrieve all records for a particular model and "index" each one by their name attribute. The end result should be a Hash, where the keys are the name of the record, and the value is the record. I can do this easy enough with a method like
def self.all_by_name
hash = {}
all.each { |model| hash[model.name] = model }
hash
end
Is there a way to do this with an active record query?
all.group(:name) is what you need!
Some documentation: http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-group
No, active record will either return an array or an active record relation. You would have to massage it after into the data type of your choice. ActiveRecor dcan return anything that SQL can normally return. However, you could do use the group method which is essentially the group by in SQL.
I'm not sure in your case what your method should do because it seems like you are going to overwrite the value of your key if there are 2 objects with the same class. Perhaps if you better defined what you need in an example I could help you better.

Seed embedded documents to MongoDB using Rails rake db:seed

How should db.seeds be structured in order to provide data for MongoDB, especially when containing embedded documents?
I ran into the following error when trying to seed a supposedly wrongly structured db.seeds file :
Cannot serialize an object of class ClassName into BSON.
Start by creating a 'new' nested object like address, with attribute street and city, and setting it equal to a variable. Then create the parent object, in this case user with an attribute address, and assign the variable you created above to it. Since it is a nested object, you need to wrap your variable in an array []. Doing it this way will make it easy to read especially if you have a lot of nested objects. When referencing the nested object make sure to exclude any spaces after the colon or you will get an error.
a = Address.new(street: 'Any_Street', city: 'Any_City')
User.create(address:[a])
This will seed mongoDB with an address object which is nested in the user object.
Parent.create(title: 'foo', children: [
Child.create(title: 'bar', date: Time.utc(2011,10,13)),
Child.create(...),
Child.create(...)
])

How do you look up various properties of a mongodb record using the objectID in mongoid for rails?

Using MongoID and Rails 3...
If I store the objectID as a reference to an object in my database how do I use it to query the object and return its other properties?
Let's say my object is:
{
"_id" : ObjectId( "4da0f56ad1f4a901ba455340007" ),
"name" : "John",
"age" : "40"
}
If I had the ObjectId stored in by DB - how would I use it to pull the name or age back to my view? If the object is stored in another model (that doesn't belong to the view) is there anything else I need to do?
Look at database references:
http://www.mongodb.org/display/DOCS/Database+References
Otherwise if you have the object id as references stored to another object inside a different collection then your application has to know where the collection is and fetch it from there using another query.

Persisting string array in single column

Our main domain object has multiple string[] properties (various configuration options) and we are thinking of an elegant way to persist the data. GORM creates joined table for the each array so we end up with about dozen joined tables.
I wonder if it would be possible to serialize each array into single column of the main table (someway delimited) and parse it back into array onload?
Do you have suggestions how to do this? I'm thinking either hibernate usertype or grails property editor? I spent some time with usertypes but without luck.
thanks
pk
you could put the parameters into a map / array, then store them in a db field as Json:
def someDomainInstance = new SomeDomain()
def paramMap = [name:'John', age:24]
someDomainInstance.paramJson = paramMap as JSON
someDomainInstance.save()
Then you can easily convert this string back to a map / array when you interrogate the DB:
def paramMapFromDB = JSON.parse(someDomainInstance.paramJson)
assertEquals 24, paramMapFromDB.age
Something like that, I haven't tested the syntax, but that's the general idea.

Resources