1 .. -*- coding: utf-8 -*- |
|
2 |
|
3 .. _Concepts: |
|
4 |
|
5 The Core Concepts of |cubicweb| |
|
6 =============================== |
|
7 |
|
8 This section defines some terms and core concepts of the |cubicweb| |
|
9 framework. To avoid confusion while reading this book, take time to go through |
|
10 the following definitions and use this section as a reference during your |
|
11 reading. |
|
12 |
|
13 .. _Cube: |
|
14 |
|
15 Cubes |
|
16 ----- |
|
17 |
|
18 A cube is a software component made of three parts: its data model |
|
19 (:file:`schema`), its logic (:file:`entities`) and its user interface |
|
20 (:file:`views`). |
|
21 |
|
22 A cube can use other cubes as building blocks and assemble them to provide |
|
23 a whole with richer functionnalities than its parts. The cubes `cubicweb-blog`_ |
|
24 and `cubicweb-comment`_ could be used to make a cube named *myblog* with |
|
25 commentable blog entries. |
|
26 |
|
27 The `|cubicweb| Forge`_ offers a large number of cubes developed by the community |
|
28 and available under a free software license. |
|
29 |
|
30 The command :command:`cubicweb-ctl list` displays the list of cubes installed on your |
|
31 system. |
|
32 |
|
33 On a Unix system, the available cubes are usually stored in the directory |
|
34 :file:`/usr/share/cubicweb/cubes`. If you're using the cubicweb forest |
|
35 (:ref:SourceInstallation), the cubes are searched in the directory |
|
36 :file:`/path/to/cubicweb_forest/cubes`. The environment variable |
|
37 :envvar:`CW_CUBES_PATH` gives additionnal locations where to search for cubes. |
|
38 |
|
39 .. _`|cubicweb| Forge`: http://www.cubicweb.org/project/ |
|
40 .. _`cubicweb-blog`: http://www.cubicweb.org/project/cubicweb-blog |
|
41 .. _`cubicweb-comment`: http://www.cubicweb.org/project/cubicweb-comment |
|
42 |
|
43 |
|
44 Instances |
|
45 --------- |
|
46 |
|
47 An instance is a runnable application installed on a computer and based on a |
|
48 cube. |
|
49 |
|
50 The instance directory contains the configuration files. Several instances can |
|
51 be created and based on the same cube. For exemple, several software forges can |
|
52 be set up on one computer system based on the `cubicweb-forge`_ cube. |
|
53 |
|
54 .. _`cubicweb-forge`: http://www.cubicweb.org/project/cubicweb-forge |
|
55 |
|
56 Instances can be of three different types: all-in-one, web engine or data |
|
57 repository. For applications that support high traffic, several web (front-end) |
|
58 and data (back-end) instances can be set-up to share the load. |
|
59 |
|
60 .. image:: ../../images/archi_globale.en.png |
|
61 |
|
62 The command :command:`cubicweb-ctl list` also displays the list of instances |
|
63 installed on your system. |
|
64 |
|
65 On a Unix system, the instances are usually stored in the directory |
|
66 :file:`/etc/cubicweb.d/`. During development, the :file:`~/etc/cubicweb.d/` |
|
67 directory is looked up, as well as the paths in :envvar:`CW_INSTANCES_DIR` |
|
68 environment variable. |
|
69 |
|
70 The term application is used to refer to "something that should do something as a |
|
71 whole", eg more like a project and so can refer to an instance or to a cube, |
|
72 depending on the context. This book will try to use *application*, *cube* and |
|
73 *instance* as appropriate. |
|
74 |
|
75 Data Repository |
|
76 --------------- |
|
77 |
|
78 The data repository [1]_ provides access to one or more data sources (including |
|
79 SQL databases, LDAP repositories, Mercurial or Subversion version control |
|
80 systems, other |cubicweb| instance repositories, GAE's DataStore, etc). |
|
81 |
|
82 All interactions with the repository are done using the Relation Query Language |
|
83 (RQL). The repository federates the data sources and hides them from the |
|
84 querier, which does not realize when a query spans accross several data sources |
|
85 and requires running sub-queries and merges to complete. |
|
86 |
|
87 It is common to run the web engine and the repository in the same process (see |
|
88 instances of type all-in-one above), but this is not a requirement. A repository |
|
89 can be set up to be accessed remotely using Pyro (`Python Remote Objects`_) and |
|
90 act as a server. |
|
91 |
|
92 Some logic can be attached to events that happen in the repository, like |
|
93 creation of entities, deletion of relations, etc. This is used for example to |
|
94 send email notifications when the state of an object changes. See `Hooks` below. |
|
95 |
|
96 .. [1] not to be confused with a Mercurial repository or a Debian repository. |
|
97 .. _`Python Remote Objects`: http://pyro.sourceforge.net/ |
|
98 |
|
99 Web Engine |
|
100 ---------- |
|
101 |
|
102 The web engine replies to http requests and runs the user interface |
|
103 and most of the application logic. |
|
104 |
|
105 By default the web engine provides a default user interface based on |
|
106 the data model of the instance. Entities can be created, displayed, |
|
107 updated and deleted. As the default user interface is not very fancy, |
|
108 it is usually necessary to develop your own. |
|
109 |
|
110 Schema (Data Model) |
|
111 ------------------- |
|
112 |
|
113 The data model of a cube is described as an entity-relationship schema using a |
|
114 comprehensive language made of Python classes imported from the yams_ library. |
|
115 |
|
116 .. _yams: http://www.logilab.org/project/yams/ |
|
117 |
|
118 An `entity type` defines a set of attributes and is used in some relations. |
|
119 Attributes may be of the following types: `String`, `Int`, `Float`, `Boolean`, |
|
120 `Date`, `Time`, `Datetime`, `Interval`, `Password`, `Bytes`, `RichString`. See |
|
121 :ref:`yams.BASE_TYPES` for details. |
|
122 |
|
123 A `relation type` is used to define an oriented binary relation between two |
|
124 entity types. The left-hand part of a relation is named the `subject` and the |
|
125 right-hand part is named the `object`. |
|
126 |
|
127 A `relation definition` is a triple (*subject entity type*, *relation type*, *object |
|
128 entity type*) associated with a set of properties such as cardinality, |
|
129 constraints, etc. |
|
130 |
|
131 Permissions can be set on entity types and relation types to control who will be |
|
132 able to create, read, update or delete entities and relations. |
|
133 |
|
134 Some meta-data necessary to the system is added to the data model. That includes |
|
135 entities like users and groups, the entities used to store the data model |
|
136 itself and attributes like unique identifier, creation date, creator, etc. |
|
137 |
|
138 When you create a new |cubicweb| instance, the schema is stored in the database. |
|
139 When the cubes the instance is based on evolve, they may change their data model |
|
140 and provide migration scripts that will be executed when the administrator will |
|
141 run the upgrade process for the instance. |
|
142 |
|
143 Registries and Objects |
|
144 ---------------------- |
|
145 |
|
146 Application objects |
|
147 ~~~~~~~~~~~~~~~~~~~ |
|
148 |
|
149 Beside a few core functionalities, almost every feature of the framework is |
|
150 achieved by dynamic objects (`application objects` or `appobjects`) stored in a |
|
151 two-levels registry (the `vregistry`). Each object is affected to a registry with |
|
152 an identifier in this registry. You may have more than one object sharing an |
|
153 identifier in the same registry, At runtime, appobjects are selected in the |
|
154 vregistry according to the context. |
|
155 |
|
156 Application objects are stored in the registry using a two-level hierarchy : |
|
157 |
|
158 object's `__registry__` : object's `id` : [list of app objects] |
|
159 |
|
160 The base class of appobjects is `AppObject` (module `cubicweb.appobject`). |
|
161 |
|
162 The `vregistry` |
|
163 ~~~~~~~~~~~~~~~ |
|
164 |
|
165 At startup, the `registry` inspects a number of directories looking |
|
166 for compatible classes definition. After a recording process, the |
|
167 objects are assigned to registers so that they can be selected |
|
168 dynamically while the instance is running. |
|
169 |
|
170 Selectors |
|
171 ~~~~~~~~~ |
|
172 |
|
173 Each appobject has a selector, that is used to compute how well the object fits |
|
174 a given context. The better the object fits the context, the higher the score. |
|
175 |
|
176 |cubicweb| provides a set of basic selectors that may be parametrized. Selectors |
|
177 can be combined with the binary operators `&` and `|` to build more complex |
|
178 selector that can be combined too. |
|
179 |
|
180 There are three common ways to retrieve some appobject from the repository: |
|
181 |
|
182 * get the most appropriate objects by specifying a registry and an identifier. In |
|
183 that case, the object with the greatest score is selected. There should always |
|
184 be a single appobject with a greater score than others. |
|
185 |
|
186 * get all appobjects applying to a context by specifying a registry. In |
|
187 that case, every object with the a postive score is selected. |
|
188 |
|
189 * get the object within a particular registry/identifier. In that case no |
|
190 selection process is involved, the vregistry will expect to find a single |
|
191 object in that cell. |
|
192 |
|
193 Selector sets are the glue that tie views to the data model. Using them |
|
194 appropriately is an essential part of the construction of well behaved cubes. |
|
195 |
|
196 When no score is higher than the others, an exception is raised in development |
|
197 mode to let you know that the engine was not able to identify the view to |
|
198 apply. This error is silenced in production mode and one of the objects with the |
|
199 higher score is picked. |
|
200 |
|
201 If no object has a positive score, ``NoSelectableObject`` exception is raised. |
|
202 |
|
203 If no object is found for a particular registry and identifier, |
|
204 ``ObjectNotFound`` exception is raised. |
|
205 |
|
206 In such cases you would need to review your design and make sure your views are |
|
207 properly defined. |
|
208 |
|
209 |
|
210 |
|
211 The RQL query language |
|
212 ---------------------- |
|
213 |
|
214 **No need for a complicated ORM when you have a powerful query language** |
|
215 |
|
216 All the persistent data in a |cubicweb| instance is retrieved and modified by using the |
|
217 Relation Query Language. |
|
218 |
|
219 This query language is inspired by SQL but is on a higher level in order to |
|
220 emphasize browsing relations. |
|
221 |
|
222 db-api |
|
223 ~~~~~~ |
|
224 |
|
225 The repository exposes a `db-api`_ like api but using the RQL instead of SQL. |
|
226 XXX feed me |
|
227 |
|
228 Result set |
|
229 ~~~~~~~~~~ |
|
230 |
|
231 Every request made (using RQL) to the data repository returns an |
|
232 object we call a Result Set. It enables easy use of the retrieved |
|
233 data, providing a translation layer between the backend's native |
|
234 datatypes and |cubicweb| schema's EntityTypes. |
|
235 |
|
236 Result sets provide access to the raw data, yielding either basic |
|
237 Python data types, or schema-defined high-level entities, in a |
|
238 straightforward way. |
|
239 |
|
240 |
|
241 Views |
|
242 ----- |
|
243 |
|
244 **CubicWeb| is data driven** |
|
245 |
|
246 The view system is loosely coupled to data through a selection |
|
247 system. Views are, in essence, defined by an id, a selection predicate |
|
248 and an entry point (generaly producing html). |
|
249 |
|
250 XXX feed me. |
|
251 |
|
252 |
|
253 Hooks |
|
254 ----- |
|
255 |
|
256 **CubicWeb provides an extensible data repository** |
|
257 |
|
258 The data model defined using Yams types allows to express the data |
|
259 model in a comfortable way. However several aspects of the data model |
|
260 can not be expressed there. For instance: |
|
261 |
|
262 * managing computed attributes |
|
263 |
|
264 * enforcing complicated structural invariants |
|
265 |
|
266 * real-world side-effects linked to data events (email notification |
|
267 being a prime example) |
|
268 |
|
269 The hook system is much like the triggers of an SQL database engine, |
|
270 except that: |
|
271 |
|
272 * it is not limited to one specific SQL backend (every one of them |
|
273 having an idiomatic way to encode triggers), nor to SQL backends at |
|
274 all (think about LDAP or a Subversion repository) |
|
275 |
|
276 * it is well-coupled to the rest of the framework |
|
277 |
|
278 Hooks are basically functions that dispatch on both: |
|
279 |
|
280 * events : after/before add/update/delete on entities/relations |
|
281 |
|
282 * entity or relation types |
|
283 |
|
284 They are an essential building block of any moderately complicated |
|
285 cubicweb application. |
|
286 |
|
287 |
|
288 .. _RunMode: |
|
289 |
|
290 Running mode |
|
291 ------------ |
|
292 |
|
293 A running mode is a predifined set of configuration telling where it should look |
|
294 for various resources, such as cubes, instances, etc. To ease development with |
|
295 the framework, there are two running modes with |cubicweb|: |
|
296 |
|
297 * 'user', resources are searched / created in the user home directory: |
|
298 - instances are stored in :file:`~/etc/cubicweb.d` |
|
299 - temporary files (such as pid file) in :file:`/tmp` |
|
300 |
|
301 * 'system', resources are searched / created in the system directories (eg usually requiring root access): |
|
302 - instances are stored in :file:`/etc/cubicweb.d` |
|
303 - temporary files (such as pid file) in :file:`/var/run/cubicweb` |
|
304 |
|
305 Cubes search path is also affected, see the :ref:Cube section. |
|
306 |
|
307 By default, the mode automatically set to 'user' if a :file:`.hg` directory is found |
|
308 in the cubicweb package, else it's set to 'system'. You can force this by setting |
|
309 the :envvar:`CW_MODE` environment variable to either 'user' or 'system'. |
|
310 |
|
311 If you've a doubt about the mode you're currently running, check the first line |
|
312 outputed by the :command:`cubicweb-ctl list` command. |
|
313 |
|
314 Notice that each resource path may be explicitly set using an environment |
|
315 variable if the default doesn't suit your needs. |
|
316 |
|
317 .. |cubicweb| replace:: *CubicWeb* |
|