chawk 0.1.15 → 0.1.16

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e45b7bfdb83f83bc57e9fd40b1ca45d1e7f8093
4
- data.tar.gz: 58a5800c07914a2ba330d8fc487a4e9dd0976c48
3
+ metadata.gz: 8e4af3f3f47d72453ac226d2f5645f8288c38843
4
+ data.tar.gz: 4c5cdc1405311d4b03e67540f0fd55c1eb4997af
5
5
  SHA512:
6
- metadata.gz: f8db6cfd8327facfe80afab263fb7826cfbf97b537975aa5715ff750c3bf01845034ec78339c8fb27d0ae165252c139ca2b7cf35924d3abb09191ff39ff265d8
7
- data.tar.gz: 1598c3c209cd5590fb187aaa3ae5bea1a224d2b5754c51cb914d96f0489933b17e71c5c397c3120c308a5337227e5b67b8964e771e6e19465d2d11842e3be25d
6
+ metadata.gz: e276cefee3bc31f2bd0c3e1fd668a67336935abde8f17624f901d672e85fc03f22b61777bc9f4d166d1bcf6fcaeb451fe54702de8b166e0ffc722e78991cb696
7
+ data.tar.gz: c373b9799df4768f20851298ce7a083cfe16174a24b73e29769b48920e034273ff91a5df75509ca6f941c20cd232be6bb079e1eb9652ed214646f6fea490499f
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  *.gem
2
2
  *.rbc
3
+ .env
3
4
  .bundle
4
5
  .config
5
6
  .yardoc
data/.pryrc ADDED
@@ -0,0 +1,10 @@
1
+ $:.unshift('lib')
2
+
3
+ require 'active_record'
4
+ require 'hirb'
5
+ require 'chawk'
6
+
7
+
8
+ Hirb.enable
9
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
10
+ ActiveRecord::Base.establish_connection ENV["TEST_DATABASE_URL"]
@@ -1,7 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.1.0
4
- - 2.0.0
5
- - 1.9.3
6
4
 
7
5
  script: "rake test"
