dcadenas-change_watcher 0.1.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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Daniel Cadenas
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,42 @@
1
+ = change_watcher
2
+
3
+ A gem to keep track of data changes
4
+
5
+ require "rubygems"
6
+ require "change_watcher"
7
+
8
+ change_watcher = ChangeWatcher.new do
9
+ data_to_watch do
10
+ #scrape some interesting data from the web (account balance, ranking of something, prices, etc.), from the filesystem, or get it from any other data source
11
+ BankAccount.new(username, password).balance
12
+ end
13
+
14
+ on_change do |old, new|
15
+ #notify yourself with an email, growl, etc. about the change, or do any other interesting stuff
16
+ require 'gmail_sender'
17
+
18
+ g = GmailSender.new("gmail_account_user_name", "gmail_account_password")
19
+ g.send("someone@domain.com", "More money yay!!", "It was $#{old} and now it is $#{new}!!!!!") if new > old
20
+ g.send("someone@domain.com", "Less money, ouch", "It was $#{old} but now it is $#{new} :(" if new < old
21
+ end
22
+
23
+ #this gets the path for the yml file where all the changes will be stored or some object implementing a store interface (e.g. a database)
24
+ store_changes_in "/Users/daniel/.foobar_changes.yml"
25
+ end
26
+
27
+ #loop or create a script to call from cron
28
+ change_watcher.check_for_change
29
+
30
+ There's also an optional define_change method you can use if you consider that old != new does not cover the concept of change. See the tests for more details.
31
+
32
+ == Installation
33
+
34
+ sudo gem install dcadenas-change_watcher
35
+
36
+ == Collaborate
37
+
38
+ http://github.com/dcadenas/change_watcher
39
+
40
+ == Copyright
41
+
42
+ Copyright (c) 2009 Daniel Cadenas. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "change_watcher"
8
+ gem.summary = %Q{TODO}
9
+ gem.email = "dcadenas@gmail.com"
10
+ gem.homepage = "http://github.com/dcadenas/change_watcher"
11
+ gem.authors = ["Daniel Cadenas"]
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/*_test.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+
40
+ task :default => :test
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ if File.exist?('VERSION.yml')
45
+ config = YAML.load(File.read('VERSION.yml'))
46
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
47
+ else
48
+ version = ""
49
+ end
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "change_watcher #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
56
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,49 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{change_watcher}
5
+ s.version = "0.1.0"
6
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
7
+ s.authors = ["Daniel Cadenas"]
8
+ s.date = %q{2009-06-17}
9
+ s.email = %q{dcadenas@gmail.com}
10
+ s.extra_rdoc_files = [
11
+ "LICENSE",
12
+ "README.rdoc"
13
+ ]
14
+ s.files = [
15
+ ".document",
16
+ ".gitignore",
17
+ "LICENSE",
18
+ "README.rdoc",
19
+ "Rakefile",
20
+ "VERSION",
21
+ "change_watcher.gemspec",
22
+ "lib/change_watcher.rb",
23
+ "lib/change_watcher/file_store.rb",
24
+ "lib/change_watcher/store.rb",
25
+ "test/change_watcher/file_store_test.rb",
26
+ "test/change_watcher_test.rb",
27
+ "test/test_helper.rb"
28
+ ]
29
+ s.homepage = %q{http://github.com/dcadenas/change_watcher}
30
+ s.rdoc_options = ["--charset=UTF-8"]
31
+ s.require_paths = ["lib"]
32
+ s.rubygems_version = %q{1.3.3}
33
+ s.summary = %q{TODO}
34
+ s.test_files = [
35
+ "test/change_watcher/file_store_test.rb",
36
+ "test/change_watcher_test.rb",
37
+ "test/test_helper.rb"
38
+ ]
39
+
40
+ if s.respond_to? :specification_version then
41
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
45
+ else
46
+ end
47
+ else
48
+ end
49
+ end
@@ -0,0 +1,29 @@
1
+ class ChangeWatcher
2
+ class FileStore
3
+ def initialize(path_to_yaml_file)
4
+ @path_to_yaml_file = path_to_yaml_file
5
+ end
6
+
7
+ def empty?(yaml_stream = get_yaml_stream)
8
+ yaml_stream.nil? || yaml_stream.documents.empty?
9
+ end
10
+
11
+ def latest_value
12
+ yaml_stream = get_yaml_stream
13
+ return nil if empty?(yaml_stream)
14
+ yaml_stream.documents.last.last
15
+ end
16
+
17
+ def save(value)
18
+ File.open( @path_to_yaml_file, 'w' ) do |out|
19
+ YAML.dump( [Time.now, value], out )
20
+ end
21
+ end
22
+
23
+ private
24
+ def get_yaml_stream
25
+ return nil unless File.exists?(@path_to_yaml_file)
26
+ YAML::load_stream(File.open(@path_to_yaml_file))
27
+ end
28
+ end
29
+ end
@@ -0,0 +1 @@
1
+ class S
@@ -0,0 +1,55 @@
1
+ require 'change_watcher/file_store'
2
+
3
+ class ChangeWatcher
4
+ def initialize(&construction_block_dsl)
5
+ construction_block_interpreter = ConstructionBlockInterpreter.new(&construction_block_dsl)
6
+
7
+ @data_to_watch_block = construction_block_interpreter.data_to_watch_block
8
+ @on_change_block = construction_block_interpreter.on_change_block
9
+ @store = construction_block_interpreter.store
10
+ @change_test_block = construction_block_interpreter.change_test_block || lambda{|old, new| old != new}
11
+ end
12
+
13
+ def check_for_change
14
+ current_value = @data_to_watch_block.call
15
+
16
+ if value_changed?(current_value)
17
+ @on_change_block.call(@store.latest_value, current_value) if @on_change_block
18
+ @store.save(current_value)
19
+ end
20
+ end
21
+
22
+ private
23
+ def value_changed?(current_value)
24
+ @store.empty? || @change_test_block.call(@store.latest_value, current_value)
25
+ end
26
+
27
+ class ConstructionBlockInterpreter
28
+ attr_reader :data_to_watch_block, :on_change_block, :store, :change_test_block
29
+
30
+ def initialize(&construction_block_dsl)
31
+ instance_eval(&construction_block_dsl)
32
+ raise ArgumentError unless @data_to_watch_block && @store
33
+ end
34
+
35
+ def data_to_watch(&data_to_watch_block)
36
+ @data_to_watch_block = data_to_watch_block
37
+ end
38
+
39
+ def on_change(&on_change_block)
40
+ @on_change_block = on_change_block
41
+ end
42
+
43
+ def store_changes_in(store)
44
+ if store.respond_to?(:to_str)
45
+ @store = FileStore.new(store.to_str)
46
+ else
47
+ @store = store
48
+ end
49
+ end
50
+
51
+ def define_change(&change_test_block)
52
+ @change_test_block = change_test_block
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,52 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+ require 'file_test_helper'
3
+ include FileTestHelper
4
+
5
+ Expectations do
6
+ expect nil do
7
+ with_files do
8
+ ChangeWatcher::FileStore.new("store.yml").latest_value
9
+ end
10
+ end
11
+
12
+ expect true do
13
+ with_files do
14
+ ChangeWatcher::FileStore.new("store.yml").empty?
15
+ end
16
+ end
17
+
18
+ expect true do
19
+ with_files "store.yml" => "" do
20
+ ChangeWatcher::FileStore.new("store.yml").empty?
21
+ end
22
+ end
23
+
24
+ expect false do
25
+ with_files "store.yml" => [Time.now, 6969].to_yaml do
26
+ ChangeWatcher::FileStore.new("store.yml").empty?
27
+ end
28
+ end
29
+
30
+ expect 6969 do
31
+ with_files "store.yml" => [Time.now, 6969].to_yaml do
32
+ ChangeWatcher::FileStore.new("store.yml").latest_value
33
+ end
34
+ end
35
+
36
+ expect 6969 do
37
+ with_files do
38
+ file_store = ChangeWatcher::FileStore.new("store.yml")
39
+ file_store.save(6969)
40
+ file_store.latest_value
41
+ end
42
+ end
43
+
44
+ expect 2 do
45
+ with_files do
46
+ file_store = ChangeWatcher::FileStore.new("store.yml")
47
+ file_store.save(1)
48
+ file_store.save(2)
49
+ file_store.latest_value
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,203 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+ require 'file_test_helper'
3
+ include FileTestHelper
4
+
5
+ Expectations do
6
+ expect "Something changed" do
7
+ result = "Nothing changed"
8
+
9
+ change_watcher = ChangeWatcher.new do
10
+ data_to_watch do
11
+ 0
12
+ end
13
+
14
+ on_change do
15
+ result = "Something changed"
16
+ end
17
+
18
+ store_changes_in TestStore.new
19
+ end
20
+
21
+ change_watcher.check_for_change
22
+ result
23
+ end
24
+
25
+ expect "Nothing changed" do
26
+ result = "Nothing changed"
27
+
28
+ change_watcher = ChangeWatcher.new do
29
+ data_to_watch do
30
+ 0
31
+ end
32
+
33
+ on_change do
34
+ result = "Something changed"
35
+ end
36
+
37
+ store_changes_in TestStore.new
38
+ end
39
+
40
+ change_watcher.check_for_change
41
+ result = "Nothing changed"
42
+ change_watcher.check_for_change
43
+ result
44
+ end
45
+
46
+ expect "Nothing changed" do
47
+ result = "Nothing changed"
48
+
49
+ change_watcher = ChangeWatcher.new do
50
+ data_to_watch do
51
+ 0
52
+ end
53
+
54
+ define_change do |old_value, new_value|
55
+ old_value != new_value
56
+ end
57
+
58
+ on_change do
59
+ result = "Something changed"
60
+ end
61
+
62
+ store_changes_in TestStore.new
63
+ end
64
+
65
+ change_watcher.check_for_change
66
+ result = "Nothing changed"
67
+ change_watcher.check_for_change
68
+ result
69
+ end
70
+
71
+ expect "Something changed" do
72
+ result = "Nothing changed"
73
+
74
+ change_watcher = ChangeWatcher.new do
75
+ data_to_watch do
76
+ 0
77
+ end
78
+
79
+ define_change do |old_value, new_value|
80
+ old_value == new_value
81
+ end
82
+
83
+ on_change do
84
+ result = "Something changed"
85
+ end
86
+
87
+ store_changes_in TestStore.new
88
+ end
89
+
90
+ change_watcher.check_for_change
91
+ result = "Nothing changed"
92
+ change_watcher.check_for_change
93
+ result
94
+ end
95
+
96
+ expect "It was 0 but now it is 1" do
97
+ watched_value = 0
98
+ result = "Nothing changed"
99
+
100
+ change_watcher = ChangeWatcher.new do
101
+ data_to_watch do
102
+ watched_value
103
+ end
104
+
105
+ on_change do |old_value, new_value|
106
+ result = "It was #{old_value} but now it is #{new_value}"
107
+ end
108
+
109
+ store_changes_in TestStore.new
110
+ end
111
+
112
+ change_watcher.check_for_change
113
+ watched_value = 1
114
+ change_watcher.check_for_change
115
+ result
116
+ end
117
+
118
+ expect "It was 1 but now it is 2" do
119
+ watched_value = 0
120
+ result = "Nothing changed"
121
+
122
+ change_watcher = ChangeWatcher.new do
123
+ data_to_watch do
124
+ watched_value
125
+ end
126
+
127
+ on_change do |old_value, new_value|
128
+ result = "It was #{old_value} but now it is #{new_value}"
129
+ end
130
+
131
+ store_changes_in TestStore.new
132
+ end
133
+
134
+ change_watcher.check_for_change
135
+ watched_value = 1
136
+ change_watcher.check_for_change
137
+ watched_value = 2
138
+ change_watcher.check_for_change
139
+ result
140
+ end
141
+
142
+ expect false do
143
+ store = TestStore.new
144
+
145
+ change_watcher = ChangeWatcher.new do
146
+ data_to_watch do
147
+ 0
148
+ end
149
+
150
+ store_changes_in store
151
+ end
152
+
153
+ change_watcher.check_for_change
154
+ store.empty?
155
+ end
156
+
157
+ expect false do
158
+ store = TestStore.new
159
+
160
+ change_watcher = ChangeWatcher.new do
161
+ data_to_watch do
162
+ 0
163
+ end
164
+
165
+ store_changes_in store
166
+ end
167
+
168
+ change_watcher.check_for_change
169
+ change_watcher.check_for_change
170
+ store.empty?
171
+ end
172
+
173
+ expect true do
174
+ i = 0
175
+ store = TestStore.new
176
+
177
+ change_watcher = ChangeWatcher.new do
178
+ data_to_watch do
179
+ i += 1
180
+ end
181
+
182
+ store_changes_in store
183
+ end
184
+
185
+ change_watcher.check_for_change
186
+ !store.empty?
187
+ end
188
+
189
+ expect true do
190
+ with_files do
191
+ change_watcher = ChangeWatcher.new do
192
+ data_to_watch do
193
+ 12345678
194
+ end
195
+
196
+ store_changes_in "store.yml"
197
+ end
198
+
199
+ change_watcher.check_for_change
200
+ !!(File.read("store.yml") =~ /12345678/)
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'expectations'
3
+
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ require 'change_watcher'
7
+
8
+ class TestStore
9
+ def initialize
10
+ @array = []
11
+ end
12
+
13
+ def latest_value
14
+ @array.last
15
+ end
16
+
17
+ def empty?
18
+ @array.empty?
19
+ end
20
+
21
+ def save(value)
22
+ @array << value
23
+ end
24
+ end
25
+
26
+ class Test::Unit::TestCase
27
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dcadenas-change_watcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Cadenas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-17 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: dcadenas@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README.rdoc
30
+ - Rakefile
31
+ - VERSION
32
+ - change_watcher.gemspec
33
+ - lib/change_watcher.rb
34
+ - lib/change_watcher/file_store.rb
35
+ - lib/change_watcher/store.rb
36
+ - test/change_watcher/file_store_test.rb
37
+ - test/change_watcher_test.rb
38
+ - test/test_helper.rb
39
+ has_rdoc: false
40
+ homepage: http://github.com/dcadenas/change_watcher
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.2.0
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: TODO
65
+ test_files:
66
+ - test/change_watcher/file_store_test.rb
67
+ - test/change_watcher_test.rb
68
+ - test/test_helper.rb