wherever-positions 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create 1.8.7-p72@wherever
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'bson_ext'
4
+ gem 'mongoid'
5
+
6
+ group :development do
7
+ gem "rspec", "~> 2.3.0"
8
+ gem "cucumber", ">= 0"
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.6.4"
11
+ gem "rcov", ">= 0"
12
+ gem 'ruby-debug'
13
+ gem 'database_cleaner'
14
+
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,71 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.1.1)
5
+ activesupport (= 3.1.1)
6
+ builder (~> 3.0.0)
7
+ i18n (~> 0.6)
8
+ activesupport (3.1.1)
9
+ multi_json (~> 1.0)
10
+ bson (1.4.1)
11
+ bson_ext (1.4.1)
12
+ builder (3.0.0)
13
+ columnize (0.3.4)
14
+ cucumber (1.1.0)
15
+ builder (>= 2.1.2)
16
+ diff-lcs (>= 1.1.2)
17
+ gherkin (~> 2.5.0)
18
+ json (>= 1.4.6)
19
+ term-ansicolor (>= 1.0.6)
20
+ database_cleaner (0.6.7)
21
+ diff-lcs (1.1.3)
22
+ gherkin (2.5.4)
23
+ json (>= 1.4.6)
24
+ git (1.2.5)
25
+ i18n (0.6.0)
26
+ jeweler (1.6.4)
27
+ bundler (~> 1.0)
28
+ git (>= 1.2.5)
29
+ rake
30
+ json (1.6.1)
31
+ linecache (0.46)
32
+ rbx-require-relative (> 0.0.4)
33
+ mongo (1.4.1)
34
+ bson (= 1.4.1)
35
+ mongoid (2.3.2)
36
+ activemodel (~> 3.1)
37
+ mongo (~> 1.4)
38
+ tzinfo (~> 0.3.22)
39
+ multi_json (1.0.3)
40
+ rake (0.9.2.2)
41
+ rbx-require-relative (0.0.5)
42
+ rcov (0.9.11)
43
+ rspec (2.3.0)
44
+ rspec-core (~> 2.3.0)
45
+ rspec-expectations (~> 2.3.0)
46
+ rspec-mocks (~> 2.3.0)
47
+ rspec-core (2.3.1)
48
+ rspec-expectations (2.3.0)
49
+ diff-lcs (~> 1.1.2)
50
+ rspec-mocks (2.3.0)
51
+ ruby-debug (0.10.4)
52
+ columnize (>= 0.1)
53
+ ruby-debug-base (~> 0.10.4.0)
54
+ ruby-debug-base (0.10.4)
55
+ linecache (>= 0.3)
56
+ term-ansicolor (1.0.7)
57
+ tzinfo (0.3.30)
58
+
59
+ PLATFORMS
60
+ ruby
61
+
62
+ DEPENDENCIES
63
+ bson_ext
64
+ bundler (~> 1.0.0)
65
+ cucumber
66
+ database_cleaner
67
+ jeweler (~> 1.6.4)
68
+ mongoid
69
+ rcov
70
+ rspec (~> 2.3.0)
71
+ ruby-debug
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 David Henry
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,143 @@
1
+ = WHEREVER
2
+
3
+ Storage and retrieve of data for identifying keys, with advanced summary options.
4
+
5
+ == Install
6
+
7
+ gem install wherever
8
+
9
+ == Setup
10
+
11
+ Create a reference to the Gem:
12
+
13
+ Wherever.new("keys" => keys,
14
+ "database" => database,
15
+ "key_groups" => key_groups,
16
+ "key" => key)
17
+
18
+ keys => Key fields to be stored with individual records, fields my be listed here be used in key_groups below
19
+ database => Name of the Mongo DB to store the data in
20
+ key_groups => Field combinations to be used for grouping
21
+ key => Key for unique records in the dataset
22
+
23
+ example:
24
+
25
+ Store data with fields "group_one_id", "group_two_id" and "unique_id".
26
+ Data should be grouped and stored for quick retrieval by "group_one_id" or "group_one_id" and "group_two_id".
27
+
28
+ @wherever = Wherever.new("keys" => ["group_one_id", "group_two_id"],
29
+ "database" => "wherever_dev",
30
+ "key_groups" => ["group_one_id", ["group_one_id", "group_two_id"]],
31
+ "key" => "unique_id")
32
+
33
+ NOTE: In the previous example data could still be retrieved for grouping "group_two_id" but this would need to be calculated on the fly and would be significantly slower.
34
+
35
+ The setup takes an optional block which can the be used to summarise the group data which takes the following parameters:
36
+ values => Hash to store the data in. (This should support summing of the data across multiple inserts)
37
+ data => Hash containing the data to be stored
38
+ record => MongoDB record for the unique record => useful to retrieve lookup data (see below)
39
+ keys => "key_group" that is currently being summarised.
40
+
41
+ The below is the default grouping that is applied
42
+
43
+ @wherever = Wherever.new(*options) do |values, data, record, keys|
44
+ data.keys.each do |key|
45
+ values[key] += data[key]
46
+ end
47
+ end
48
+
49
+
50
+ == Data Insertion
51
+
52
+ @wherever.add(values, options)
53
+
54
+ values => Raw data values to be stored. This should be a hash containing "version" and "key" (as defined on setup) values.
55
+ options => Relevant options relating to the data being inserted. This should be a hash containing "unique" and "keys" values.
56
+ unique => This should be a hash containing "version" and "key" (as defined on setup) fields.
57
+ keys => This should be a hash with a value for each key defined in "keys" on setup.
58
+
59
+ == Data Retrieval
60
+
61
+ @wherever.get(options)
62
+
63
+ options => Hash containing "keys" (for setup above) with desired lookup value.
64
+ Data is returned as a hash the values which are stored on the record or generated via the summary block.
65
+
66
+ == Data Lookup
67
+
68
+ Store lookup data for the use in data summarisation block.
69
+
70
+ In order to use a lookup store you first need to create it using:
71
+
72
+ @wherever.create_lookup(name, keys)
73
+
74
+ name => Name of the lookup to be created. This is used to create set_<name> and get_<name> methods for the lookup.
75
+ keys => Keys that are required to on the stored keys to correctly determine the correct lookup value
76
+
77
+ The setter method can then be used to store data:
78
+
79
+ wherever.set_<name>(lookup_version, data)
80
+
81
+ lookup_version => This is used to allow storage of multiple sets of lookup values.
82
+ * Recommend using the storage time as this must be a unique value.
83
+ data => Hash of the data to be stored. The key should match to the "keys" fields declared above joined by "_" character.
84
+
85
+ The data can the be retrieved using the the getter method:
86
+
87
+ wherever.get_<name>(lookup_version, record)
88
+
89
+ lookup_version => This is used to allow storage of multiple sets of lookup values.
90
+ * Recommend using the storage time as this must be a unique value.
91
+ record => This is a record that contains the required fields ("keys" in create above) to perform the lookup
92
+
93
+ Lookups can then be used to create more sophisticated data summarisation process.
94
+
95
+ example: The below is a complex summary method which is the main reason for building the whole gem (field names have been changed to protect the innocent).
96
+
97
+ Wherever.new(*options) do |values, data, record, keys|
98
+ value_two = wherever.get_lookup(record.lookup_key, record)
99
+ if keys.include?("group_one_id")
100
+ values["value_one"] += data["value_one"] if data
101
+ values["value_two"] = value_two
102
+ end
103
+ if data
104
+ values["value_three"] += data["value_one"] * value_two
105
+ else
106
+ values["value_three"] = values["value_one"] * value_two
107
+ end
108
+ end
109
+
110
+ == Remaining Work
111
+
112
+ * Allow marked points in time to be modified by changing the data version they represent.
113
+ * Allow pricing data on marked data points to be modified.
114
+
115
+ == Data Storage Levels
116
+
117
+ === Unique Records
118
+
119
+ Data is passed in for each identifier and version. This is then used to store each record as a diff to it's previous level. Meaning the data at any point in time can be generated by summing all previous versions. This data is only stored once within the system with each marked version just storing the version for each trade that was used to generated the summed date.
120
+
121
+ === Identifier Records
122
+
123
+ This stores the current value of each identifier and is used when data is required to be regenerated at a summed level as a result of a change in lookup values.
124
+
125
+ === Grouped Records
126
+
127
+ These are stored to allow quick and easy access to the data.
128
+
129
+ == Contributing to wherever
130
+
131
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
132
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
133
+ * Fork the project
134
+ * Start a feature/bugfix branch
135
+ * Commit and push until you are happy with your contribution
136
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
137
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
138
+
139
+ == Copyright
140
+
141
+ Copyright (c) 2011 David Henry. See LICENSE.txt for
142
+ further details.
143
+
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "wherever-positions"
18
+ gem.homepage = "http://github.com/dw_henry/wherever"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Store and Retrieve positions by location}
21
+ gem.description = %Q{Allow Store of positions by multiple keys with teh option to mark specific points in time for use later}
22
+ gem.email = "dw_henry@yahoo.com.au"
23
+ gem.authors = ["David Henry"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ require 'cucumber/rake/task'
40
+ Cucumber::Rake::Task.new(:features)
41
+
42
+ task :default => :spec
43
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,14 @@
1
+ Given /^a configured wherever system with keys "([^"]*)"$/ do |keys|
2
+ @interface = Wherever.new(:keys => keys.split(','))
3
+ end
4
+
5
+ When /^I add data to the system for:$/ do |string|
6
+ hash = JSON.parse(string)
7
+ p hash
8
+ @interface.add(hash)
9
+ end
10
+
11
+ Then /^I have have the following data:$/ do |table|
12
+ # table is a Cucumber::Ast::Table
13
+ pending # express the regexp above with the code you wish you had
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
11
+ require 'wherever'
12
+ require 'ruby-debug'
13
+ require 'rspec/expectations'
@@ -0,0 +1,18 @@
1
+ Feature: I can add and retrieve data fro the system
2
+
3
+ Scenario: I add data to the system
4
+ Given a configured wherever system with keys "fund_id"
5
+ When I add data to the system for:
6
+ """
7
+ {
8
+ "keys": {"fund_id": 1},
9
+ "unique": {"id": 1, "version": 1},
10
+ "position": 100,
11
+ "settled": true
12
+ }
13
+ """
14
+ Then I have have the following data:
15
+ | table | keys | settled positon | unsettled position |
16
+ | keys | {"fund_id": 1} | 100 | 0 |
17
+ | unique | {"fund_id": 1, "trade_id": 1} | 100 | 0 |
18
+ | all | {"fund_id": 1, "trade_id": 1, "version": 1} | 100 | 0 |
@@ -0,0 +1,20 @@
1
+ class Configure
2
+ attr_accessor :keys, :key_groups, :_id
3
+ def initialize(options)
4
+ host = options["host"] || 'localhost'
5
+ database = options["database"] || 'wherever'
6
+ user = options["user"]
7
+ password = options["password"]
8
+ @_id = options["key"] ||= "unqiue_id"
9
+
10
+ Mongoid.config do |config|
11
+ mongo_connection = Mongo::Connection.new(host).db(database)
12
+ mongo_connection.authenticate(user, password) if user
13
+ config.master = mongo_connection
14
+ end
15
+
16
+ @keys = options["keys"]
17
+ groups = options["key_groups"] || @keys.map{|k| k.gsub(/_id$/,'')}
18
+ @key_groups = groups.map{|g| Array(g)}
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module DbStore
2
+ class Dataset
3
+ include Mongoid::Document
4
+ include DbStore::RecordMatcher
5
+ embedded_in :store, :class_name => 'DbStore::Store'
6
+ field :values, :type => Hash, :default => Hash.new(0)
7
+
8
+ def price
9
+ self.store.marker.price
10
+ end
11
+
12
+ def diff(record)
13
+ res = {}
14
+ record.keys.each do |key|
15
+ res[key] = record[key] - self.values[key]
16
+ end
17
+ res
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ module DbStore
2
+ class Identifier
3
+ include Mongoid::Document
4
+ embedded_in :store, :class_name => 'DbStore::Store'
5
+ include DbStore::RecordMatcher
6
+
7
+ field :_id, :type => Integer
8
+ field :version, :type => Integer
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ module DbStore
2
+ class Lookup
3
+ include Mongoid::Document
4
+ embeds_many :versions, :class_name => 'DbStore::Version'
5
+ field :name, :type => String
6
+ field :keys, :type => Hash
7
+ end
8
+
9
+ class Version
10
+ include Mongoid::Document
11
+ embedded_in :lookup, :class_name => 'DbStore::Lookup'
12
+ field :name, :type => String
13
+ field :values, :type => Hash, :default => Hash.new(0)
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ module DbStore
2
+ class Marker
3
+ include Mongoid::Document
4
+ embeds_many :stores, :class_name => 'DbStore::Store'
5
+ field :name, :type => String
6
+ field :price, :type => String
7
+
8
+ def self.find_by_name(name)
9
+ find_or_create_by({:name => name})
10
+ end
11
+ end
12
+ end