my_annotations 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +32 -0
- data/README.rdoc +517 -0
- data/RUNNING_TESTS.rdoc +28 -0
- data/RakeFile +28 -0
- data/VERSION.yml +4 -0
- data/lib/my_annotations.rb +24 -0
- data/my_annotations.gemspec +19 -0
- data/script/console +7 -0
- metadata +76 -0
data/LICENSE
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
Copyright (c) 2008-2009, Regents of the University of Manchester and
|
2
|
+
the European Bioinformatics Institute (EMBL-EBI)
|
3
|
+
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions are
|
8
|
+
met:
|
9
|
+
|
10
|
+
* Redistributions of source code must retain the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer.
|
12
|
+
|
13
|
+
* Redistributions in binary form must reproduce the above copyright
|
14
|
+
notice, this list of conditions and the following disclaimer in the
|
15
|
+
documentation and/or other materials provided with the distribution.
|
16
|
+
|
17
|
+
* Neither the name of the University of Manchester nor the European
|
18
|
+
Bioinformatics Institute (EMBL-EBI) nor the names of its contributors
|
19
|
+
may be used to endorse or promote products derived from this software
|
20
|
+
without specific prior written permission.
|
21
|
+
|
22
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
23
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
24
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
25
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
26
|
+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
27
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
28
|
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
29
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
30
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
31
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
32
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,517 @@
|
|
1
|
+
This is the Gem version of Annotations plugin
|
2
|
+
|
3
|
+
= Annotations Gem
|
4
|
+
== Install
|
5
|
+
Add the following line in the Gemfile:
|
6
|
+
|
7
|
+
gem 'annotations', :git => "git://github.com/quyen/annotations.git"
|
8
|
+
|
9
|
+
== Setup
|
10
|
+
Please read the setup of the Annotations Plugin.
|
11
|
+
The only differences are the loadpaths of some dependencies. For example:
|
12
|
+
|
13
|
+
* Annotations Gem uses:
|
14
|
+
|
15
|
+
require_dependency File.join(Gem.loaded_specs['annotations'].full_gem_path,'lib','app','controllers','application_controller')
|
16
|
+
|
17
|
+
* Annotations Plugin uses:
|
18
|
+
|
19
|
+
require_dependency File.join(Rails.root, 'vendor', 'plugins', 'annotations', 'lib', 'app', 'controllers', 'application_controller')
|
20
|
+
|
21
|
+
|
22
|
+
= Annotations Plugin (for Ruby on Rails applications)
|
23
|
+
|
24
|
+
|
25
|
+
Original Author:: Jiten Bhagat (mailto:mail@jits.co.uk)
|
26
|
+
Other Authors:: Stuart Owen, Quyen Nguyen
|
27
|
+
Copyright:: (c) 2008-2013, the University of Manchester and the European Bioinformatics Institute (EMBL-EBI)
|
28
|
+
License:: BSD
|
29
|
+
Version:: 0.5.0
|
30
|
+
|
31
|
+
== IMPORTANT NOTE
|
32
|
+
|
33
|
+
In v0.2.0+ this plugin has been modified substantially to support polymorphic annotation values rather than just strings.
|
34
|
+
|
35
|
+
== Overview
|
36
|
+
|
37
|
+
This plugin allows arbitrary metadata and relationships to be stored and retrieved, in the form of *Annotations* for any model objects in your Ruby on Rails (v2.2+) application.
|
38
|
+
|
39
|
+
Annotations are in the form:
|
40
|
+
|
41
|
+
Annotation = Annotatable (what thing are you talking about?)
|
42
|
+
+ Attribute (what is the kind/class of annotation? [tag? description?])
|
43
|
+
+ Value (what is the data or other thing you want to associate with the annotatable))
|
44
|
+
+ Source (who/what made this annotation?)
|
45
|
+
+ Version Info (how many versions of this annotation are there?)
|
46
|
+
+ Timestamps (when was this annotation created/updated?)
|
47
|
+
|
48
|
+
|
49
|
+
The idea is to provide a consistent and systematic way to abstract out and decouple annotations from your application's core data model and allow layering in of metadata/relationships easily.
|
50
|
+
|
51
|
+
Examples of things you can use the annotations plugin for:
|
52
|
+
* Tags
|
53
|
+
* Categories
|
54
|
+
* Descriptions
|
55
|
+
* Examples
|
56
|
+
* Notes
|
57
|
+
* Comments
|
58
|
+
|
59
|
+
A concrete example of a 'tag' Annotation:
|
60
|
+
|
61
|
+
Ann1 = <car SF8 JK0> (Annotatable)
|
62
|
+
+ <tag> (Attribute)
|
63
|
+
+ <dirty> (Value)
|
64
|
+
+ <Autobot 3000> (Source)
|
65
|
+
+ <v1> (Version Info)
|
66
|
+
+ <2011-07-06 10:00> (Timestamps)
|
67
|
+
|
68
|
+
A concrete example of another kind of Annotation:
|
69
|
+
|
70
|
+
Ann1 = <dog jack> (Annotatable)
|
71
|
+
+ <isBreed> (Attribute)
|
72
|
+
+ <chihuahua> (Value)
|
73
|
+
+ <Dave Elias> (Source)
|
74
|
+
+ <v2> (Version Info)
|
75
|
+
+ <2011-07-06 11:00> (Timestamps)
|
76
|
+
|
77
|
+
The main benefit is that annotations are stored and retrieved in a uniform manner with a common API. Parts of the plugin can also be extended and overridden in your application (see the Usage section for more info).
|
78
|
+
|
79
|
+
The annotations plugin is currently being used successfully in the BioCatalogue {codebase}[http://rubyforge.org/projects/biocatalogue] to allow easy annotation of web services and their deployments/versions/operations/inputs/outputs/etc. Check out http://www.biocatalogue.org.
|
80
|
+
|
81
|
+
=== Features:
|
82
|
+
|
83
|
+
* A complete set of ActiveRecord models for annotations, annotation attributes and annotation values and annotation value seeds.
|
84
|
+
* acts_as_annotatable, acts_as_annotation_source and acts_as_annotation_value mixin modules for your models, complete with a number of advanced finders.
|
85
|
+
* A basic CRUD controller that can be used out of the box to list, create, view, edit and delete annotations.
|
86
|
+
* Versioning of annotations - all updates to annotations cause a new version of that annotation to be created.
|
87
|
+
* Annotation Value Seeds can be used to set up some default/preliminary seed data for attributes without having to create annotations.
|
88
|
+
* Lots of configuration options!
|
89
|
+
|
90
|
+
== Full Documentation
|
91
|
+
|
92
|
+
To generate full documentation (including this readme and full API docs) do the following:
|
93
|
+
|
94
|
+
Install RDoc (v2.3.0 or above):
|
95
|
+
|
96
|
+
% [sudo] gem install rdoc
|
97
|
+
|
98
|
+
Install the darkfish-rdoc gem:
|
99
|
+
|
100
|
+
% [sudo] gem install darkfish-rdoc
|
101
|
+
|
102
|
+
Run the following command in the plugin's root directory (_vendor/plugins/annotations_):
|
103
|
+
|
104
|
+
% rdoc -SHNU -w 2 --title='Annotations Plugin' -m 'INDEX.rdoc' -x '(/doc|/tasks|/script|/test)'
|
105
|
+
|
106
|
+
The generated documentation will be in the _doc_ folder of the annotations plugin.
|
107
|
+
|
108
|
+
== Conceptual Data Model
|
109
|
+
|
110
|
+
At a conceptual level, an *Annotation* consists of:
|
111
|
+
* a link to the thing being annotated - the *Annotatable*
|
112
|
+
* a link to the attribute which specifies what kind of annotation this is - the *Attribute*
|
113
|
+
* a link to the value of the annotation - the *Value*
|
114
|
+
* a link to the source of the annotation - the *Source*
|
115
|
+
* version information - *Version Info*
|
116
|
+
* timestamps for event time info - *Timestamps*
|
117
|
+
|
118
|
+
This can be represented as:
|
119
|
+
|
120
|
+
Annotation = Annotatable + Attribute + Value + Source + Version Info + Timestamps
|
121
|
+
|
122
|
+
The database model for an Annotation is made up of the following fields:
|
123
|
+
|
124
|
+
| id | annotatable_type | annotatable_id | source_type | source_id | attribute_id | value_type | value_id | version | version_creator_id | created_at | updated_at |
|
125
|
+
|
126
|
+
This makes use of ActiveRecord polymorphic relationships to allow any ActiveRecord model to be an Annotatable, Source and Value.
|
127
|
+
|
128
|
+
*Note:* The _version_creator_id_ field is only relevant when there are more than one version of an Annotation. I.e.: for the first version of the annotation the _version_creator_id_ will be nil.
|
129
|
+
|
130
|
+
Annotation Attributes currently consist of a name and a unique identifier (in the form of a URI). This is the _attribute_ or _property_ you are describing for an Annotatable. Examples: 'tag', 'description', etc.
|
131
|
+
|
132
|
+
== Versioning of Annotations
|
133
|
+
|
134
|
+
Whenever an Annotation is updated, a new AnnotationVersion entry is created in the db (corresponding model name = Annotation::Version).
|
135
|
+
|
136
|
+
This uses a library from the {version_fu plugin}[http://github.com/jmckible/version_fu/tree/master]. A customised version of this is embedded within the Annotations plugin (which won't conflict if version_fu is installed in the main codebase).
|
137
|
+
|
138
|
+
== Installation and Setup
|
139
|
+
|
140
|
+
=== Important Requirements
|
141
|
+
|
142
|
+
* Only works for Ruby on Rails v2.2 and above.
|
143
|
+
* Your Application Controller MUST define (or have access to) the following methods:
|
144
|
+
* _login_required_ - a method that checks if the user is logged in and if not redirects to the login page.
|
145
|
+
* _logged_in?_ - a method to check if the user is logged_in.
|
146
|
+
* _current_user_ - a method to retrieve the currently logged in user. This MUST return nil if no user is currently logged in.
|
147
|
+
|
148
|
+
=== Installation
|
149
|
+
|
150
|
+
To install the plugin as a git cloned repo (this allows you to easily update the plugin in the future):
|
151
|
+
|
152
|
+
ruby script/plugin install git://github.com/myGrid/annotations.git
|
153
|
+
|
154
|
+
*Note:* this requires git to be installed.
|
155
|
+
|
156
|
+
To install the plugin the regular way:
|
157
|
+
|
158
|
+
ruby script/plugin install http://github.com/myGrid/annotations.git/
|
159
|
+
|
160
|
+
=== Setup
|
161
|
+
|
162
|
+
* Generate the migration(s):
|
163
|
+
|
164
|
+
ruby script/generate annotations_migration all
|
165
|
+
|
166
|
+
* Create a config file - _config/initializers/annotations.rb_ - for the plugin specific configuration (see Usage section for the available config options)
|
167
|
+
|
168
|
+
* Modify your application to work with the plugin:
|
169
|
+
|
170
|
+
* Add the following line to the top of your _app/controllers/application_controller.rb_ file (or _application.rb_ in older versions of Rails):
|
171
|
+
|
172
|
+
require_dependency File.join(Rails.root, 'vendor', 'plugins', 'annotations', 'lib', 'app', 'controllers', 'application_controller')
|
173
|
+
|
174
|
+
* Add the following line to the top of your _app/helpers/application_helper.rb_ file:
|
175
|
+
|
176
|
+
require_dependency File.join(Rails.root, 'vendor', 'plugins', 'annotations', 'lib', 'app', 'helpers', 'application_helper')
|
177
|
+
|
178
|
+
*Note:* the _require_dependency_ line is crucial in making your app work with the files in the plugin and allows for easy extension and overriding of the plugin parts. *However, this does mean that any file with the _require_dependency_ line will not be automagically loaded by Rails in development mode when changes have been made - a server restart is required whenever any changes are made to these files.*
|
179
|
+
|
180
|
+
* Create the following files in your application:
|
181
|
+
|
182
|
+
* \Annotation model:
|
183
|
+
|
184
|
+
# app/models/annotation.rb
|
185
|
+
#
|
186
|
+
# This extends the Annotation model defined in the Annotations plugin.
|
187
|
+
|
188
|
+
require_dependency File.join(Rails.root, 'vendor', 'plugins', 'annotations', 'lib', 'app', 'models', 'annotation')
|
189
|
+
|
190
|
+
class Annotation < ActiveRecord::Base
|
191
|
+
end
|
192
|
+
|
193
|
+
* \AnnotationAttribute model:
|
194
|
+
|
195
|
+
# app/models/annotation_attribute.rb
|
196
|
+
#
|
197
|
+
# This extends the AnnotationAttribute model defined in the Annotations plugin.
|
198
|
+
|
199
|
+
require_dependency File.join(Rails.root, 'vendor', 'plugins', 'annotations', 'lib', 'app', 'models', 'annotation_attribute')
|
200
|
+
|
201
|
+
class AnnotationAttribute < ActiveRecord::Base
|
202
|
+
end
|
203
|
+
|
204
|
+
* \AnnotationsController controller:
|
205
|
+
|
206
|
+
# app/controllers/annotations_controller.rb
|
207
|
+
#
|
208
|
+
# This extends the AnnotationsController controller defined in the Annotations plugin.
|
209
|
+
|
210
|
+
require_dependency File.join(Rails.root, 'vendor', 'plugins', 'annotations', 'lib', 'app', 'controllers', 'annotations_controller')
|
211
|
+
|
212
|
+
class AnnotationsController < ApplicationController
|
213
|
+
end
|
214
|
+
|
215
|
+
These are used to extend/override the models and controller from the plugin with extra actions, filters, validations, processing and so on (see Usage section for more details and examples).
|
216
|
+
|
217
|
+
* Specify which models in your codebase can be *annotated* by adding _acts_as_annotatable_ in the model's definition. For example:
|
218
|
+
|
219
|
+
class Service < ActiveRecord::Base
|
220
|
+
...
|
221
|
+
acts_as_annotatable
|
222
|
+
...
|
223
|
+
end
|
224
|
+
|
225
|
+
* Specify which models in your codebase can be the *source* of annotations by adding _acts_as_annotation_source_ in the model's definition. For example:
|
226
|
+
|
227
|
+
class User < ActiveRecord::Base
|
228
|
+
...
|
229
|
+
acts_as_annotation_source
|
230
|
+
...
|
231
|
+
end
|
232
|
+
|
233
|
+
The Annotations plugin has now been installed and is ready for use. See the Usage section for further details.
|
234
|
+
|
235
|
+
|
236
|
+
== Usage
|
237
|
+
|
238
|
+
=== Quick Use
|
239
|
+
|
240
|
+
* To add a bunch of Annotations to a model instance:
|
241
|
+
|
242
|
+
book = Book.find(1)
|
243
|
+
data = {
|
244
|
+
:description => "My bookie wookie",
|
245
|
+
:rating => 5,
|
246
|
+
:tag => [ "horror", "romance", "indiluted", "true story" ] }
|
247
|
+
new_annotations = book.create_annotations(data, current_user)
|
248
|
+
|
249
|
+
* Create an Annotation directly:
|
250
|
+
|
251
|
+
book = Book.find(10)
|
252
|
+
ann1 = Annotation.new(:attribute_name => "tag",
|
253
|
+
:value => "hot",
|
254
|
+
:source_type => "User",
|
255
|
+
:source_id => 100,
|
256
|
+
:annotatable_type => book.class.name,
|
257
|
+
:annotatable_id => book.id)
|
258
|
+
|
259
|
+
* Building a simple form for adding a single Annotation, like 'description', to a specified model object:
|
260
|
+
|
261
|
+
<% form_tag annotations_url do %>
|
262
|
+
<%= hidden_field_tag "annotation[annotatable_type]", "Book" -%>
|
263
|
+
<%= hidden_field_tag "annotation[annotatable_id]", 100 -%>
|
264
|
+
<%= hidden_field_tag "annotation[attribute_name]", "description" -%>
|
265
|
+
<%= text_area_tag "annotation[value]" -%>
|
266
|
+
<%= submit_tag "Submit", :disable_with => "Submitting..." -%>
|
267
|
+
<% end %>
|
268
|
+
|
269
|
+
* Building a simple form for adding multiple Annotations from one field, like 'tags', to a specified model object:
|
270
|
+
|
271
|
+
<% form_tag create_multiple_annotations_url do %>
|
272
|
+
<%= hidden_field_tag "separator", "," -%>
|
273
|
+
<%= hidden_field_tag "annotation[annotatable_type]", "Book" -%>
|
274
|
+
<%= hidden_field_tag "annotation[annotatable_id]", 100 -%>
|
275
|
+
<%= hidden_field_tag "annotation[attribute_name]", "description" -%>
|
276
|
+
<%= text_area_tag "annotation[value]" -%>
|
277
|
+
<%= submit_tag "Submit", :disable_with => "Submitting..." -%>
|
278
|
+
<% end %>
|
279
|
+
|
280
|
+
* Find all Annotations for a model instance (that has _acts_annotatable_ specified in the model's class):
|
281
|
+
|
282
|
+
book = Book.find(6806)
|
283
|
+
annotations = book.annotations
|
284
|
+
|
285
|
+
* Find all 'tag' Annotations for a model instance (that has _acts_annotatable_ specified in the model's class):
|
286
|
+
|
287
|
+
book = Book.find(23)
|
288
|
+
tag_annotations = book.annotations_with_attribute("tag")
|
289
|
+
|
290
|
+
* Find all Annotations for a model instance that have a number of different attribute names (that has _acts_annotatable_ specified in the model's class):
|
291
|
+
|
292
|
+
book = Book.find(22124)
|
293
|
+
rating_annotations = book.annotations_with_attributes([ "rating-performance", "rating-usefulness", "rating-documentation" ])
|
294
|
+
|
295
|
+
See _More Examples_ below.
|
296
|
+
|
297
|
+
=== Important Usage Notes
|
298
|
+
|
299
|
+
* When using the built in Annotations Controller to create annotations (as in the forms examples above), the default is to use the _current_user_ as the Source. However, you can explicitly specify the source by adding fields for "annotations[source_type]" and "annotations[source_id]".
|
300
|
+
* Attributes are NOT case-sensitive. So 'description' and 'Description' will be the same AnnotationAttribute entity and therefore all annotations with that attribute will be the exact same type/class/kind of annotation).
|
301
|
+
* When displaying the values of annotations, ALWAYS clean the data using methods like _h_ (html escape), _sanitize_ and _white_list_.
|
302
|
+
* By default, duplicate annotations cannot be created (by "duplicate" we mean: same value for the same attribute, on an annotatable object, regardless of source). For example: a user cannot add a description to a service that matches an existing description for that service. You can override this behaviour for annotations with certain attributes, using the configuration option: _attribute_names_to_allow_duplicates_. NOTE: this is different to the _limits_per_source_ config_ option, which isn't about duplicate annotations, but rather limiting the quantity of annotations of a specific attribute on a specific annotatable object by a specific source.
|
303
|
+
|
304
|
+
=== Config Options
|
305
|
+
|
306
|
+
All the config options can be found in _lib/annotations/config.rb_, listed below:
|
307
|
+
|
308
|
+
* *attribute_names_for_values_to_be_downcased*
|
309
|
+
* *attribute_names_for_values_to_be_upcase*
|
310
|
+
* *strip_text_rules*
|
311
|
+
* *user_model_name*
|
312
|
+
* *limits_per_source*
|
313
|
+
* *attribute_names_to_allow_duplicates*
|
314
|
+
* *value_restrictions*
|
315
|
+
|
316
|
+
TODO: explain and document these.
|
317
|
+
|
318
|
+
=== More Examples
|
319
|
+
|
320
|
+
* Create multiple 'tag' Annotations from a single string value:
|
321
|
+
|
322
|
+
params = { :annotatable_type => "Book",
|
323
|
+
:annotatable_id => 78,
|
324
|
+
:attribute_name => "tag",
|
325
|
+
:value => "workflow, taverna, brilliant",
|
326
|
+
:source_type => "Group",
|
327
|
+
:source_id => 4 }
|
328
|
+
Annotation.create_multiple(params, ',')
|
329
|
+
|
330
|
+
* Find all 'comment' Annotations, by a specified Source, for a model instance (that has _acts_annotatable_ specified in the model's class):
|
331
|
+
|
332
|
+
book = Book.find(67)
|
333
|
+
user = User.find_by_name("jane")
|
334
|
+
annotations = book.annotations_with_attribute_and_by_source("comment", user)
|
335
|
+
|
336
|
+
* Find all Annotations, that don't have the specified attributes, for a model instance (that has _acts_annotatable_ specified in the model's class):
|
337
|
+
|
338
|
+
book = Book.find(56)
|
339
|
+
annotations = book.all_annotations_excluding_attributes([ "tag", "note", "example" ])
|
340
|
+
|
341
|
+
* Find Annotatable objects that have a specific attribute name AND value:
|
342
|
+
|
343
|
+
* Gets all annotatables regardless of type:
|
344
|
+
|
345
|
+
Annotation.find_annotatables_with_attribute_name_and_value("complexity", "O(x^2)")
|
346
|
+
|
347
|
+
* Gets only annotatables that are Books:
|
348
|
+
|
349
|
+
Book.with_annotations_with_attribute_name_and_value("Tag", "Amusing rhetoric")
|
350
|
+
|
351
|
+
* Find Annotatable objects that have a combination of attribute names AND values:
|
352
|
+
|
353
|
+
Annotation.find_annotatables_with_attribute_names_and_values([ "tag" ], [ "fiction", "sci-fi", "fantasy" ])
|
354
|
+
|
355
|
+
Annotation.find_annotatables_with_attribute_names_and_values([ "tag", "keyword", "category" ], [ "fiction", "fantasy" ])
|
356
|
+
|
357
|
+
* Count the number of Annotations, by any Source, for a model instance (that has _acts_annotatable_ specified in the model's class):
|
358
|
+
|
359
|
+
book = Book.find(90)
|
360
|
+
count = book.count_annotations_by("all")
|
361
|
+
|
362
|
+
* Count the number of Annotations, by Users, for a model instance (that has _acts_annotatable_ specified in the model's class):
|
363
|
+
|
364
|
+
book = Book.find(90)
|
365
|
+
count = book.count_annotations_by("User")
|
366
|
+
|
367
|
+
TODO: add more advanced examples!
|
368
|
+
|
369
|
+
=== Extending the Plugin
|
370
|
+
|
371
|
+
Most of the aspects of this plugin can be extended/overridden in your codebase.
|
372
|
+
|
373
|
+
Examples:
|
374
|
+
|
375
|
+
* To restrict the values for certain annotations, you can either use the Annotations::Config::value_restrictions setting and/or extend the Annotation model in your own codebase and use the ActiveRecord validates_inclusion_of validation. For the latter, an example is below:
|
376
|
+
|
377
|
+
require_dependency RAILS_ROOT + '/vendor/plugins/annotations/lib/app/models/annotation'
|
378
|
+
|
379
|
+
class Annotation < ActiveRecord::Base
|
380
|
+
...
|
381
|
+
|
382
|
+
validates_inclusion_of :value,
|
383
|
+
:in => [ "fruit", "nut", "fibre" ],
|
384
|
+
:message => "Please select a valid category.",
|
385
|
+
:if => Proc.new { |ann| ann.attribute_name.downcase == "category" }
|
386
|
+
|
387
|
+
...
|
388
|
+
end
|
389
|
+
|
390
|
+
TODO: add more!
|
391
|
+
|
392
|
+
==== See Also
|
393
|
+
|
394
|
+
The BioCatalogue {codebase}[http://rubyforge.org/projects/biocatalogue] contains many examples of using the Annotations plugin successfully. Some pointers:
|
395
|
+
|
396
|
+
* {Configuring the plugin}[http://biocatalogue.rubyforge.org/svn/trunk/config/initializers/biocat_main.rb] (scroll down to the "Configure the Annotations plugin" section)
|
397
|
+
* {A module to add extra logic on top of the Annotations plugin}[http://biocatalogue.rubyforge.org/svn/trunk/lib/bio_catalogue/annotations.rb]
|
398
|
+
* {The extended \Annotation model}[http://biocatalogue.rubyforge.org/svn/trunk/app/models/annotation.rb]
|
399
|
+
* {The extended \AnnotationAttribute model}[http://biocatalogue.rubyforge.org/svn/trunk/app/models/annotation_attribute.rb]
|
400
|
+
* {The extended \AnnotationsController controller}[http://biocatalogue.rubyforge.org/svn/trunk/app/controllers/annotations_controller.rb]
|
401
|
+
* The \AnnotationsHelper helper (to be added)
|
402
|
+
* {Views and partials for annotations}[http://biocatalogue.rubyforge.org/svn/trunk/app/views/annotations/]
|
403
|
+
* Tags (all of these build a layer on top of the annotations plugin, specifically for tagging of objects):
|
404
|
+
* {Module}[http://biocatalogue.rubyforge.org/svn/trunk/lib/bio_catalogue/tags.rb]
|
405
|
+
* {Controller}[http://biocatalogue.rubyforge.org/svn/trunk/app/controllers/tags_controller.rb] (adds new and alternative actions for tagging that builds on annotations).
|
406
|
+
* {Views Helper}[http://biocatalogue.rubyforge.org/svn/trunk/app/helpers/tags_helper.rb]
|
407
|
+
* Views:
|
408
|
+
* {Tags box}[http://biocatalogue.rubyforge.org/svn/trunk/app/views/annotations/_tags_box.html.erb]
|
409
|
+
* {Tags flat}[http://biocatalogue.rubyforge.org/svn/trunk/app/views/annotations/_tags_flat.html.erb]
|
410
|
+
* Ratings (all of these build a layer on top of the annotations plugin, specifically for rating of objects):
|
411
|
+
* {Controller}[http://biocatalogue.rubyforge.org/svn/trunk/app/controllers/ratings_controller.rb] (adds new and alternative actions for rating that builds on annotations).
|
412
|
+
* {Views Helper}[http://biocatalogue.rubyforge.org/svn/trunk/app/helpers/ratings_helper.rb]
|
413
|
+
* Views:
|
414
|
+
* {Ratings box}[http://biocatalogue.rubyforge.org/svn/trunk/app/views/annotations/_ratings_box.html.erb]
|
415
|
+
|
416
|
+
The prototype {Shims Library}[http://code.google.com/p/mygrid-shims-library/] also makes use of the Annotations plugin successfully and may provide some useful examples.
|
417
|
+
|
418
|
+
== Updating the Plugin
|
419
|
+
|
420
|
+
Update the plugin code using the appropriate mechanism. Then:
|
421
|
+
|
422
|
+
ruby script/generate annotations_migration vX
|
423
|
+
|
424
|
+
... where X is the version of the migration you want to generate
|
425
|
+
|
426
|
+
== Main Plugin Contents
|
427
|
+
|
428
|
+
TODO: list files and what the purpose of each is.
|
429
|
+
|
430
|
+
== Known Issues
|
431
|
+
|
432
|
+
* May not work with sqlite and sqlite3 databases.
|
433
|
+
* Not tested with Postgres DB.
|
434
|
+
* Doesn't work consistently well with Single Table Inheritance (STI).
|
435
|
+
|
436
|
+
== Troubleshooting
|
437
|
+
|
438
|
+
* Whilst running in development mode, if you get an error such as:
|
439
|
+
|
440
|
+
A copy of ApplicationController has been removed from the module tree but is still active!
|
441
|
+
|
442
|
+
... then restart your server. This is due to the way Rails autoloads files in development mode, which affects the plugin and any extensions in the main app.
|
443
|
+
|
444
|
+
== Future Plans
|
445
|
+
|
446
|
+
In no particular order:
|
447
|
+
|
448
|
+
* Allow curation assertions such as "Agree", "Useful", "Incomplete" to be made on annotations.
|
449
|
+
* Allow values to be any model rather than free text and provide a basic set of annotation value models, such as AnnotationValueFreeText, AnnotationValueNumber, AnnotationValueUri, etc
|
450
|
+
* Extend the AnnotationAttribute model to contain controlled vocabulary / ontology term information.
|
451
|
+
* Update the versioning to a better version of _version_fu_. See: http://github.com/jmckible/version_fu/network
|
452
|
+
|
453
|
+
== Appendix A: Data Model
|
454
|
+
|
455
|
+
=== Annotations
|
456
|
+
|
457
|
+
Table name: annotations
|
458
|
+
|
459
|
+
Fields:
|
460
|
+
|
461
|
+
* id
|
462
|
+
* source_type
|
463
|
+
* source_id
|
464
|
+
* annotatable_type
|
465
|
+
* annotatable_id
|
466
|
+
* attribute_id
|
467
|
+
* value
|
468
|
+
* value_type
|
469
|
+
* created_at
|
470
|
+
* updated_at
|
471
|
+
* version
|
472
|
+
* version_creator_id
|
473
|
+
|
474
|
+
=== \Annotation Versions
|
475
|
+
|
476
|
+
Table name: annotation_versions
|
477
|
+
|
478
|
+
Fields:
|
479
|
+
|
480
|
+
* id
|
481
|
+
* annotation_id
|
482
|
+
* version
|
483
|
+
* version_creator_id
|
484
|
+
* source_type
|
485
|
+
* source_id
|
486
|
+
* annotatable_type
|
487
|
+
* annotatable_id
|
488
|
+
* attribute_id
|
489
|
+
* value
|
490
|
+
* value_type
|
491
|
+
* created_at
|
492
|
+
* updated_at
|
493
|
+
|
494
|
+
=== \Annotation Attributes
|
495
|
+
|
496
|
+
Table name: annotation_attributes
|
497
|
+
|
498
|
+
Fields:
|
499
|
+
|
500
|
+
* id
|
501
|
+
* name
|
502
|
+
* created_at
|
503
|
+
* updated_at
|
504
|
+
|
505
|
+
=== \Annotation Value Seeds
|
506
|
+
|
507
|
+
Table name: annotation_value_seeds
|
508
|
+
|
509
|
+
Fields:
|
510
|
+
|
511
|
+
* id
|
512
|
+
* attribute_id
|
513
|
+
* value
|
514
|
+
* created_at
|
515
|
+
* updated_at
|
516
|
+
|
517
|
+
|
data/RUNNING_TESTS.rdoc
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
= Running Tests
|
2
|
+
|
3
|
+
To run the tests for this plugin:
|
4
|
+
|
5
|
+
* you have to install this into a dummy Rails v2.3.2 app and meet the requirements (see the README file).
|
6
|
+
|
7
|
+
* ensure the following gems are installed:
|
8
|
+
|
9
|
+
gem install plugin_test_helper -v 0.3.0
|
10
|
+
gem install mysql
|
11
|
+
|
12
|
+
* ensure database 'annotations_plugin_test' exists on a local MySQL server installation (with default ports) and username 'annotations' with password 'annotations_plugin'. Commands for MySQL:
|
13
|
+
|
14
|
+
create database annotations_plugin_test character set utf8;
|
15
|
+
create user 'annotations'@'localhost' identified by 'annotations_plugin';
|
16
|
+
grant all privileges on annotations_plugin_test.* to 'annotations'@'localhost';
|
17
|
+
|
18
|
+
* In the root of the dummy Rails app, run:
|
19
|
+
|
20
|
+
rake test:plugins PLUGIN=annotations
|
21
|
+
|
22
|
+
* For more detailed back traces, run:
|
23
|
+
|
24
|
+
rake test:plugins PLUGIN=annotations BACKTRACE=blegga
|
25
|
+
|
26
|
+
* To run a specific test file, run e.g.:
|
27
|
+
|
28
|
+
rake test:plugins PLUGIN=annotations BACKTRACE=blegga TEST=vendor/plugins/annotations/test/config_test.rb
|
data/RakeFile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the Annotations plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the Annotations plugin.'
|
16
|
+
Rake::RDocTask.new do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'doc'
|
18
|
+
rdoc.title = "Annotations Plugin"
|
19
|
+
rdoc.main = 'README.rdoc'
|
20
|
+
|
21
|
+
rdoc.rdoc_files << "LICENSE"
|
22
|
+
rdoc.rdoc_files << "**/*.rdoc"
|
23
|
+
rdoc.rdoc_files << "lib/**/*.rb"
|
24
|
+
|
25
|
+
rdoc.options << '-SHNU'
|
26
|
+
rdoc.options << '-w 2'
|
27
|
+
rdoc.options << '-f darkfish'
|
28
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "annotations", "config")
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), "annotations_version_fu")
|
4
|
+
|
5
|
+
%w{ models controllers helpers }.each do |dir|
|
6
|
+
path = File.join(File.dirname(__FILE__), 'app', dir)
|
7
|
+
$LOAD_PATH << path
|
8
|
+
ActiveSupport::Dependencies.autoload_paths << path
|
9
|
+
ActiveSupport::Dependencies.autoload_once_paths.delete(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
require File.join(File.dirname(__FILE__), "annotations", "acts_as_annotatable")
|
13
|
+
ActiveRecord::Base.send(:include, Annotations::Acts::Annotatable)
|
14
|
+
|
15
|
+
require File.join(File.dirname(__FILE__), "annotations", "acts_as_annotation_source")
|
16
|
+
ActiveRecord::Base.send(:include, Annotations::Acts::AnnotationSource)
|
17
|
+
|
18
|
+
require File.join(File.dirname(__FILE__), "annotations", "acts_as_annotation_value")
|
19
|
+
ActiveRecord::Base.send(:include, Annotations::Acts::AnnotationValue)
|
20
|
+
|
21
|
+
|
22
|
+
require File.join(File.dirname(__FILE__), "annotations", "routing")
|
23
|
+
|
24
|
+
require File.join(File.dirname(__FILE__), "annotations", "util")
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'my_annotations'
|
3
|
+
s.version = '0.5.0'
|
4
|
+
s.date = '2013-05-02'
|
5
|
+
s.summary = "This gem allows arbitrary metadata and relationships to be stored and retrieved, in the form of Annotations for any model objects in your Ruby on Rails (v2.2+) application."
|
6
|
+
s.description = "This gem allows arbitrary metadata and relationships to be stored and retrieved, in the form of Annotations for any model objects in your Ruby on Rails (v2.2+) application."
|
7
|
+
s.authors = ["Jiten Bhagat","Stuart Owen","Quyen Nguyen"]
|
8
|
+
s.email = 'nttqa22001@yahoo.com'
|
9
|
+
s.files = ["lib/my_annotations.rb",
|
10
|
+
"RakeFile",
|
11
|
+
"VERSION.yml",
|
12
|
+
"LICENSE",
|
13
|
+
"script/console",
|
14
|
+
"README.rdoc",
|
15
|
+
"RUNNING_TESTS.rdoc",
|
16
|
+
"my_annotations.gemspec"]
|
17
|
+
s.homepage = 'https://github.com/myGrid/annotations'
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
end
|
data/script/console
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
2
|
+
libs = " -r irb/completion"
|
3
|
+
libs << " -r test/test_helper"
|
4
|
+
libs << " -r plugin_test_helper/console_with_fixtures"
|
5
|
+
libs << " -r console_app"
|
6
|
+
libs << " -r console_with_helpers"
|
7
|
+
exec "#{irb} #{libs} --simple-prompt"
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: my_annotations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jiten Bhagat
|
14
|
+
- Stuart Owen
|
15
|
+
- Quyen Nguyen
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2013-05-02 00:00:00 +01:00
|
21
|
+
default_executable:
|
22
|
+
dependencies: []
|
23
|
+
|
24
|
+
description: This gem allows arbitrary metadata and relationships to be stored and retrieved, in the form of Annotations for any model objects in your Ruby on Rails (v2.2+) application.
|
25
|
+
email: nttqa22001@yahoo.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- lib/my_annotations.rb
|
34
|
+
- RakeFile
|
35
|
+
- VERSION.yml
|
36
|
+
- LICENSE
|
37
|
+
- script/console
|
38
|
+
- README.rdoc
|
39
|
+
- RUNNING_TESTS.rdoc
|
40
|
+
- my_annotations.gemspec
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: https://github.com/myGrid/annotations
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
hash: 3
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
hash: 3
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
version: "0"
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.3.7
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: This gem allows arbitrary metadata and relationships to be stored and retrieved, in the form of Annotations for any model objects in your Ruby on Rails (v2.2+) application.
|
75
|
+
test_files: []
|
76
|
+
|