mgan59 / mongoose-fixture

A bootstrap library to import javascript objects into mongodb using a series of raw json files
25 stars 3 forks source link

Implment simpler interface for collections and references #9

Open hal-gh opened 10 years ago

hal-gh commented 10 years ago

The approach shown in https://github.com/mgan59/mongoose-fixture/issues/5#issuecomment-25921163 is no doubt very versatile, but it seems to rely on data that already exists in the database and requires some existing knowledge of how the library works in order to use it.

The option to use an interface that supports the following construct that would make the learning curve very shallow and, consequently, allow far greater adoption.

// fixture object - single letter for brevity
var o = {};

// collections
o.families = {};
o.people = {};

// documents
o.families.smith   = { name: "Smith" };
o.families.jones   = { name: "Jones" };
o.families.connors = { name: "Connors" };
o.people.peter     = { name: "Peter", family: o.families.smith };
o.people.catherine = { name: "Catherine", family: o.families.connors, parents: [ { name: o.people.peter.name } ] };

console.log("Peter's family: " + o.people.peter.family.name);
console.log("Catherine's family: " + o.people.catherine.family.name);
console.log("Catherine's parent(s): " + o.people.catherine.parents[0].name);

Note how the collections are declared, which could be determined using lodash's _.keys(object) method).

Obviously, a full example showing self-references and references between collections where the data is purely described in text files or scripts would also be helpful after the implementation.

There maybe some benefit to separating the logic code and fixture data objects into separate files, to make it simpler to understand, possibly with them being loaded using async.series (already provided in a boilerplate).

This interface may well be quite difficult to implement or there may be some reasons you can think of why it wouldn't be practical or versatile which outweigh it's ease of use. If so, and if you do not object, I think it's worth discussing.

mgan59 commented 10 years ago

So I understand the result.

The expectation would be the o would get sent to the fixture-loader and all the o.families would need to be inserted into mongo and their _ids returned and embedded into the references defined within the o.people. So essentially clients are defining these tree structures in a data-fixture file and mongoose-fixture is then deciphering the collections and handling all the embedded documents in a more literate form?

hal-gh commented 10 years ago

I am not sure that mongo would need to be touched while the o object is being created. Surely references are simply two properties that have the same value, regardless of whether they are in the same or different collections? The _id properties' ObjectId values can be created before o is processed by mongoose-fixtures.

The snippet above is a working example of what would be passed to mongoose-fixture. The only difficulty would be how the section of BaseFixtureLoader.js that I patched the other day would differentiate between an object of documents and an object of collections.

A possible solution could be to check the existence of a specific property, as follows.

        if(_.isPlainObject(globalFixtureData)){
            if(globalFixtureData.fixtureCollection){
                // handle each property as a collection whose properties contain documents
            }
            if(globalFixtureData.dataFixtures){
                fixtureSet = globalFixtureData.dataFixtures;
            } else {
                globalFixtureData = _.values(globalFixtureData);
            }
         }
         if(_.isArray(globalFixtureData)){
             fixtureSet = globalFixtureData;
         }

However, there may be a much more elegant way of doing it.

mgan59 commented 10 years ago

your right wouldn't need to touch mongo. just thinking of a case where you generate these _ids and then during the insertion phase something goes wrong and then you have these _ids with no match. Where inserting into mongo would give you some assurance that the fk-doc-ids exist. Maybe that isn't a concern and ideally that shouldn't/wouldn't happen. so yeah the implementation provided looks easy enough.

how would the --reset or --remove methods work? edit the way the mongoose-config works to accept multiple collections names to drop from?

hal-gh commented 10 years ago

This scenario isn't really intended for fixtures that reference data that already exists in the db. For that, I think your approach (that I linked to above) would be better.

Here, any references must exist in the object. If they don't, javascript will inherently throw an error. I don't think there needs to be any special logic or error checking to handle this.

hal-gh commented 10 years ago

Devising a way to integrate this into the fixtures user interface may be trickier. Could you just build the whole o object and then only process the collections specified by the `fixtureConfig.fixtureListings config?

mgan59 commented 10 years ago

Think that would be the tricky part.

I'm not opposed to supporting this interface, I could see it being useful for some to simplify their fixtures. I of course have my own use cases at the moment and need to get some changes for schema/model loading for a 0.3.0 release which will break apis for people. Why I'm incrementing off the 0.2.x line.

Anyways, if you want to put in the effort to implement this interface and write the test then I'm willing to merge it. If you build it from the 0.2.3 tag I'll help port it to the 0.3.0 version. I hope to have 0.3.0 out in the next day or so.

hal-gh commented 10 years ago

When I said "trickier", I just meant, to make the decision. As long as the behaviour is documented, I don't think it would cause a problem.

I've realised that other projects use a similar type of interface https://github.com/tdegrunt/mongodb-fixtures/blob/master/fixtures/wines.json

Pow fixtures also uses something similar but, when I tried it, it didn't work as documented.