ar-deltas 0.6

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.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Arya Asemanfar
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ lib/ar-deltas.rb
2
+ MIT-LICENSE
3
+ Rakefile
4
+ Manifest
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('ar-deltas', '0.6') do |p|
6
+ p.description = "ActiveRecord extension to allow for updating numerical attributes using deltas."
7
+ p.url = "https://github.com/arya/ar-deltas/"
8
+ p.author = "Arya Asemanfar"
9
+ p.email = "aryaasemanfar@gmail.com"
10
+ p.ignore_pattern = ["tmp/*", "script/*", 'test/*']
11
+ p.runtime_dependencies = ["activerecord"]
12
+ p.development_dependencies = ["shoulda"]
13
+ end
14
+
15
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ar-deltas}
5
+ s.version = "0.6"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Arya Asemanfar"]
9
+ s.date = %q{2009-09-30}
10
+ s.description = %q{ActiveRecord extension to allow for updating numerical attributes using deltas.}
11
+ s.email = %q{aryaasemanfar@gmail.com}
12
+ s.extra_rdoc_files = ["lib/ar-deltas.rb"]
13
+ s.files = ["lib/ar-deltas.rb", "MIT-LICENSE", "Rakefile", "Manifest", "ar-deltas.gemspec", "test/deltas_test.rb", "test/test_helper.rb"]
14
+ s.homepage = %q{https://github.com/arya/ar-deltas/}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ar-deltas", "--main", "README.markdown"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{ar-deltas}
18
+ s.rubygems_version = %q{1.3.4}
19
+ s.summary = %q{ActiveRecord extension to allow for updating numerical attributes using deltas.}
20
+ s.test_files = ["test/deltas_test.rb", "test/test_helper.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_runtime_dependency(%q<activerecord>, [">= 0"])
28
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
29
+ else
30
+ s.add_dependency(%q<activerecord>, [">= 0"])
31
+ s.add_dependency(%q<shoulda>, [">= 0"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<activerecord>, [">= 0"])
35
+ s.add_dependency(%q<shoulda>, [">= 0"])
36
+ end
37
+ end
@@ -0,0 +1,48 @@
1
+ require 'set'
2
+
3
+ module ActiveRecord::Deltas
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ alias_method_chain :attributes_with_quotes, :deltas
7
+ end
8
+ end
9
+
10
+ def attributes_with_quotes_with_deltas(*args)
11
+ with_deltas = attributes_with_quotes_without_deltas(*args)
12
+ return with_deltas if self.new_record?
13
+ with_deltas.keys.each do |attribute_name|
14
+ if self.class.delta_attributes.include?(attribute_name.intern) && !self.excluded_deltas.include?(attribute_name.intern)
15
+ delta_string = "#{self.connection.quote_column_name(attribute_name)} "
16
+ old_value, new_value = self.changes[attribute_name]
17
+ delta_string << (old_value > new_value ? "-" : "+")
18
+ delta_string << " #{(old_value - new_value).abs}"
19
+ with_deltas[attribute_name] = delta_string
20
+ end
21
+ end
22
+ with_deltas
23
+ end
24
+
25
+ def excluded_deltas
26
+ @_excluded_deltas ||= Set.new
27
+ end
28
+
29
+ def force_clobber(attr_name, value)
30
+ self.excluded_deltas.add(attr_name.to_s.intern)
31
+ send("#{attr_name}=", value)
32
+ end
33
+ end
34
+
35
+ class ActiveRecord::Base
36
+ include ActiveRecord::Deltas
37
+ class InvalidDeltaColumn < StandardError; end
38
+ def self.delta_attributes(*args)
39
+ @_delta_attributes ||= Set.new
40
+
41
+ return @_delta_attributes if args.empty?
42
+
43
+ args.each do |attribute|
44
+ raise InvalidDeltaColumn.new("Delta attributes only work with number attributes, column `#{attribute}` is not a number.") unless self.columns_hash[attribute.to_s].number?
45
+ @_delta_attributes.add(attribute)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+ puts ActiveRecord::VERSION::STRING
3
+
4
+ class DeltasTest < Test::Unit::TestCase
5
+ include TestHelper
6
+ context "with an blank AR class" do
7
+ setup do
8
+ conn = connection_specification # because it changes context in the block
9
+ @klass = Class.new(ActiveRecord::Base) do
10
+ self.table_name = "widgets"
11
+ establish_connection(conn)
12
+ end
13
+ end
14
+
15
+ should "should throw exception for deltaing non-number fields" do
16
+ assert_raises(ActiveRecord::Base::InvalidDeltaColumn) do
17
+ @klass.class_eval { delta_attributes :name }
18
+ end
19
+ end
20
+
21
+ should "override values with latest update" do
22
+ original = @klass.create
23
+ one, two = @klass.find(original.id), @klass.find(original.id)
24
+ one.counter += 2
25
+ two.counter += 3
26
+ one.save
27
+ two.save
28
+ assert_equal 3, original.reload.counter
29
+ end
30
+
31
+ context "with a delta attribute" do
32
+ setup do
33
+ @klass.class_eval { delta_attributes :counter }
34
+ end
35
+
36
+ should "update value using delta (additions)" do
37
+ original = @klass.create
38
+ one, two = @klass.find(original.id), @klass.find(original.id)
39
+ one.counter += 2
40
+ two.counter += 3
41
+ one.save
42
+ two.save
43
+ assert_equal 5, original.reload.counter
44
+ end
45
+
46
+ should "update value using delta (subtractions)" do
47
+ original = @klass.create
48
+ one, two = @klass.find(original.id), @klass.find(original.id)
49
+ one.counter -= 6
50
+ two.counter -= 7
51
+ one.save
52
+ two.save
53
+ assert_equal -13, original.reload.counter
54
+ end
55
+
56
+ should "exclude delta attribute if explictly specified" do
57
+ original = @klass.create
58
+ one, two = @klass.find(original.id), @klass.find(original.id)
59
+ one.force_clobber(:counter, 100)
60
+ two.force_clobber(:counter, 3000)
61
+ one.save
62
+ two.save
63
+ assert_equal 3000, original.reload.counter
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,20 @@
1
+ TEST_DIR = File.dirname(__FILE__)
2
+ %w(lib test).each do |dir|
3
+ $LOAD_PATH.unshift File.join(TEST_DIR, "..", dir)
4
+ end
5
+
6
+ require 'test/unit'
7
+ require 'rubygems'
8
+ require 'shoulda'
9
+
10
+ require 'activerecord'
11
+ require 'ar-deltas'
12
+
13
+ # To run the tests, you need a MySQL database as described below.
14
+ # create table widgets (id int auto_increment primary key, counter int default 0, name varchar(255));
15
+
16
+ module TestHelper
17
+ def connection_specification
18
+ {:username => "root", :password => "", :database => "ar_deltas", :adapter => "mysql"}
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ar-deltas
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.6"
5
+ platform: ruby
6
+ authors:
7
+ - Arya Asemanfar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-30 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: shoulda
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: ActiveRecord extension to allow for updating numerical attributes using deltas.
36
+ email: aryaasemanfar@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - lib/ar-deltas.rb
43
+ files:
44
+ - lib/ar-deltas.rb
45
+ - MIT-LICENSE
46
+ - Rakefile
47
+ - Manifest
48
+ - ar-deltas.gemspec
49
+ - test/deltas_test.rb
50
+ - test/test_helper.rb
51
+ has_rdoc: true
52
+ homepage: https://github.com/arya/ar-deltas/
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --line-numbers
58
+ - --inline-source
59
+ - --title
60
+ - Ar-deltas
61
+ - --main
62
+ - README.markdown
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "1.2"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project: ar-deltas
80
+ rubygems_version: 1.3.4
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: ActiveRecord extension to allow for updating numerical attributes using deltas.
84
+ test_files:
85
+ - test/deltas_test.rb
86
+ - test/test_helper.rb