yogo-project 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +27 -0
- data/Gemfile +34 -0
- data/Gemfile.lock +198 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/features/step_definitions/yogo_project_steps.rb +0 -0
- data/features/support/env.rb +1 -0
- data/features/yogo_project.feature +9 -0
- data/lib/datamapper/adapters/postgres.rb +9 -0
- data/lib/datamapper/adapters/sqlite.rb +9 -0
- data/lib/yogo-project.rb +2 -0
- data/lib/yogo/collection.rb +12 -0
- data/lib/yogo/collection/asset.rb +12 -0
- data/lib/yogo/collection/asset/model.rb +11 -0
- data/lib/yogo/collection/asset/model_configuration.rb +21 -0
- data/lib/yogo/collection/asset/model_properties.rb +47 -0
- data/lib/yogo/collection/base.rb +69 -0
- data/lib/yogo/collection/base/collection_repository.rb +21 -0
- data/lib/yogo/collection/base/model.rb +20 -0
- data/lib/yogo/collection/base/model_collection_context.rb +25 -0
- data/lib/yogo/collection/base/model_configuration.rb +34 -0
- data/lib/yogo/collection/data.rb +61 -0
- data/lib/yogo/collection/data/model.rb +72 -0
- data/lib/yogo/collection/data/model_configuration.rb +42 -0
- data/lib/yogo/collection/data/model_properties.rb +15 -0
- data/lib/yogo/collection/field_view.rb +26 -0
- data/lib/yogo/collection/form.rb +22 -0
- data/lib/yogo/collection/property.rb +127 -0
- data/lib/yogo/collection/static.rb +13 -0
- data/lib/yogo/collection/static/model_configuration.rb +31 -0
- data/lib/yogo/configuration.rb +9 -0
- data/lib/yogo/datamapper/model/common/properties.rb +16 -0
- data/lib/yogo/datamapper/model/configuration.rb +31 -0
- data/lib/yogo/datamapper/model/operations/add.rb +34 -0
- data/lib/yogo/datamapper/model/operations/clear.rb +29 -0
- data/lib/yogo/datamapper/model/stored/configuration.rb +25 -0
- data/lib/yogo/datamapper/repository_manager.rb +30 -0
- data/lib/yogo/datamapper/repository_manager/model.rb +40 -0
- data/lib/yogo/datamapper/repository_manager/resource.rb +124 -0
- data/lib/yogo/example/dynamic/project_full.rb +48 -0
- data/lib/yogo/example/dynamic/project_remix.rb +16 -0
- data/lib/yogo/example/voeis/managed/data_stream.rb +39 -0
- data/lib/yogo/example/voeis/managed/site.rb +51 -0
- data/lib/yogo/example/voeis/project.rb +57 -0
- data/lib/yogo/operation.rb +49 -0
- data/lib/yogo/project.rb +32 -0
- data/lib/yogo/property_ext.rb +7 -0
- data/spec/resource/.gitdir +0 -0
- data/spec/resource/text_file_asset.txt +1 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/yogo/all_collection_data_models_spec.rb +34 -0
- data/spec/yogo/all_collection_managers_spec.rb +18 -0
- data/spec/yogo/all_collections_spec.rb +54 -0
- data/spec/yogo/all_data_collections_spec.rb +51 -0
- data/spec/yogo/asset_collection_spec.rb +28 -0
- data/spec/yogo/data_collection_spec.rb +16 -0
- data/yogo-project.gemspec +128 -0
- metadata +222 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'yogo/configuration'
|
2
|
+
require 'yogo/datamapper/model/configuration'
|
3
|
+
require 'yogo/datamapper/model/common/properties'
|
4
|
+
require 'dm-types/yaml'
|
5
|
+
|
6
|
+
DataMapper.setup(:default, :adapter => 'sqlite3', :database => 'dynamic_project.db')
|
7
|
+
|
8
|
+
class ProjectFull
|
9
|
+
include DataMapper::Resource
|
10
|
+
|
11
|
+
Yogo::DataMapper::Model::Common::Properties::UUIDKey[self]
|
12
|
+
|
13
|
+
property :name, String, :required => true
|
14
|
+
|
15
|
+
has n, :managed_models
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
class ManagedModel
|
20
|
+
include DataMapper::Resource
|
21
|
+
include Yogo::DataMapper::Model::Configuration
|
22
|
+
|
23
|
+
Yogo::DataMapper::Model::Common::Properties::UUIDKey[self]
|
24
|
+
property :name, String, :required => true
|
25
|
+
|
26
|
+
has n, :model_operations
|
27
|
+
|
28
|
+
def operation_definitions
|
29
|
+
model_operations.map{|model_op| model_op.to_a }
|
30
|
+
end
|
31
|
+
|
32
|
+
def update(model=nil)
|
33
|
+
to_proc.call(model || (@_model ||= DataMapper::Model.new))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class ModelOperation
|
38
|
+
include DataMapper::Resource
|
39
|
+
|
40
|
+
Yogo::DataMapper::Model::Common::Properties::UUIDKey[self]
|
41
|
+
|
42
|
+
property :operation, String, :required => true
|
43
|
+
property :parameters, Yaml, :default => lambda{|*args| [] }
|
44
|
+
|
45
|
+
def to_a
|
46
|
+
[self.operation, self.parameters].flatten
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'yogo/datamapper/dynamic/stored/configuration'
|
2
|
+
|
3
|
+
|
4
|
+
class ProjectRemix
|
5
|
+
include ::DataMapper::Resource
|
6
|
+
|
7
|
+
property :id, UUID, :key => true, :default => lambda { Yogo::Configuration.random_uuid }
|
8
|
+
property :name, String, :required => true
|
9
|
+
|
10
|
+
without_auto_validations do
|
11
|
+
remix n, 'Yogo::DataMapper::Dynamic::Stored::Configuration', :as => :model_configurations, :model => 'ProjectModelConfiguration'
|
12
|
+
enhance :configuration do
|
13
|
+
property :project_id, UUID
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end # ProjectRemix
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Yogo Data Management Toolkit
|
2
|
+
# Copyright (c) 2010 Montana State University
|
3
|
+
#
|
4
|
+
# License -> see license.txt
|
5
|
+
#
|
6
|
+
# FILE: data_stream.rb
|
7
|
+
# The Data Stream model is where the streaming data parsing templates are stores.
|
8
|
+
#
|
9
|
+
|
10
|
+
# Class for a Yogo Project. A project contains a name, a description, and access to all of the models
|
11
|
+
# that are part of the project.
|
12
|
+
module Yogo
|
13
|
+
module Voeis
|
14
|
+
module Managed
|
15
|
+
class DataStream
|
16
|
+
include ::DataMapper::Resource
|
17
|
+
|
18
|
+
property :id, UUID, :key => true, :default => lambda { UUIDTools::UUID.timestamp_create }
|
19
|
+
|
20
|
+
property :name, String, :required => true, :unique => true
|
21
|
+
property :description, Text, :required => false
|
22
|
+
property :filename, String, :required => true, :length => 512
|
23
|
+
property :start_line, Integer, :required => true, :default => 0
|
24
|
+
|
25
|
+
property :project_id, Integer, :required =>true, :default => 1
|
26
|
+
|
27
|
+
validates_uniqueness_of :name
|
28
|
+
|
29
|
+
#before :destroy, :delete_data_stream_columns!
|
30
|
+
|
31
|
+
has n, :sites, :through => Resource
|
32
|
+
# has n, :data_stream_columns, :model => "DataStreamColumn", :through => Resource
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
end # DataStream
|
37
|
+
end # Managed
|
38
|
+
end # Voeis
|
39
|
+
end # Yogo
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Sites TODO- validate the best practices below
|
2
|
+
#
|
3
|
+
# This is a "Monitoring Site Locations"
|
4
|
+
# The Sites table provides information giving the spatial location at which data values have been
|
5
|
+
# collected.
|
6
|
+
# The following rules and best practices should be followed when populating this table:
|
7
|
+
# * The SiteID field is the primary key, must be a unique integer, and cannot be NULL. This
|
8
|
+
# field should be implemented as an auto number/identity field.
|
9
|
+
# * The SiteCode field must contain a text code that uniquely identifies each site. The values
|
10
|
+
# in this field should be unique and can be an alternate key for the table. SiteCodes cannot
|
11
|
+
# contain any characters other than A-Z (case insensitive), 0-9, period “.”, dash “-“, and
|
12
|
+
# underscore “_”.
|
13
|
+
# * The LatLongDatumID must reference a valid SpatialReferenceID from the
|
14
|
+
# SpatialReferences controlled vocabulary table. If the datum is unknown, a default value
|
15
|
+
# of 0 is used.
|
16
|
+
# * If the Elevation_m field is populated with a numeric value, a value must be specified in
|
17
|
+
# the VerticalDatum field. The VerticalDatum field can only be populated using terms
|
18
|
+
# from the VerticalDatumCV table. If the vertical datum is unknown, a value of
|
19
|
+
# “Unknown” is used.
|
20
|
+
# * If the LocalX and LocalY fields are populated with numeric values, a value must be
|
21
|
+
# specified in the LocalProjectionID field. The LocalProjectionID must reference a valid
|
22
|
+
# SpatialReferenceID from the SpatialReferences controlled vocabulary table. If the spatial
|
23
|
+
# reference system of the local coordinates is unknown, a default value of 0 is used.
|
24
|
+
#
|
25
|
+
module Yogo
|
26
|
+
module Voeis
|
27
|
+
module Managed
|
28
|
+
class Site
|
29
|
+
include ::DataMapper::Resource
|
30
|
+
|
31
|
+
property :id, UUID, :key => true, :default => lambda { UUIDTools::UUID.timestamp_create }
|
32
|
+
property :site_code, String, :required => true
|
33
|
+
property :site_name, String, :required => true
|
34
|
+
property :latitude, Float, :required => true
|
35
|
+
property :longitude, Float, :required => true
|
36
|
+
property :lat_long_datum_id, Integer, :required => true, :default => 0
|
37
|
+
property :elevation_m, Float, :required => false
|
38
|
+
property :vertical_datum, String, :required => false
|
39
|
+
property :local_x, Float, :required => false
|
40
|
+
property :local_y, Float, :required => false
|
41
|
+
property :local_projection_id, Integer, :required => false
|
42
|
+
property :pos_accuracy_m, Float, :required => false
|
43
|
+
property :state, String, :required => false
|
44
|
+
property :country, String, :required => false
|
45
|
+
property :comments, String, :required => false
|
46
|
+
|
47
|
+
has n, :data_streams, :through => Resource
|
48
|
+
end # Site
|
49
|
+
end # Managed
|
50
|
+
end # Voeis
|
51
|
+
end # Yogo
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'dm-types/uuid'
|
3
|
+
|
4
|
+
require 'yogo/datamapper/repository_manager'
|
5
|
+
require 'yogo/example/voeis/managed/site'
|
6
|
+
require 'yogo/example/voeis/managed/data_stream'
|
7
|
+
|
8
|
+
module Yogo
|
9
|
+
module Voeis
|
10
|
+
class Project
|
11
|
+
include ::DataMapper::Resource
|
12
|
+
include Yogo::DataMapper::RepositoryManager
|
13
|
+
|
14
|
+
property :id, UUID, :key => true, :default => lambda { UUIDTools::UUID.timestamp_create }
|
15
|
+
property :name, String, :required => true
|
16
|
+
property :description, String
|
17
|
+
|
18
|
+
def self.manage(klass)
|
19
|
+
@managed_models ||= []
|
20
|
+
unless @managed_models.include?(klass)
|
21
|
+
@managed_models << klass
|
22
|
+
end
|
23
|
+
@managed_models
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.managed_models
|
27
|
+
@managed_models
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def managed_repository_name
|
32
|
+
ActiveSupport::Inflector.tableize(id.to_s).to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
def adapter_config
|
36
|
+
{
|
37
|
+
:adapter => 'sqlite',
|
38
|
+
:database => "voeis-project-#{managed_repository_name}.db"
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def prepare_models
|
43
|
+
adapter # ensure the adapter exists or is setup
|
44
|
+
managed_repository.scope {
|
45
|
+
self.class.managed_models.each do |klass|
|
46
|
+
klass.auto_upgrade!
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
after :save, :prepare_models
|
52
|
+
|
53
|
+
manage Managed::Site
|
54
|
+
manage Managed::DataStream
|
55
|
+
end # Project
|
56
|
+
end # Voeis
|
57
|
+
end # Yogo
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'facets/proc/curry'
|
2
|
+
require 'facets/proc/compose'
|
3
|
+
|
4
|
+
X = :partial_unspecified_argument
|
5
|
+
|
6
|
+
module Yogo
|
7
|
+
class Operation < Proc
|
8
|
+
|
9
|
+
def self.on(type, &block)
|
10
|
+
op = self.new(&block)
|
11
|
+
op.instance_eval{ self.type = type }
|
12
|
+
op
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(*args)
|
16
|
+
x = args.first
|
17
|
+
raise "Can only invoke on #{type}" if type && !x.is_a?(type)
|
18
|
+
super(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
attr_accessor :type
|
25
|
+
end # Operation
|
26
|
+
|
27
|
+
class ::Proc
|
28
|
+
def partial(*args)
|
29
|
+
Proc.new do |*spice|
|
30
|
+
result = args.collect do |a|
|
31
|
+
X == a ? spice.shift : a
|
32
|
+
end
|
33
|
+
call(*result)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Operations
|
39
|
+
def self.[](op_name)
|
40
|
+
op_name.split("::").reduce(self) do |namespace, const|
|
41
|
+
if namespace && namespace.const_defined?(const)
|
42
|
+
namespace.const_get(const)
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end # Yogo
|
data/lib/yogo/project.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'dm-types/uuid'
|
3
|
+
require 'yogo/collection'
|
4
|
+
|
5
|
+
module Yogo
|
6
|
+
class Project
|
7
|
+
include ::DataMapper::Resource
|
8
|
+
|
9
|
+
property :id, UUID, :key => true, :default => lambda { |p,r| UUIDTools::UUID.timestamp_create }
|
10
|
+
property :name, String, :required => true
|
11
|
+
property :description, Text
|
12
|
+
|
13
|
+
has n, :data_collections, :model => 'Yogo::Collection::Data', :child_key => [:project_id]
|
14
|
+
|
15
|
+
chainable do
|
16
|
+
def as_json(options={})
|
17
|
+
{
|
18
|
+
:id => self.id.to_s,
|
19
|
+
:name => self.name,
|
20
|
+
:description => self.description,
|
21
|
+
:data_collections => self.data_collections.map{|c| c.id.to_s }
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_attributes(hash)
|
26
|
+
attrs = {}
|
27
|
+
attrs[:name] = hash[:name] || hash['name'] || self.name
|
28
|
+
attrs[:description] = hash[:description] || hash['description'] || self.description
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end # Project
|
32
|
+
end # Yogo
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
Example of an asset.
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Standard requirements for Bundler management
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
# Load the bundler gemset
|
6
|
+
Bundler.setup(:default, ENV['RACK_ENV'] || :test )
|
7
|
+
|
8
|
+
# Mess with load paths
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
|
10
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
11
|
+
|
12
|
+
require 'rspec/core'
|
13
|
+
require 'autotest/rspec2'
|
14
|
+
require 'rack/test'
|
15
|
+
require 'rack/mock'
|
16
|
+
|
17
|
+
require 'data_mapper'
|
18
|
+
require 'dm-postgres-adapter'
|
19
|
+
require 'dm-sqlite-adapter'
|
20
|
+
|
21
|
+
require 'yogo-project'
|
22
|
+
|
23
|
+
require 'yogo/project'
|
24
|
+
require 'yogo/collection'
|
25
|
+
|
26
|
+
Dir[File.join(File.dirname(__FILE__), "helpers", "**/*.rb")].each do |f|
|
27
|
+
require f
|
28
|
+
end
|
29
|
+
|
30
|
+
Dir[File.join(File.dirname(__FILE__), "factories", "**/*.rb")].each do |f|
|
31
|
+
require f
|
32
|
+
end
|
33
|
+
|
34
|
+
SPEC_DIR = File.expand_path(File.dirname(__FILE__))
|
35
|
+
SPEC_TMP_DIR = File.join(SPEC_DIR, 'tmp')
|
36
|
+
SPEC_RES_DIR = File.join(SPEC_DIR, 'resource')
|
37
|
+
|
38
|
+
DB_URL = "sqlite://#{SPEC_TMP_DIR}/projects.db"
|
39
|
+
COLLECTION_URL = "sqlite://#{SPEC_TMP_DIR}/collections.db"
|
40
|
+
|
41
|
+
Rspec.configure do |config|
|
42
|
+
config.before(:suite) do
|
43
|
+
DataMapper::Model.raise_on_save_failure = true
|
44
|
+
DataMapper::Logger.new('log/datamapper.log', :debug)
|
45
|
+
@default = ::DataMapper.setup(:default, DB_URL)
|
46
|
+
@collection_data = ::DataMapper.setup(:collection_data, COLLECTION_URL)
|
47
|
+
::DataMapper.finalize.auto_migrate!
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
shared_examples_for "All Collection Data Models" do
|
4
|
+
it "should be a datamapper model" do
|
5
|
+
@data_model.should be_a_kind_of(::DataMapper::Model)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should use the collection data_repository" do
|
9
|
+
@collection.scope do
|
10
|
+
@data_model.repository.should == @data_model.collection.collection_repository
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "core properties" do
|
16
|
+
it "should include :id" do
|
17
|
+
@collection.scope do
|
18
|
+
@data_model.properties[:id].should_not be_nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should include :created_at" do
|
23
|
+
@collection.scope do
|
24
|
+
@data_model.properties[:created_at].should_not be_nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should include :updated_at" do
|
29
|
+
@collection.scope do
|
30
|
+
@data_model.properties[:updated_at].should_not be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
shared_examples_for "All Collection Managers" do
|
4
|
+
|
5
|
+
describe "class" do
|
6
|
+
before(:each) do
|
7
|
+
@manager_class = @manager.class
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be a datamapper model" do
|
11
|
+
@manager_class.should be_a_kind_of(::DataMapper::Model)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have a repository for collections"
|
16
|
+
it "should have collections"
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
shared_examples_for "All Collections" do
|
4
|
+
it "should have a name" do
|
5
|
+
@collection.name.should be_a_kind_of(String)
|
6
|
+
@collection.name.should_not be_empty
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should allow name to be changed" do
|
10
|
+
new_name = "Cercal Cell DB"
|
11
|
+
|
12
|
+
@collection.name = new_name
|
13
|
+
@collection.should be_valid
|
14
|
+
@collection.save.should be_true
|
15
|
+
@collection.name.should == new_name
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow description to be changed" do
|
19
|
+
new_description = "Example Database"
|
20
|
+
@collection.description = new_description
|
21
|
+
@collection.should be_valid
|
22
|
+
@collection.save.should be_true
|
23
|
+
@collection.description.should == new_description
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
it "should have a collection_repository" do
|
28
|
+
@collection.should respond_to(:collection_repository)
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "collection_repository" do
|
32
|
+
it "should be a datamapper respository" do
|
33
|
+
@collection.collection_repository.should be_a_kind_of(DataMapper::Repository)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have a data_model" do
|
38
|
+
@collection.should respond_to(:data_model)
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "data_model" do
|
42
|
+
before(:each) do
|
43
|
+
@data_model = @collection.data_model
|
44
|
+
end
|
45
|
+
|
46
|
+
it_should_behave_like "All Collection Data Models"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have items" do
|
50
|
+
@collection.should respond_to(:items)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|