Zena::Remote
is a library to ease console and other script based work on a Zena application.
introduction
Unlike other ORMs, “Remote” is made to work with multiple connections to Zena applications. This enables migration from different sites and other synchronization features.
connecting to a remote
You simply create a connection to a remote with Remote.connect
and authenticate with a secure token:
require 'zena/remote' app1 = Zena::Remote.connect('http://test.host', 'mytoken')
The connection will not be authorized if the visitor is not in the “api group” of the site (group set in site settings). By default, the “api group” is empty thus forbidding any API access.
get records
There are many ways to find remote records either from a connection or from an already found node.
- from id
- from a SQLiss request
- by querying the indices
- by doing a fulltext search
All these methods are explained below.
direct id
When you need to find an object from it’s id, you use “first” method with an id:
project = app1.first(44)
QueryBuilder request
This is the most powerful tool because you can execute any SQLiss query. In fact you can implement all other solutions with this method (except the fulltext search).
all
Get a list of records (returns an array or nil):
images = app1.all('images in site')
You can also start from an existing remote node:
project.all('images in project')
Or even use ruby for simple relations:
project.pages
first
Get a single record (returns a Remote::Node
or nil):
project = app1.first('project where title like "%shazam%" in site')
Just as “all”, you can start from an existing node:
project.first('image')
or with ruby
project.image
And you can get funky:
app1.find(45).project.pages
index
Here you use the indexed properties of the objects to search. Just as with QueryBuilder based request, you can use “first” or “all”. Use a hash for this type of request:
app1.first(:title => 'shazam')
In fact this is a shortcut for the query:
app1.first("node where title = 'shazam' in site")
You can also use title like '%shazam%' in the latter. See below for another alternative that does this.
fulltext
And finally, you can execute a fulltext query (returning the first 20 entries) with:
app1.search("some text")
root
And finally, there is the special “root” node that can be found with:
app1.root
counting
You can use “count” to get the number of values:
app1.count("contacts in site")
paginate
If you need to paginate entries, or get more then 20 entries with the fulltext query, you can use “per_page” (default to 20) and “page” arguments:
app1.all("contacts in site", :page => 2, :per_page => 15)
create
To create new remote records, you can either use the connection and specify the class as an attribute or first retrieve the remote class and then execute a create:
Use connection
app1.create(:title => "New post", :class => "Post", :parent_id => 54)
Use the remote class
app1['Post'].create(:title => "New post", :parent => some_node)
You may have noticed that whenever you would specify an id or list of ids, you can also provide an instance of a remote node.
delete
You can delete an instance with:
app1.first(454).delete # or app1.first(454).destroy
mass delete
You can use the equivalent of an “all” command with “delete”.
For example, the following line destroys all images from the remote site for which the user has “drive” acces (see who can do what).
app1.delete("images in site")
This command first executes a “find” to get all records and then deletes each of them one at a time: there is no “mass” delete API on the server side.
You can also use “destroy” if you prefer the verb.
update
You can update a single instance either with “update_attributes” or save>
app1.first(454).update_attributes(:title => "Fermat's Last Theorem")
or
node = app1.first(454) node.title = "Fermat's Last Theorem" node.save
mass update
You can update many objects at once by using executing a query followed by the new attributes.
For example, the following code moves all images from the remote site in a new folder:
folder = app1['Page'].create(:title => 'gallery', :parent => app1.root) app1.update("images in site", :parent => folder)
remote class
You can access the remote (possibly virtual) class with:
app1['Post']
Once you have a class (instance of Zena::Remote::Klass
), you can use it to find objects of that class (or sub-classes), create objects of this class and get information on defined properties, relations, etc.
You can store the klass instance in a constant if you like:
Post = app1['Post']
You should only use a constant if you are connecting to a single remote server (during a console session for example).
find with a Klass
Here are some examples:
Post = app1['Post'] Post.first Post.all Post.all("created_at.year > 2010") Post.first(:title => "badaboom")
create with a Klass
When you use a remote class, you can create new remote nodes without specifying “class” argument:
app1['Post'].create(:parent => maza, :title => "Hello kitty")
logging
Since some operations can have an important impact on the data (mass update, mass delete), all update/delete operations are logged in “log/hostname.log”. The log contains all the attributes of a deleted node and attribute changes for update operations so that these operations can be reverted to a certain point.
The log does not contain version history, document files, comments, etc.
The format of the logged content is a list of operations encoded with yaml.