===== Populate/Refres a site's demo data (In progress) =====
===== Requirement =====
1. We should be able to setup some sample users, content, courses on a fresh demo site.
2. After the site being used some time by users all the data of the site should be rolled back to default demo data created by (1).
===== Approach =====
=== 1. Population of data - ===
The following items will be created when a task to populate data is run.
Users - create 3 users (Admin, Instructor, Learener)
Group - A single group with all the 3 default users.
Content - sample doc (.doc, .ppt, .pdf, .mov, webtext, webcontent, Quiz)
Courses - A sample course with all the possible contents
Certification - A sample certification with
Looked at gems like faker, populate and forgery but they do not suit of our purpose as we do not generate random data.
Even factory girl is not a good option as we know the exact data we want to create.
== Fixtures ==
In the case of tests factory girl is a better option but for our case using fixtures is better.
The sample data is added in the yml files and each and every model is populated with it. We use
http://stackoverflow.com/questions/761123/what-is-the-best-way-to-seed-a-database-in-rails for this task as the active record callbacks are needed to be called in.
== Sample code ==
To create users -
Please place the user information in a fixture file (ex - in "#{RAILS_ROOT}/db/demo_data/fixtures/users.yml").
Then just load it -
User.load_from_file("#{RAILS_ROOT}/db/demo_data/fixtures/users.yml") #creates users in the company
=== 2. Reset site data ===
The resetting of the data should clear all the data except the default users , documents etc. In addition to these, the site owner's information should be preserved. The site owner's information would be in a state when he has created the site. This is because the owner might have enrolled to some courses and made progress or commented on other users. All this information would be reset.
All the records are deleted physically form the tables and the documents are removed from the disk.
== Implementation Problem ===
We do not delete all the records from the database at the moment. We use acts_as_paranoid plugin to soft delete some items. As we need to hard delete all the items in the tables for this task, we need to figure out how this can be done.
a) acts_as_paranoid overwrites the sql queries constructed by active record and updates deleted_at column instead deleting the records. There are two issues with this.
1. It does not allow us to hard delete records. We can call "destroy!" method on the model object but it does not call "destroy!" on the callbacks. So, say if we have :dependent => :destroy for a model's association and the associated model also uses acts_as_paranoid it is always soft deleted.
It is not advisable to hack this as that might create problems with queries.
As an alternative looked at some other gems/plugins like https://github.com/expectedbehavior/acts_as_archival , https://github.com/ajh/acts_as_soft_deletable and etc. but they are not good options in our case as we need data to be in the same table for reporting purposes and query simplification.
== Fix ==
So, the best thing is to use write our own plugin which also deletes the associations from the database tables. https://github.com/JackDanger/permanent_records seems to be a good inspiration and we can try to build on top of this.
== Code Change required ==
We need to make sure that all the associations have proper dependency setup. If an entity cannot exists without user it should have ":dependent" option set to either ":destroy" or ":delete_all" or "nullify" based on the code context. This way we make sure that no erroneous or invalid tuples remain the database tables.
== Implementation Algorithm ==
We can follow these steps to reset the data.
1. Check if this is ran on the super site. If yes exit by throwing a warning that it should not be run on the super site.
2. Clone company and site owner objects (say company and site_owner).
3. Get all the photo and asset ids of the company.
photo_ids = company.photos.map(&:id)
asset_ids = company.assets.map(&:id)
4. Destroy all company users (including site admin. We will recreate it from the step 1's clone). This also deletes all the associations which are dependent on users. company.users.each { |user| user.destroy }
5. Now call destroy on each and every association of the company, which are not 'through' the users. company.translationseach {|tr| tr.destroy} ........
6. Delete the photos and assets from the file system. We can use the ids we have backed up in the step (2) to construct the document urls.
photo location = "#{RAILS_ROOT}/public/system/images/#{id}"
asset location = "#{RAILS_ROOT}/public/system/uploaded_data/#{id}"
7. Now, all the company information is cleaned up. Recreate site admin from the object clone in step (1). Create demo information on the site by running the demo data creation task mentioned above in the page.
===== Open Questions =====
1. Should the script to populate demo data also create the subsite ?
or
This is run to populate data on an already created subsite ? (The document is written assuming this case.)
2. Do we need the population and reset of the data to be done from the UI or a rake task is good enough ?
(Super site admin can populate/reset a subsite's data ? or some one can run this as a rake task on production)