.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Jifty::Manual::Upgrading 3pm" .TH Jifty::Manual::Upgrading 3pm "2010-09-25" "perl v5.14.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Jifty::Manual::Upgrading \- How\-to change your application database over time .SS "\s-1DESCRIPTION\s0" .IX Subsection "DESCRIPTION" Jifty provides a way for you to upgrade the database schema and data of your application between versions. If all you are doing is adding new models or columns to existing models Jifty will do the upgrade almost automatically. If more extensive changes are required you need to write some code to tell Jifty what to do. .SH "TERMINOLOGY" .IX Header "TERMINOLOGY" Be sure you know the following terms before reading this document: .IP "\(bu" 4 \&\*(L"schema\*(R" in Jifty::Manual::Glossary .IP "\(bu" 4 \&\*(L"schema version\*(R" in Jifty::Manual::Glossary .IP "\(bu" 4 \&\*(L"database version\*(R" in Jifty::Manual::Glossary .SH "HOW TO" .IX Header "HOW TO" .SS "General Instructions" .IX Subsection "General Instructions" For all of these actions, the the database version stored in your Jifty configuration is significant. See the value stored in \fIetc/config.yml\fR at: .PP .Vb 3 \& framework: \& Database: \& Version: 0.0.1 .Ve .PP Make all your code changes using the version number \fIyou are going to use\fR. Once you have finished updating your code and are ready to test, bump the version stored in \fIetc/config.yml\fR to match the new version you are going to use. .PP If you are writing tests as you go (shame on you if you aren't!), you should be able to run: .PP .Vb 3 \& perl Makefile.PL \& make \& make test .Ve .PP to test the latest version and check for problems. .PP Once you are sure you've worked out the kinds, you may perform the actual upgrade by running: .PP .Vb 1 \& bin/jifty schema \-\-setup .Ve .PP This will take care of the work of adding any new columns and models, dropping old columns, and running any upgrade scripts you have scheduled. .SS "Basic column and model operations" .IX Subsection "Basic column and model operations" \fIAdding a new model\fR .IX Subsection "Adding a new model" .PP Create your model just as you normally would: .PP .Vb 1 \& bin/jifty model \-\-name MyModel .Ve .PP Then, you need to tell Jifty at which version of your application the model was created. To do this add a since sub to your new model class. .PP .Vb 1 \& sub since { \*(Aq0.0.5\*(Aq } .Ve .PP \fIAdding a new column to an existing model\fR .IX Subsection "Adding a new column to an existing model" .PP When you have an existing model and decide that you need to add another column to it you also need to tell Jifty about this. This is done by using \f(CW\*(C`since\*(C'\fR as well. However, the \f(CW\*(C`since\*(C'\fR goes into the column definition itself. .PP .Vb 3 \& column created_by => \& refers_to Wifty::Model::User, \& since \*(Aq0.0.20\*(Aq; .Ve .PP \fIDropping a column from a model\fR .IX Subsection "Dropping a column from a model" .PP \&\fB\s-1CAUTION:\s0\fR Be aware that all the data that was stored in this column will be destroyed at upgrade if you follow this procedure. .PP If you no longer need a particular column in your model, you can have it dropped by setting the \f(CW\*(C`till\*(C'\fR property on your column definition. .PP .Vb 4 \& column extra_info \& type is \*(Aqtext\*(Aq, \& label is \*(AqExtra info\*(Aq, \& till \*(Aq0.0.13\*(Aq; .Ve .PP The version you use for \f(CW\*(C`till\*(C'\fR is the version the drop is effective. In the example above, the \f(CW\*(C`extra_info\*(C'\fR column will be available in version 0.0.12, but not in version 0.0.13. .PP This column will be dropped from the schema at the next upgrade, \fIwhich will destroy all data stored in that column.\fR .PP \fI\s-1TODO\s0 Dropping a model\fR .IX Subsection "TODO Dropping a model" .SS "Data migration and schema changes" .IX Subsection "Data migration and schema changes" If a file called \fIUpgrade.pm\fR exists in your application it will be run by \f(CW\*(C`jifty schema \-\-setup\*(C'\fR. .PP \&\fIUpgrade.pm\fR can be used to make any schema changes or to manipulate your applications data. .PP At the very least your \fIUpgrade.pm\fR should contain the following: .PP .Vb 1 \& package MyApp::Upgrade; \& \& use base qw(Jifty::Upgrade); \& use Jifty::Upgrade qw( since rename ); \& \& since \*(Aq0.6.1\*(Aq => sub { \& .... \& }; .Ve .PP The \f(CW\*(C`since\*(C'\fR function is where you do all the work. Each \f(CW\*(C`since\*(C'\fR will be run in version order until the application is up to date. .PP \fIRenaming a column\fR .IX Subsection "Renaming a column" .PP To rename a column, you need to make sure that your schema and upgrade script both cooperate in the process. Your schema will record changes to your model \s-1API\s0 and the upgrade script will tell Jifty about the rename. .PP The old column name needs to marked with \f(CW\*(C`till\*(C'\fR to notify Jifty that the column name no longer exists. The new column name needs to marked with \f(CW\*(C`since\*(C'\fR to notify Jifty that a column by the new name exists. .PP Here we are renaming \f(CW\*(C`zip\*(C'\fR to \f(CW\*(C`postcode\*(C'\fR: .PP .Vb 4 \& column zip => \& type is \*(Aqtext\*(Aq, \& label is \*(AqZIP code\*(Aq, \& till \*(Aq0.6.1\*(Aq; \& \& column postcode => \& type is \*(Aqtext\*(Aq, \& label is \*(AqPostal code\*(Aq, \& since \*(Aq0.6.1\*(Aq; .Ve .PP Notice that both \f(CW\*(C`since\*(C'\fR and \f(CW\*(C`till\*(C'\fR have the same version number set. This is the version number the change will take place. .PP Before you upgrade, though, you must tell Jifty that a rename is happening here, which is done in your upgrade script: .PP .Vb 1 \& use MyApp::Upgrade; \& \& use base qw(Jifty::Upgrade); \& use Jifty::Upgrade qw( since rename ); \& \& since \*(Aq0.6.1\*(Aq => sub { \& rename( \& table => \*(AqMyApp::Model::User\*(Aq, \& column => \*(Aqzip\*(Aq, \& to => \*(Aqpostcode\*(Aq \& ); \& }; .Ve .PP \fIMigrating data\fR .IX Subsection "Migrating data" .PP You can perform any action you want inside the \f(CW\*(C`since\*(C'\fR blocks of your upgrade script. In the case of data migration, you might want to convert your data from one form to another. .PP For example, let's say our users always gave us \f(CW\*(C`first_name\*(C'\fR and \f(CW\*(C`last_name\*(C'\fR before, but we've added a new column \f(CW\*(C`display_name\*(C'\fR which will normally contain their name in \*(L"last, first\*(R" format, but could be customized per-account. We want to go ahead and initialize this new column during the upgrade. In your upgrade script, you could add: .PP .Vb 5 \& since \*(Aq0.2.4\*(Aq => sub { \& my $users = MyApp::Model::UserCollection\->new( \& current_user => Jifty\->app_class(\*(AqCurrentUser\*(Aq)\->superuser \& ); \& $users\->unlimit; \& \& while (my $user = $users\->next) { \& # error checks may save you from hours of debugging \& my ($status, $msg) = $user\->set_display_name( \& join(\*(Aq, \*(Aq, $user\->last_name, $user\->first_name) \& ); \& Jifty\->log\->error("Couldn\*(Aqt change user record: $msg") \& unless $status; \& } \& }; .Ve .PP Note that collection created using super user to pass \s-1ACL\s0 checks and other restrictions, if your models are protected from super user then you may have problems. See also Jifty::Manual::AccessControl. .SH "SEE ALSO" .IX Header "SEE ALSO" Jifty::Upgrade, Jifty::Script::Schema, Jifty::Manual::Models, Jifty::Manual::Tutorial, Jifty::Manual::Glossary