SproutCore

SproutCore Guides

These guides are designed to help you write and perfect your code.

Using Fixtures

This guide covers the use of fixtures in your application. By referring to this guide, you will be able to:

  • Understand the purpose of fixtures.
  • Write your own fixtures.
  • Set up relationships within fixtures.
  • Use the fixtures data source.

1 - The Purpose of Fixtures

Fixtures are a quick and easy way to preload your application with sample data without having to write a custom data source. This is especially useful in the early stages of development as it allows you to focus on the general structure without having to be concerned with your application's backend.

1.1 - How Fixtures Work

Fixtures are defined as an array of hashes with each hash containing the attributes and values for each instance you wish to create.

A sample fixture looks something like:

apps/app/fixtures/my_model.js
App.MyModel.FIXTURES = [ { guid: 1, firstName: "Michael", lastName: "Scott" }, { guid: 2, firstName: "Dwight", lastName: "Schrute" } ];

1.2 - Defining Fixtures

SproutCore looks for fixtures assigned specifically to a model (i.e. App.MyModel.FIXTURES on the above example). By convention, fixtures are defined in the app/fixtures folder of your application (i.e. app/fixtures/my_model.js). By default fixtures are not included in production builds.

2 - Writing Your Own Fixtures

Writing fixtures is relatively straightforward. Each item representing a record gets its own hash in the format of propertyName: value. If your model looks like:

apps/app/models/article.js
App.Article = SC.Record.extend({ title: SC.Record.attr(String), body: SC.Record.attr(String) });

Your fixture will look like:

apps/app/fixtures/article.js
App.Article.FIXTURES = [ { guid: 1, title: "Writing a SproutCore app", body: "Writing a SproutCore app is fun and exciting!" }, { guid: 2, title: "Working with Fixtures", body: "Using fixtures can make it easier to get your app started." } ];

It is also possible to specify attributes that are not explicity defined in your model, though explicit declaration is encouraged.

You must specify a value for the primaryKey in your fixtures.

2.1 - Defining Relationships

Since relationships are only specified with the foreign key it is quite easy to set them up in your fixtures. If you have model declaration, like the following, where an employee belongs to a company and a company has many employees:

apps/app/models/employee.js
App.Employee = SC.Record.extend({ firstName: SC.Record.attr(String), lastName: SC.Record.attr(String), company: SC.Record.toOne("App.Company", { inverse: "employees", isMaster: NO }) }); App.Company = SC.Record.extend({ name: SC.Record.attr(String), employees: SC.Record.toMany("App.Employee", { inverse: "company", isMaster: YES }) });

You would set up your fixtures like:

apps/app/fixtures/employee.js
App.Employee.FIXTURES = [ { guid: 1, firstName: "John", lastName: "Smith", company: 1 // SomeCompany, Inc. }, { guid: 2, firstName: "Sally", lastName: "Washington", company: 1 // SomeCompany, Inc. }, { guid: 3, firstName: "Bernard", lastName: "Peterson", company: 2 // AnotherCompany, Inc. } ]; App.Company.FIXTURES = [ { guid: 1, name: "SomeComany, Inc.", employees: [1,2] }, { guid: 2, name: "AnotherCompany, Inc.", employees: [3] } ];

When the fixtures are loaded into your application the relationships automatically take over and point to the appropriate records.

Unlike a traditional relational database it is necessary to specify both sides of the relationship.

When defining the 'many' side of the fixture record, be certain to include the [ ] around a single value because SproutCore is expecting an array of values.

2.2 - Defining Non-String Values

The above examples have referred mostly to string values in the fixture. As most data is either passed into the application via JSON or XML, SC.Record is capable of transforming data from a string into the appropriate object type. See SC.RecordAttribute.registerTransform for more information.

3 - Hooking Up Your Fixtures

SproutCore comes with a built-in data source for your fixtures. To use the fixtures data source you merely need to set the following in your application's core.js.

in apps/app/core.js
App = SC.Application.create({ store: SC.Store.create().from(SC.Record.fixtures) });

You can extend the built-in fixture data source to simulate real world performance (important in managing user expectations).

$ sc-gen data-source App.AppsFixturesDataSource SC.FixturesDataSource

Delete the boilerplate code in the fixture data source so your code looks like:

apps/app/data_sources/apps_fixtures.js
App.AppsFixturesDataSource = SC.FixturesDataSource.extend({ simulateRemoteResponse: YES, latency: 500 // 500 ms latency });

This simulates a remote response with 500 milliseconds round trip latency. Tweak the value to match the performance of your network and servers.

Next, point your store to the new fixtures data source.

in apps/app/core.js
App = SC.Application.create({ store: SC.Store.create().from('App.AppsFixturesDataSource') });

Notice the quotes around the data source name? App.AppsFixturesDataSource doesn't exist until its instantiated during the loading process.

And that's it! Your fixtures should now be available to your data store!

4 - Changelog