Below is a simple example of the steps for setting up a simple database driven application using Fins. Commands that should be typed are listed in bold.
hera:/tmp hww3$ curl -o Fins.zip http://hww3.riverweb.com/dist/Fins/Fins-0.2.zip
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 760k 100 760k 0 0 83665 0 0:00:09 0:00:09 --:--:-- 98487
hera:/tmp hww3$ unzip Fins.zip
Archive: Fins.zip
hera:/tmp hww3$ cd Fins-0.2/
hera:/tmp/Fins-0.2 hww3$ pike -Mlib -x fins create widgetco
/18:35:17 INFO - CreateApplication module loading
18:35:17 INFO - CreateApplication module running.
18:35:17 INFO - Creating application widgetco in /private/tmp/Fins-0.2.
18:35:17 INFO - Be sure to edit config/*.cfg to specify the application's datasource
hera:/tmp/Fins-0.2 hww3$ mysqladmin -p create -uroot foo
Enter password:
hera:/tmp/Fins-0.2 hww3$ mysql -uroot foo -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 18 to server version: 5.0.27-standard
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> grant all on foo.* to foo identified by 'foo4u';
Query OK, 0 rows affected (0.01 sec)
mysql> quit
mysql> create table widgets(
id int(11) not null auto_increment primary key,
name char(32),
on_hand int(11) ,
manufacturer_id int(11));
Query OK, 0 rows affected (0.00 sec)
mysql> create table manufacturers(
id int(11) not null auto_increment primary key,
name char(32),
phone_number char(16)
);
Query OK, 0 rows affected (0.00 sec)
mysql> Bye
hera:/tmp/Fins-0.2 hww3$ cd widgetco
hera:/tmp/Fins-0.2/widgetco hww3$ export FINS_HOME=/tmp/Fins-0.2
hera:/tmp/Fins-0.2/widgetco hww3$ bin/start.sh
18:43:08 INFO - FinServe starting on port 8080
18:43:08 INFO - Starting Session Manager.
18:43:08 INFO - FinServe loading application widgetco using configuration dev
18:43:08 DEBUG - config file: /private/tmp/Fins-0.2/widgetco/config/dev.cfg
18:43:08 INFO - Starting Cache.
18:43:08 INFO - loading model from model
18:43:08 DEBUG - loading macro "implode"
18:43:08 DEBUG - loading macro "boolean"
18:43:08 DEBUG - loading macro "javascript_includes"
18:43:08 DEBUG - loading macro "remote_form"
18:43:08 DEBUG - loading macro "capitalize"
18:43:08 DEBUG - loading macro "format_date"
18:43:08 DEBUG - loading macro "flash"
18:43:08 DEBUG - loading macro "remote_link"
18:43:08 DEBUG - loading macro "sizeof"
18:43:08 DEBUG - /private/tmp/Fins-0.2/widgetco/classes/application()->load_controller()
18:43:08 INFO - Application widgetco loaded.
18:43:08 INFO - Application ready for business.
hera:/tmp/Fins-0.2/widgetco hww3$ pike -x fins model . add manufacturers widgets
hera:/tmp/Fins-0.2/widgetco hww3$ bin/start.sh --hilfe
18:52:33 INFO - Application widgetco loaded.
Starting interactive interpreter...
Fins 0.4 running Pike v7.6 release 86 / Hilfe v3.5 (Incremental Pike Frontend)
> object m = widgetco.Objects.Manufacturer();
> m["name"] = "Spacely Sprockets";
(2) Result: "Spacely Sprockets"
> m->save();
QUERY: "INSERT INTO manufacturers (name, id) VALUES ('Spacely Sprockets', NULL)"
QUERY: "SELECT manufacturers.id AS manufacturers__id, manufacturers.name AS manufacturers__name, manufacturers.phone_number AS manufacturers__phone_number FROM manufacturers WHERE id=1"
(3) Result: 0
> object m = widgetco.Objects.Manufacturer();
> m["name"] = "Cogswell Cogs";
(4) Result: "Cogswell Cogs"
> m->save();
QUERY: "INSERT INTO manufacturers (name, id) VALUES ('Cogswell Cogs', NULL)"
QUERY: "SELECT manufacturers.id AS manufacturers__id, manufacturers.name AS manufacturers__name, manufacturers.phone_number AS manufacturers__phone_number FROM manufacturers WHERE id=2"
(5) Result: 0
> object w = widgetco.Objects.Widget();
> w["name"] = "SuperCog 2000";
(6) Result: "SuperCog 2000"
> w["Manufacturer"] = m;
(7) Result: Manufacturer(id=2)
> w["on_hand"] = 12;
(8) Result: 12
> w->save();
QUERY: "INSERT INTO widgets (manufacturer_id, id, name, on_hand) VALUES (2, NULL, 'SuperCog 2000', 12)"
QUERY: "SELECT widgets.id AS widgets__id, widgets.manufacturer_id AS widgets__manufacturer_id, widgets.name AS widgets__name widgets.on_hand AS widgets__on_hand FROM widgets WHERE id=1"
(9) Result: 0
> indices(w);
(10) Result: ({ /* 4 elements */
"on_hand",
"Manufacturer",
"name",
"id"
})
> w["Manufactuer"]["name"];
> w["Manufacturer"]["name"];
(11) Result: "Cogswell Cogs"
That's all very nice, but the description of the object is a little unfriendly. let's fix that by setting an "alternate key" field. setting an alternate key field allows us to query by that field easily, and the value of the alternate key is used in debug displays. Note that Fins doesn't envorce uniqueness of the alternate key; you should use database level techniques to do this (the UNIQUE key type). Edit t
To set an alternate key field, select the field you'd like to use, and edit that object type's model definition (in this example, modules/widgetco.pmod/Model.pmod/Manufacturer.pike:
void post_define()
{
set_alternate_key("name");
}
hera:/tmp/Fins-0.2/widgetco hww3$ bin/start.sh --hilfe
20:24:22 INFO - FinServe starting on port 8080
...
Starting interactive interpreter...
Fins 0.4 running Pike v7.6 release 112 / Hilfe v3.5 (Incremental Pike Frontend)
> Fins.Model.find.manufacturers_by_id(1);
(1) Result: Manufacturer(name=Spacely Sprockets)
> Fins.Model.find.manufacturers_by_alternate("Cogswell Cogs");
(4) Result: Manufacturer(name=Cogswell Cogs)
Now, let's add some validation to our model. Perhaps we should make sure that phone numbers are provided in a particular format. We can use validation to perform this task. Add the validation by editing modules/widgetco.pmod/Model.pmod/Manufacturer.pike. Add the following lines of code and save the file:
// our simple phone number regexp.
constant pnf = "[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]";
void validate(mapping changes, object errors, object i)
{
if(changes->phone_number)
{
object r = Regexp.SimpleRegexp(pnf);
if(!r->match(changes->phone_number))
errors->add("phone_number", "must be in the format nnn-nnn-nnnn.");
}
}
hera:/tmp/Fins-0.2/widgetco hww3$ bin/start.sh --hilfe
20:24:22 INFO - FinServe starting on port 8080
...
Starting interactive interpreter...
Fins 0.4 running Pike v7.6 release 112 / Hilfe v3.5 (Incremental Pike Frontend)
> Fins.Model.find.manufacturers_by_id(1);
(1) Result: Manufacturer(name=Spacely Sprockets)
> object m = Fins.Model.find.manufacturers_by_id(1);
> m["phone_number"] = "8885551212";
Data Validation Error
Phone number must be in the format nnn-nnn-nnnn.
lib/Fins.pmod/Model.pmod/DataObject.pike:664:
wooga.Model.Manufacturer()->set("phone_number","1234567890",UNDEFINED,Manufac
turer(name=Spacely Sprockets))
lib/Fins.pmod/Model.pmod/DataObjectInstance.pike:223:
Manufacturer(name=Spacely Sprockets)->`[]=("phone_number","1234567890")
object manufacturers;
object widgets;
void start()
{
manufacturers = load_controller("mfg_controller");
widgets = load_controller("widget_controller");
}
Then, add the files classes/mfg_controller.pike and classes/widget_controller.pike. In the first file, add the following lines:
inherit Fins.ScaffoldController; string model_component = "Manufacturer";
In the second file, add the following lines:
inherit Fins.ScaffoldController; string model_component = "Widget";
Then, simply restart and point your web browser to /manufacturers or /widgets to edit data in your model. You'll notice that validation code will be run and any errors will be passed up to the client in a friendly way.
No comments | Post a Comment| RSS Feed | BackLinks