data/CHANGES CHANGED
@@ -0,0 +1,5 @@
1
+
2
+ -- 0.1.15 --
3
+ Added "append" method and redirected << into it (Apparently, << is magic and won't take 2 parameters)
4
+ -- 0.1.16 --
5
+ Switched to ActiveRecord, removed DataMapper
@@ -18,15 +18,14 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- #spec.add_runtime_dependency "dm-postgres-adapter","1.2.0"
22
- spec.add_runtime_dependency "data_mapper", "1.2.0"
21
+ spec.add_runtime_dependency('activerecord',"4.0.4")
23
22
 
24
23
  spec.add_development_dependency "bundler", "~> 1.5"
25
24
  spec.add_development_dependency "rake"
26
- spec.add_development_dependency('minitest', '5.3.0')
25
+ spec.add_development_dependency('minitest', '5.3.1')
27
26
  spec.add_development_dependency('rack-test', "0.6.2")
28
27
  spec.add_development_dependency('json', "1.8.1")
29
- spec.add_development_dependency('simplecov')
30
- spec.add_development_dependency "dm-sqlite-adapter", "1.2.0"
31
-
28
+ spec.add_development_dependency('simplecov', "0.8.2")
29
+ spec.add_development_dependency('pg', "0.17.1")
30
+ spec.add_development_dependency('sqlite3', "1.3.9")
32
31
  end
@@ -1,35 +1,65 @@
1
1
  require "chawk/version"
2
- require 'data_mapper'
3
2
  require 'quantizer'
4
3
  require 'models'
5
- require 'addr'
6
4
 
7
5
  # Chawk is a gem for storing and retrieving time seris data.
8
6
  module Chawk
7
+ def self.check_node_security(agent,node)
9
8
 
10
- # Has Chawk been setup yet?
11
- @@ready = nil
9
+ if node.public_read
10
+ return node
11
+ end
12
+
13
+ rel = node.relations.where(agent_id:agent.id).first
14
+
15
+ if (rel && (rel.read || rel.admin))
16
+ return node
17
+ else
18
+ raise SecurityError,"You do not have permission to access this node. #{agent} #{rel}"
19
+ end
20
+ end
21
+
22
+ def self.find_or_create_node(agent,key)
23
+ #TODO also accept regex-tested string
24
+ raise(ArgumentError,"Key must be a string.") unless key.is_a?(String)
25
+
26
+ node = Chawk::Models::Node.where(key:key).first
27
+ if node
28
+ node = check_node_security(agent,node)
29
+ else
30
+ node = Chawk::Models::Node.create(key:key) if node.nil?
31
+ node.relations.create(agent:agent,node:node,admin:true,read:true,write:true)
32
+ return node
33
+ end
34
+ end
12
35
 
13
36
  # @param agent [Chawk::Agent] the agent whose permission will be used for this request
14
- # @param path [String] the string address this addr can be found in the database.
37
+ # @param key [String] the string address this addr can be found in the database.
15
38
  # @return [Chawk::Addr]
16
- # The primary method for retrieving an Addr. If a path does not exist, it will be created
39
+ # The primary method for retrieving an Addr. If a key does not exist, it will be created
17
40
  # and the current agent will be set as an admin for it.
18
- def self.addr(agent,path)
19
- if @@ready.nil?
20
- raise "Chawk has not been setup yet."
41
+ def self.addr(agent,key)
42
+
43
+ unless key =~ /^[\w\:\$\!\@\*\[\]\~\(\)]+$/
44
+ raise ArgumentError, "Key can only contain [A-Za-z0-9_:$!@*[]~()] (#{key})"
21
45
  end
22
46
 
23
47
  unless agent.is_a?(Chawk::Models::Agent)
24
48
  raise ArgumentError, 'Agent must be a Chawk::Models::Agent instance'
25
49
  end
26
50
 
27
- unless path.is_a?(String)
28
- raise ArgumentError, 'Path must be a string.'
51
+ unless key.is_a?(String)
52
+ raise ArgumentError, 'key must be a string.'
29
53
  end
30
54
 
31
- return Chawk::Addr.new(agent,path)
55
+ node = find_or_create_node(agent,key)
56
+
57
+ unless node
58
+ raise ArgumentError,"No node was returned."
59
+ end
32
60
 
61
+ node.agent = agent
62
+ return node
33
63
  end
34
64
 
35
65
  # @param agent [Chawk::Agent] the agent whose permission will be used for this request
@@ -40,34 +70,17 @@ module Chawk
40
70
  data.keys.each do |key|
41
71
  dset = data[key]
42
72
  daddr = addr(agent,key)
43
- daddr.points << dset
73
+ daddr.add_points dset
44
74
  end
45
75
  end
46
76
 
47
77
 
48
78
  # Deletes all data in the database. Very dangerous. Backup often!
49
79
  def self.clear_all_data!
50
- if @@ready.nil?
51
- raise "Chawk has not been setup yet."
52
- end
53
-
54
- Chawk::Models::Agent.all.destroy!
55
- Chawk::Models::Relation.all.destroy!
56
- Chawk::Models::AgentTag.all.destroy!
57
- Chawk::Models::Tag.all.destroy!
58
- Chawk::Models::Node.all.destroy!
59
- Chawk::Models::Point.all.destroy!
60
- Chawk::Models::Value.all.destroy!
61
- end
62
-
63
-
64
- # @param database_url [String]
65
- # Startup routine for Chawk, requires a database URL in DataMapper's standard format.
66
- def self.setup(database_url)
67
- @@ready = true
68
- adapter = DataMapper.setup(:default, database_url)
69
- DataMapper::Model.raise_on_save_failure = true
70
- DataMapper.finalize
71
- nil
80
+ Chawk::Models::Agent.destroy_all
81
+ Chawk::Models::Relation.destroy_all
82
+ Chawk::Models::Node.destroy_all
83
+ Chawk::Models::Point.destroy_all
84
+ Chawk::Models::Value.destroy_all
72
85
  end
73
86
  end
@@ -0,0 +1,92 @@
1
+ ## ~~~- Created via -~~~
2
+
3
+ # ActiveRecord::Base.establish_connection ENV["TEST_DATABASE_URL"]
4
+ # File.open(schema_file, "w") do |file|
5
+ # ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
6
+ # end
7
+
8
+ # create_table "chawk_g_users", force: true do |t|
9
+ # t.string "google_id", limit: 120
10
+ # t.string "google_email", limit: 120
11
+ # t.string "email", limit: 120
12
+ # t.string "handle", limit: 30
13
+ # t.string "name", limit: 40
14
+ # t.string "family_name", limit: 20
15
+ # t.text "image"
16
+ # t.text "secret"
17
+ # t.string "api_key", limit: 200
18
+ # t.integer "reset_token"
19
+ # t.integer "access_token"
20
+ # t.integer "agent_id"
21
+ # end
22
+ # add_index "chawk_g_users", ["agent_id"], name: "index_chawk_g_users_agent", using: :btree
23
+
24
+ #require 'active_record'
25
+ #ActiveRecord::Base.logger = Logger.new(STDOUT)
26
+ #ActiveRecord::Base.establish_connection ENV["TEST_DATABASE_URL"]
27
+
28
+ ActiveRecord::Migration.verbose = false
29
+ class CreateChawkBase < ActiveRecord::Migration
30
+ def up
31
+ create_table "chawk_agents", force: true do |t|
32
+ t.integer "foreign_id"
33
+ t.string "name", limit: 200
34
+ t.timestamps
35
+ end
36
+
37
+ create_table "chawk_nodes", force: true do |t|
38
+ t.string "key", limit: 150
39
+ t.text "decription"
40
+ t.boolean "public_read", default: false
41
+ t.boolean "public_write", default: false
42
+ end
43
+
44
+ create_table "chawk_points", force: true do |t|
45
+ t.float "observed_at"
46
+ t.datetime "recorded_at"
47
+ t.text "meta"
48
+ t.integer "value"
49
+ t.integer "node_id", null: false
50
+ end
51
+
52
+ add_index "chawk_points", ["node_id"], name: "index_chawk_points_node", using: :btree
53
+
54
+ create_table "chawk_values", force: true do |t|
55
+ t.float "observed_at"
56
+ t.datetime "recorded_at"
57
+ t.text "meta"
58
+ t.text "value"
59
+ t.integer "node_id", null: false
60
+ end
61
+
62
+ add_index "chawk_values", ["node_id"], name: "index_chawk_values_node", using: :btree
63
+
64
+ create_table "chawk_relations", force: true do |t|
65
+ t.boolean "admin", default: false
66
+ t.boolean "read", default: false
67
+ t.boolean "write", default: false
68
+ t.integer "agent_id", null: false
69
+ t.integer "node_id", null: false
70
+ end
71
+
72
+ add_index "chawk_relations", ["agent_id"], name: "index_chawk_relations_agent", using: :btree
73
+ add_index "chawk_relations", ["node_id"], name: "index_chawk_relations_node", using: :btree
74
+ end
75
+
76
+ def down
77
+ drop_table "chawk_agents"
78
+ drop_table "chawk_nodes"
79
+ drop_table "chawk_points"
80
+ drop_table "chawk_values"
81
+ drop_table "chawk_relations"
82
+ end
83
+
84
+ end
85
+
86
+ #CreateChawkBase.migrate :down
87
+ CreateChawkBase.migrate :up
88
+
89
+ File.open('./test/schema.rb', "w") do |file|
90
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
91
+ end
92
+
@@ -1,4 +1,4 @@
1
1
  module Chawk
2
2
  # The current version of Chawk
3
- VERSION = "0.1.15"
3
+ VERSION = "0.1.16"
4
4
  end
@@ -1,102 +1,167 @@
1
- require 'data_mapper'
2
- require 'dm-aggregates'
1
+ require 'active_record'
3
2
  module Chawk
4
- # Models used in Chawk. Most are DataMapper classes.
3
+ # Models used in Chawk. ActiveRecord classes.
5
4
  module Models
6
5
 
7
- # Base stored item, imported into other DataMapper classes.
8
- module Datum
9
-
10
- protected
11
-
12
- def self.included(base)
13
- base.class_eval do
14
- include DataMapper::Resource
15
- before :create, :set_timestamp
16
-
17
- property :id, DataMapper::Property::Serial
18
- property :observed_at, DataMapper::Property::Float
19
- property :recorded_at, DataMapper::Property::DateTime
20
- property :meta, DataMapper::Property::Text
21
-
22
- belongs_to :node
23
- belongs_to :agent
24
-
25
- def set_timestamp
26
- attribute_set(:recorded_at, DateTime.now )
27
- end
28
-
29
- end
30
- end
31
-
32
- end
33
-
34
- # Agent DataMapper classes.
35
6
  # Contains a foreign_id for use as a proxy to another table.
36
- class Agent
37
- include DataMapper::Resource
38
- property :id, Serial
39
- property :foreign_id, Integer
40
- property :name, String, length:200
41
- has n, :tags
42
- has n, :agent_tags
43
- has n, :relations
7
+ class Agent < ActiveRecord::Base
8
+ self.table_name_prefix = "chawk_"
9
+ has_many :tags
10
+ has_many :agent_tags
11
+ has_many :relations
44
12
  end
45
13
 
46
- # Agent Relation DataMapper classes, with permission flags.
47
- class Relation
48
- include DataMapper::Resource
49
- property :id, Serial
50
- property :admin, Boolean, default:false
51
- property :read, Boolean, default:false
52
- property :write, Boolean, default:false
14
+ # Agent Relation classes, with permission flags.
15
+ class Relation < ActiveRecord::Base
16
+ self.table_name_prefix = "chawk_"
53
17
  belongs_to :agent
54
18
  belongs_to :node
55
19
  end
56
20
 
57
- # Agent Tags.
58
- # Not implimented yet.
59
- class AgentTag
60
- include DataMapper::Resource
61
- property :id, Serial
62
- property :name, String, length:100
63
- property :description, Text
64
- property :managed, Boolean, default:false
21
+ # The Node, where most Chawk:Addr information is persisted..
22
+ class Node < ActiveRecord::Base
23
+ attr_accessor :agent
24
+ after_initialize :init
25
+ self.table_name_prefix = "chawk_"
65
26
  belongs_to :agent
66
- end
27
+ has_many :points
28
+ has_many :values
29
+ has_many :relations
30
+
31
+ def init
32
+ @agent = nil
33
+ end
34
+
35
+ def _insert_point(val,ts,options={})
36
+ values = {value:val,observed_at:ts.to_f}
37
+ values[:meta] = options[:meta] if options[:meta]
38
+ self.points.create(values)
39
+ end
40
+
41
+ def _insert_point_hash(item,ts,options)
42
+ if item['v'] && item['v'].is_a?(Integer)
43
+ if item['t']
44
+ _insert_point item['v'],item['t'], options
45
+ else
46
+ _insert_point item['v'],ts, options
47
+ end
48
+ else
49
+ raise ArgumentError, "Hash must have 'v' key set to proper type.. #{item.inspect}"
50
+ end
51
+ end
67
52
 
68
- # Item Tags.
69
- # Not implimented yet.
70
- class Tag
71
- include DataMapper::Resource
72
- property :description, Text
73
- property :id, Serial
74
- property :name, String, length:100
75
- end
53
+ def _insert_point_array(item,options)
54
+ if item.length == 2 && item[0].is_a?(Integer)
55
+ _insert_point item[0],item[1], options
56
+ else
57
+ raise ArgumentError, "Array Items must be in [value,timestamp] format. #{item.inspect}"
58
+ end
59
+ end
60
+
61
+ def point_recognizer(item, dt, options={})
62
+ case
63
+ when item.is_a?(Integer)
64
+ _insert_point item,dt, options
65
+ when item.is_a?(Array)
66
+ _insert_point_array(item, options)
67
+ when item.is_a?(Hash)
68
+ _insert_point_hash(item,dt,options)
69
+ else
70
+ raise ArgumentError, "Can't recognize format of data item. #{item.inspect}"
71
+ end
72
+ end
73
+
74
+ # @param args [Object, Array of Objects]
75
+ # @param options [Hash] You can also pass in :meta and :timestamp
76
+ # Add an item or an array of items (one at a time) to the datastore.
77
+ def add_points(args,options={})
78
+ options[:observed_at] ? dt = options[:observed_at] : dt = Time.now
79
+ if args.is_a?(Array)
80
+ args.each do |arg|
81
+ point_recognizer(arg, dt, options)
82
+ end
83
+ else
84
+ point_recognizer(args, dt, options)
85
+ end
86
+ end
87
+
88
+ def increment(value=1, options={})
89
+ if value.is_a?(Integer)
90
+ last = self.points.last
91
+ add_points last.value + value,options
92
+ else
93
+ raise ArgumentError, "Value must be an Integer"
94
+ end
95
+ end
96
+
97
+ def decrement(value=1, options={})
98
+ if value.is_a?(Integer)
99
+ increment (-1) * value, options
100
+ else
101
+ raise ArgumentError, "Value must be an Integer"
102
+ end
103
+ end
104
+
105
+ def max()
106
+ points.maximum('value') || 0
107
+ end
108
+
109
+ def min()
110
+ points.minimum('value') || 0
111
+ end
112
+
113
+ # Returns items whose observed_at times fit within from a range.
114
+ # @param dt_from [Time::Time] The start time.
115
+ # @param dt_to [Time::Time] The end time.
116
+ # @return [Array of Objects]
117
+ def points_range(dt_from, dt_to,options={})
118
+ vals = points.where("observed_at >= :dt_from AND observed_at <= :dt_to",{dt_from:dt_from.to_f,dt_to:dt_to.to_f}, limit:1000,order:"observed_at asc, id asc")
119
+ return vals
120
+ end
121
+
122
+ # Returns items whose observed_at times fit within from a range ending now.
123
+ # @param dt_from [Time::Time] The start time.
124
+ # @return [Array of Objects]
125
+ def points_since(dt_from)
126
+ self.points_range(dt_from,Time.now)
127
+ end
128
+
129
+ # Sets public read flag for this address
130
+ # @param value [Boolean] true if public reading is allowed, false if it is not.
131
+ def set_public_read(value)
132
+ value = value ? true : false
133
+ self.public_read = value
134
+ save
135
+ end
136
+
137
+ # Sets permissions flag for this address, for a specific agent. The existing Chawk::Relationship will be destroyed and
138
+ # a new one created as specified. Write access is not yet checked.
139
+ # @param agent [Chawk::Agent] the agent to give permission.
140
+ # @param read [Boolean] true/false can the agent read this address.
141
+ # @param write [Boolean] true/false can the agent write this address. (Read acces is required to write.)
142
+ # @param admin [Boolean] does the agent have ownership/adnim rights for this address. (Read and write are granted if admin is as well.)
143
+ def set_permissions(agent,read=false,write=false,admin=false)
144
+ relations.where(agent_id:agent.id).destroy_all
145
+ if read || write || admin
146
+ vals = {agent:agent,read:(read ? true : false),write:(write ? true : false),admin:(admin ? true : false)}
147
+ relations.create(vals)
148
+ end
149
+ nil
150
+ end
76
151
 
77
- # The Node, where most Chawk:Addr information is persisted..
78
- class Node
79
- include DataMapper::Resource
80
- property :id, Serial
81
- property :address, String, length:150
82
- property :public_read, Boolean, default:false
83
- property :public_write, Boolean, default:false
84
-
85
- has n, :points
86
- has n, :values
87
- has n, :relations
88
152
  end
89
153
 
90
154
  # The Node, where most Chawk point information is persisted..
91
- class Point
92
- include Chawk::Models::Datum
93
- property :value, Integer
155
+ class Point < ActiveRecord::Base
156
+ self.table_name_prefix = "chawk_"
157
+ belongs_to :node
94
158
  end
95
159
 
96
160
  # The Node, where most Chawk value information is persisted..
97
- class Value
98
- include Chawk::Models::Datum
99
- property :value, Text
161
+ class Value < ActiveRecord::Base
162
+ self.table_name_prefix = "chawk_"
163
+ belongs_to :node
100
164
  end
165
+
101
166
  end
102
167
  end