my_annotations 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|