Mongoid migrate BigDecimal to Rails-Money - ruby-on-rails

I'm currently using BigDecimal type in a Mongoid 3 app. There are multiple Documents and each has multiple BigDecimal fields. I'd like to migrate all the production data to type Money but keep the document field names the same. How should I do so without significant downtime?
One idea:
Create temporary fields in each Document with type Money
Convert data in existing fields into temporary field
Change original field type to Money
Copy data in temporary field to original field
Remove temporary field
Is there a better way?

Related

Loop over all model fields in Rails/MongoDB

I am using mongoid/Rails for my application server. I defined my own field typ 'formula'. This is a field I don't want to have persistent in the database since this is not a data field but a formula which is consistent across all records of a model. So I stored this formula in my metadata and whenever I create dynamically a model where I need this formula I create a field with my custom type 'formula' where the formula is the default value. This works so far - but as soon as I save a record which includes my formula field it doesn't.
So before I create or update any records I want to loop over all fields of my model and depending on the type the field I allow it to be updated - or not ( so for every formla field I don't allow updates)
I can loop over all field names (model.fields.keys.each) and check the name of the field - But I haven't found a method to loop over all fields and access the type. Any idea?
But perhaps there is another way to avoid my formula field is saved in the database? I create a mongoize (object) method for my new field type 'formula' and this method simply returns nil - but this still writes an empty field to the database.

YapDatabase only uses a single table to store data

I am looking for a key value store database on iOS. It should be based on sqlite, so YapDatabase seems to be a good choice.
But I find YapDatabase only uses a single table, to quote "The main database table is named "database" ": CREATE TABLE "database2" ("rowid" INTEGER PRIMARY KEY, "collection" CHAR NOT NULL, "key" CHAR NOT NULL, "data" BLOB, "metadata" BLOB ). So I am concerned about storing different type objects into the same column.
For example, I plan to use YapDatabase for my chat app, storing each message into |collection|key|object|metadata|. Each message has a unique id, which will be used as the key, message content normally is nstring, which will be used as object, timestamp with some other data is used as metadata. Just like YapDatase author answered here.
Sometimes pictures will be sent. The images are small, normally around couple hundreds of kbs, I don't want to store them as files, I believe storing them as blob is appropriate.
But if I use YapDatabse they are stored in the same table as my normally text messages. Then how can I do some query like, said find all my text messages?
Is my concern valid (storing different type objects into the same column)? Do I need to store them in separated tables? If yes, how? If not, how do I find all my text message easily?
The whole point of a key/value store is that it uses only the keys to identify the values. So if you want to store messages and pictures in the same store, you must ensure that they have different keys.
If you want to store data in separate tables, use a database that actually has tables, like SQLite.

How to migrate from ActiveRecord's Serialize Array to Postgres Array datatype

Rails 4 supports postgres' array data type, and we want to start taking advantage of the array types in postgres , how can I migrate an existing ActiveRecord serialized array field to the new data type?
serialize stores things inside the database as YAML documents in a text column. YAML isn't the easiest format to work with inside a database so the most straightforward approach would be to:
Add an array column to hold the arrays.
Loop through each record in Rails, let ActiveRecord unserialize the YAML, copy the Ruby arrays from the serialize column to the real array column from 1.
Remove the serialize declaration from your model.
Drop the old column that serialize used.
Rename the column from 1.
Set the newly renamed column to NOT NULL if desired.
You could parse the YAML inside the database using regex and string functions but that would depend on what sorts of things you're storing in your YAML.

Issue of using field of type array in rails

There might be a group of records in a table where only two fields vary record by record, and rest fields remains same. This calls for a normalization by splitting by a table through a foreign key association. But, in Ruby-on-Rails, it would mean the creation of a model. So, is it still possible to lessen use of disk space?
May be, it is, because it would be reasonable that storing multiple values of one column in a record would require the column to be an array of any type. But declaring the field to be :array type results in an error. So, is there a way to work around it?
After generating a model, open the model's file. Insert one line for each field.
serialize :field_name
But ensure that the fields for which you are serializing, should be of type
:text
or
:string
If they aren't of such primitive data types, i.e. of another type like
:datetime
then it would return an error.
This step is not complete as a whole. You need to do one complementing step: de-serialize, because in the model-level storage, it is stored as a string starting with "---\n-", which is not suitable for array-type operations.
While reading data from the model, you need to perform the following step:
YAML.load(field_name)
where field_name refers to the field that was serialized.
The above step would return an array, on which you can perform normal array operations.

Rails - EAV model with multiple value types?

I currently have a model Feature that is used by various other models; in this example, it will be used by customer.
To keep things flexible, Feature is used to store things such as First Name, Last Name, Name, Date of Birth, Company Registration Number, etc.
You will have noticed a problem with this - while most of these are strings, features such as Date of Birth would ideally be stored in a column of type Date (and would be a datepicker rather than a text input in the view).
How would this best be handled? At the present time I simply have a string column "value"; I have considered using multiple value columns (e.g. string_value, date_value) but this doesn't seem particularly efficient as there will always be a null column in every record.
Would appreciate any advice on how to handle this - thanks!
There are a couple of ways I could see you going with this, depending on your needs. I'm not completely satisfied with any of these, but perhaps they can point you in the right direction:
Serialize Everything
Rails can store any object as a byte stream, and in Ruby everything is an object. So in theory you could store string representations of any object, including Strings, DateTimes, or even your own models in a database column. The Marshal module handles this for you most of the time, and allows you to write your own serialization methods if your objects have special needs.
Pros: Really store anything in a single database column.
Cons: Ability to work with data in the database is minimal - It's basically impossible to use this column as anything other than storage - you (probably) wouldn't be able to sort or filter your data based on it, since the format won't be anything the database will recognize.
Columns for every datatype
This is basically the solution you suggested in the question - figure out exactly which datatypes you might need to store - you mention strings and datestamps. If there aren't too many of those, it's feasible to simply have a column of each type and only store data in one of them. You can override the attribute accessor functions to use the proper column, and from the outside, Feature will act as though .value is whatever you need it to be.
Pros: Only need one table.
Cons: At least one null value in every record.
Multiple Models/Tables
You could make a model for each of the sorts of Feature you might need - TextFeature, DateFeature, etc. This guide on Multiple Table Inheritance conveys the idea and methodology.
Pros: No null values - every record contains only the columns it needs.
Cons: Complexity. In addition to needing multiple models, you may find yourself doing complex joins and unions if you need to work directly with features of different kinds in the database.

Resources