Seeding Cards
IMPORTANT: always back up any valuable data before running any seed commands.
I just want to seed my deck
If you’re starting from scratch, run decko setup
. This will create the databases
specified in your database.yml, the tables specified in the decko schema, and the
data specified in the mods.
If you have recently added a mod and need to take in its seed data, run decko update
.
If you already have tables but want to start over, you can use rake card:seed:replant
,
which will truncate (as in, delete everything from) the existing tables and then
add the seed data.
You can also use Ruby-on-Rails db tasks (eg db:reset
, db:drop
) for their original
purpose, but caution is advised.
Advanced
The remainder of these docs are intended as an introduction for Monkeys who may be creating or modifying seed data. You probably don’t need it if you’re working exclusively as a Shark.
Background: seeded cards often connect code with data
Decko blurs the line between data and code. That is by design, because Decko helps people who aren’t coders do things that usually only coders do. In Decko terms, we extend the capacities of sharks (ie advanced web users, so ultimately data people) into the realm of the capacities of monkeys (ie code people).
Mods often add cards used to configure things. These cards can be influenced in data (by sharks), in code (by monkeys), or both. Cards that are referred to in code have a codename used by coders, and those cards are generally added to decks via seeding.
IMPORTANT: Monkeys (coders) should never refer to a card in shared code by its name (which can change) or its id (which can vary from site to site). Instead, they should always use a codename, which is an independent permanent identifier. Often a card’s codename is the same as its name, but if a user changes the name, the codename remains the same, so the connection to the code is not broken.
How seeding works
Fixtures
Fast to load, hard to write.
Fixtures are fast-loading YAML files that are used by important tasks like decko setup
and rake card:seed:replant
.
Every deck is configured with a list of mods that contain fixtures. You can configure that
list in config/application.rb
or environment-specific
config files using config.seed_mods
. To see the current mod list, you can run
decko runner 'puts Cardio.config.seed_mods'
. A default installation will return the
following:
defaults
core
This tells you:
- Running
bundle exec decko setup
will use fixtures from the defaults mod, the first mod on the list. To see those fixtures, look in thedata/fixtures
directory of the defaults mod in the card gem. (You can userake card:mod:list
to see where all your mods are installed.) - The defaults mod’s seed data is generated using seed data in the core mod.
If you were to look in the data/fixtures
directory of either the core mod or the
defaults mod, you would find directories of yaml files that correspond to tables in
the database.
The deck described in the core mod is very small: just 11 cards. This is the minimal seed dataset, and it is the only one in which these fixtures files are edited by hand. Here is one example of a card in cards.yml:
list:
id: 4
name: List
key: list
codename: list
creator_id: 1
updater_id: 1
read_rule_class: all
read_rule_id: 10
trash: false
type_id: 3
db_content: ""
For a card’s representation to be complete, we also need to represent the action that created it, the act of that action, and any references it makes to other cards. Each of these involves lots of ids and repeated fields that are very easy to get wrong when working by hand. So generally speaking, the fixtures in the core mod are the only fixtures that ever get edited by hand (and even that is very rare).
Pods
Easy to use.
Because fixtures are hard to write, we almost always generate fixtures from simpler YAML files in mods’ data directories. The data in these “pod” files are based not on the final database structure but on the api by which cards are created.
For example, here is how the “List” card described above would look in pod yaml:
- :name: List
:codename: list
:type: :cardtype
Pod data are used not only in generating fixtures but also by decko update
, which is
used when updating code or installing mods. The idea is that in most cases Monkeys
just need to maintain their mod data in one place.
If you want more nuanced control of which cards you ingest – for example to ingest
only the cards from a given mod – you can use card eat
(or
rake card:eat
). See card eat -h
for more details.
Generating pod YAML
There are two main ways to generate seed pods:
- Write it by hand
- Export it from your deck using
card sow
(See card sow -h
for more)
Pods can use all the same arguments that are used with Card.create
or card.update
.
The most common are:
- name
- type
- codename
- content
- fields
- skip
- trigger
Because pods are ingested using Card.ensure
(which creates or updates the card as
necessary), they can also handle the conflict
argument, which manages situations where
an existing card differs from the pod. The default conflict handling will override cards
that are “pristine” – that is to say, that have not been directly edited by a user other
than Decko Bot. Setting conflict
to defer
will mean existing content is never
overridden. Setting it to override
will mean it always is.
The eat task also adds support for two additional arguments:
- user — who is credited with the action. Default is Decko Bot.
- time — when did the action take place. If not specified, uses actual time of action.
Useful for test data (see below). Value is an integer representing
unix time. If prefaced by a “+” or “-”,
we compute a time in the future or past respectively from
Time.now
.
You can also use user
to specify who should perform the action.
The standard way to ingest card pods is by using decko update
, but you can also
use card eat
for more control over your meal.
Real vs Test data
Test data is dummy data added to facilitate code testing. It is not intended to be included in live sites. Real data, by contrast, is intended for production sites.
When you add seed data to mods, you typically put it in one of two files:
- data/real.yml
- data/test.yml
If you have a lot of data, you can break them into more files. For example if you want
to add “project” data, you can add them to a file called data/real/projects.yml
and then
add a line with - projects
in the real.yml file.
Updating fixtures
The primary rake task for updating seed fixtures is card:seed:update
. When pods are
updated, you will need to run this update
task in order for the fixtures to be updated
and any changes to be reflected in the seed data.
Here’s how the fixtures are updated with rake card:seed:update
:
- seed with the existing fixtures
- run
decko update
to “eat” the pod data, run migrations, and install the mods - do some minor cleanup of mods / assets
- dump the results to the
data/fixtures
directory
Note that card:seed:update
simply loops through the card pods and ensures that they
exist. If you delete pods, it won’t notice. In that case you would need to rebuild
your seed data from scratch using card:seed:build
, which starts from the fixtures set
on which the current fixtures set depends. For example, if you were to run
rake card:seed:build
from the defaults mod, it would start by seeding from the
fixtures in the core mod. Note that when building, test data fixtures are seeded with
real data. So for deletions of real pod data to be removed from test data, one must
first rebuild the real fixtures, and then rebuild the test fixtures that depend on
them.
Creating a new fixtures set
For advanced monkeys
Fixtures sets are for packaged deployments of specific applications that combine many mods.
Let’s say you’re creating a site called mydeck
, and you want to install multiple copies
of that deck with the same seed data. Here’s how:
- Choose a mod where you want to save the seed fixtures and add the required
directories in
[mymod]/data/fixtures
- Add the following line to
config/application.rb
:config.seed_mods.unshift :mymod
- Run
rake card:seed:build
This will generate fixtures that include all your data in addition to the data from the defaults mod.
If you would like to publish your new seed data in a gem mod, then rather than
configuring the seed mod list in config/application.rb
, you will need to configure it
in the gem’s default required ruby file.
For example if you create a gem mod called card-mod-mymod
, then inside
lib/card/mod/mymod.rb
you will want something like the following:
Cardio::Railtie.config.seed_mods.unshift :defaults