activerecord-diff 0.0.2 → 2.0.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.
@@ -0,0 +1,55 @@
1
+ activerecord-diff
2
+ =================
3
+
4
+
5
+ Simple ActiveRecord diff functionality.
6
+
7
+
8
+ Example usage
9
+ -------------
10
+
11
+ ```ruby
12
+ require 'active_record/diff'
13
+
14
+ class User < ActiveRecord::Base
15
+ include ActiveRecord::Diff
16
+ end
17
+
18
+ alice = User.create(:name => 'alice', :email_address => 'alice@example.org')
19
+
20
+ bob = User.create(:name => 'bob', :email_address => 'bob@example.org')
21
+
22
+ alice.diff?(bob) # => true
23
+
24
+ alice.diff(bob) # => {:name => ['alice', 'bob'], :email_address => ['alice@example.org', 'bob@example.org']}
25
+
26
+ alice.diff({:name => 'eve'}) # => {:name => ['alice', 'eve']}
27
+ ```
28
+
29
+
30
+ Configuration
31
+ -------------
32
+
33
+ By default, ActiveRecord::Base.content_columns is used to decide which attributes
34
+ to compare. You can include or exclude attributes from this as follows:
35
+
36
+ ```ruby
37
+ class User < ActiveRecord::Base
38
+ diff :include => [:id], :exclude => [:password_hash]
39
+ end
40
+ ```
41
+
42
+ Alternatively, you can specify exactly which columns to compare:
43
+
44
+ ```ruby
45
+ class User < ActiveRecord::Base
46
+ diff :id, :name, :email_address
47
+ end
48
+ ```
49
+
50
+ Copyright
51
+ ---------
52
+
53
+ To the extent possible under law, Tim Fletcher has waived all copyright and
54
+ related or neighboring rights to activerecord-diff. This work is published
55
+ from the United Kingdom. http://creativecommons.org/publicdomain/zero/1.0/
@@ -1,28 +1,18 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "active_record_diff/version"
4
-
5
1
  Gem::Specification.new do |s|
6
- s.name = "activerecord-diff"
7
- s.version = ActiveRecordDiff::VERSION
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ["Stephen Prater"]
10
- s.email = ["stephenp@agrussell.com"]
11
- s.homepage = "http://github.com/agrussellknives/activerecord-diff"
12
- s.summary = %q{Gemify Simple diff for ActiveRecord objects.}
13
- s.description = %q{Simple diff for ActiveRecord }
14
-
15
- s.rubyforge_project = "activerecord-diff"
16
-
17
- s.files = `git ls-files`.split("\n")
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
- s.require_paths = ["lib"]
21
-
22
- s.add_dependency('activerecord')
23
- s.add_dependency('activesupport')
2
+ s.name = 'activerecord-diff'
3
+ s.version = '2.0.0'
4
+ s.platform = Gem::Platform::RUBY
5
+ s.authors = ['Tim Fletcher']
6
+ s.email = ['mail@tfletcher.com']
7
+ s.homepage = 'http://github.com/tim/activerecord-diff'
8
+ s.description = 'Simple ActiveRecord diff functionality'
9
+ s.summary = 'See description'
10
+ s.files = Dir.glob('{lib,spec}/**/*') + %w(README.md activerecord-diff.gemspec)
11
+ s.add_development_dependency('rake', '~> 10.0.3')
12
+ s.add_development_dependency('sqlite3', '~> 1.3.6')
13
+ s.require_path = 'lib'
24
14
 
25
- s.add_development_dependency('bundler')
26
- s.add_development_dependency('rake')
27
- s.add_development_dependency('sqlite3-ruby')
15
+ if RUBY_VERSION == '1.8.7'
16
+ s.add_development_dependency('minitest', '>= 4.2.0')
17
+ end
28
18
  end
@@ -0,0 +1,58 @@
1
+ module ActiveRecord
2
+ module Diff
3
+ module ClassMethod
4
+ def diff(*attrs)
5
+ self.diff_attrs = attrs
6
+ end
7
+ end
8
+
9
+ def self.included(base)
10
+ base.class_attribute :diff_attrs
11
+ base.extend ClassMethod
12
+ end
13
+
14
+ def diff?(record = nil)
15
+ not diff(record).empty?
16
+ end
17
+
18
+ def diff(other_record = nil)
19
+ if other_record.nil?
20
+ old_record, new_record = self.class.find(id), self
21
+ else
22
+ old_record, new_record = self, other_record
23
+ end
24
+
25
+ if new_record.is_a?(Hash)
26
+ diff_each(new_record) do |(attr_name, hash_value)|
27
+ [attr_name, old_record.send(attr_name), hash_value]
28
+ end
29
+ else
30
+ attrs = self.class.diff_attrs
31
+
32
+ if attrs.nil?
33
+ attrs = self.class.content_columns.map { |column| column.name.to_sym }
34
+ elsif attrs.length == 1 && Hash === attrs.first
35
+ columns = self.class.content_columns.map { |column| column.name.to_sym }
36
+
37
+ attrs = columns + (attrs.first[:include] || []) - (attrs.first[:exclude] || [])
38
+ end
39
+
40
+ diff_each(attrs) do |attr_name|
41
+ [attr_name, old_record.send(attr_name), new_record.send(attr_name)]
42
+ end
43
+ end
44
+ end
45
+
46
+ def diff_each(enum)
47
+ enum.inject({}) do |diff_hash, attr_name|
48
+ attr_name, old_value, new_value = *yield(attr_name)
49
+
50
+ unless old_value === new_value
51
+ diff_hash[attr_name.to_sym] = [old_value, new_value]
52
+ end
53
+
54
+ diff_hash
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,88 @@
1
+ require 'minitest/autorun'
2
+ require 'active_record'
3
+ require 'active_record/diff'
4
+
5
+ ActiveRecord::Base.establish_connection('adapter' => 'sqlite3', 'database' => ':memory:')
6
+
7
+ ActiveRecord::Schema.define do
8
+ create_table :people do |table|
9
+ table.column :name, :string
10
+ table.column :email_address, :string
11
+ end
12
+ end
13
+
14
+ describe 'ActiveRecord::Diff' do
15
+ before do
16
+ @person = Class.new(ActiveRecord::Base) do
17
+ self.table_name = :people
18
+
19
+ include ActiveRecord::Diff
20
+ end
21
+
22
+ @person.create! :name => 'alice', :email_address => 'alice@example.com'
23
+ @person.create! :name => 'bob', :email_address => 'bob@example.com'
24
+ @person.create! :name => 'eve', :email_address => 'bob@example.com'
25
+
26
+ @people = @person.all
27
+
28
+ @alice, @bob, @eve = *@people
29
+ end
30
+
31
+ describe 'diff method' do
32
+ it 'returns a hash of the differences between the attributes of the records' do
33
+ @bob.diff(@alice).must_equal({:name => %w( bob alice ), :email_address => %w( bob@example.com alice@example.com )})
34
+
35
+ @bob.diff(@eve).must_equal({:name => %w( bob eve )})
36
+ end
37
+
38
+ it 'excludes and includes attributes as specified by the diff class method' do
39
+ @person.diff :include => [:id], :exclude => [:email_address]
40
+
41
+ @alice.diff(@bob).must_equal({:id => [1, 2], :name => %w( alice bob )})
42
+ end
43
+
44
+ it 'uses the list of attributes specified by the diff class method' do
45
+ @person.diff :id, :name
46
+
47
+ @alice.diff(@bob).must_equal({:id => [1, 2], :name => %w( alice bob )})
48
+ end
49
+ end
50
+
51
+ describe 'diff method called with a hash argument' do
52
+ it 'returns a hash of the differences between the attributes of the record and the given hash' do
53
+ @bob.diff({:name => 'joe'}).must_equal({:name => %w( bob joe )})
54
+ end
55
+ end
56
+
57
+ describe 'diff method called without arguments' do
58
+ it 'returns a hash of the differences when the record has changes' do
59
+ @eve.name = 'bob'
60
+
61
+ @eve.diff.must_equal({:name => %w( eve bob )})
62
+ end
63
+
64
+ it 'returns an empty hash when the record has no changes' do
65
+ @eve.diff.must_equal({})
66
+ end
67
+ end
68
+
69
+ describe 'diff query method' do
70
+ it 'returns true when there are differences between the argument and the receiver' do
71
+ @alice.diff?(@bob).must_equal(true)
72
+ end
73
+
74
+ it 'returns true when there are no differences between the argument and the receiver' do
75
+ @alice.diff?(@alice).must_equal(false)
76
+ end
77
+ end
78
+
79
+ describe 'diff query method called without arguments' do
80
+ it 'returns true when the record has changes' do
81
+ @alice.diff?(@alice).must_equal(false)
82
+ end
83
+
84
+ it 'returns false when the record has no changes' do
85
+ @alice.diff?.must_equal(false)
86
+ end
87
+ end
88
+ end
metadata CHANGED
@@ -1,90 +1,60 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - Stephen Prater
8
+ - Tim Fletcher
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-13 00:00:00.000000000 -05:00
13
- default_executable:
12
+ date: 2013-03-11 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
- name: activerecord
17
- requirement: &9846140 !ruby/object:Gem::Requirement
18
- none: false
19
- requirements:
20
- - - ! '>='
21
- - !ruby/object:Gem::Version
22
- version: '0'
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: *9846140
26
- - !ruby/object:Gem::Dependency
27
- name: activesupport
28
- requirement: &9845930 !ruby/object:Gem::Requirement
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
29
17
  none: false
30
18
  requirements:
31
- - - ! '>='
19
+ - - ~>
32
20
  - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
21
+ version: 10.0.3
22
+ type: :development
35
23
  prerelease: false
36
- version_requirements: *9845930
37
- - !ruby/object:Gem::Dependency
38
- name: bundler
39
- requirement: &9845720 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
40
25
  none: false
41
26
  requirements:
42
- - - ! '>='
27
+ - - ~>
43
28
  - !ruby/object:Gem::Version
44
- version: '0'
45
- type: :development
46
- prerelease: false
47
- version_requirements: *9845720
29
+ version: 10.0.3
48
30
  - !ruby/object:Gem::Dependency
49
- name: rake
50
- requirement: &9845510 !ruby/object:Gem::Requirement
31
+ name: sqlite3
32
+ requirement: !ruby/object:Gem::Requirement
51
33
  none: false
52
34
  requirements:
53
- - - ! '>='
35
+ - - ~>
54
36
  - !ruby/object:Gem::Version
55
- version: '0'
37
+ version: 1.3.6
56
38
  type: :development
57
39
  prerelease: false
58
- version_requirements: *9845510
59
- - !ruby/object:Gem::Dependency
60
- name: sqlite3-ruby
61
- requirement: &9845300 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
62
41
  none: false
63
42
  requirements:
64
- - - ! '>='
43
+ - - ~>
65
44
  - !ruby/object:Gem::Version
66
- version: '0'
67
- type: :development
68
- prerelease: false
69
- version_requirements: *9845300
70
- description: ! 'Simple diff for ActiveRecord '
45
+ version: 1.3.6
46
+ description: Simple ActiveRecord diff functionality
71
47
  email:
72
- - stephenp@agrussell.com
48
+ - mail@tfletcher.com
73
49
  executables: []
74
50
  extensions: []
75
51
  extra_rdoc_files: []
76
52
  files:
77
- - .gitignore
78
- - Gemfile
79
- - README.txt
80
- - Rakefile
53
+ - lib/active_record/diff.rb
54
+ - spec/active_record_diff_spec.rb
55
+ - README.md
81
56
  - activerecord-diff.gemspec
82
- - lib/..rb
83
- - lib/active_record_diff/version.rb
84
- - lib/activerecord-diff.rb
85
- - test/test.rb
86
- has_rdoc: true
87
- homepage: http://github.com/agrussellknives/activerecord-diff
57
+ homepage: http://github.com/tim/activerecord-diff
88
58
  licenses: []
89
59
  post_install_message:
90
60
  rdoc_options: []
@@ -103,10 +73,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
73
  - !ruby/object:Gem::Version
104
74
  version: '0'
105
75
  requirements: []
106
- rubyforge_project: activerecord-diff
107
- rubygems_version: 1.5.2
76
+ rubyforge_project:
77
+ rubygems_version: 1.8.25
108
78
  signing_key:
109
79
  specification_version: 3
110
- summary: Gemify Simple diff for ActiveRecord objects.
111
- test_files:
112
- - test/test.rb
80
+ summary: See description
81
+ test_files: []
data/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- *.gem
2
- .bundle
3
- Gemfile.lock
4
- pkg/*
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in ..gemspec
4
- gemspec
data/README.txt DELETED
@@ -1,42 +0,0 @@
1
- Simple ActiveRecord diff functionality.
2
-
3
- Example usage:
4
-
5
- require 'active_record/diff'
6
-
7
- class User < ActiveRecord::Base
8
- include ActiveRecord::Diff
9
- end
10
-
11
- alice = User.create(:name => 'alice', :email_address => 'alice@example.org')
12
-
13
- bob = User.create(:name => 'bob', :email_address => 'bob@example.org')
14
-
15
- alice.diff?(bob) # => true
16
-
17
- alice.diff(bob) # => {:name => ['alice', 'bob'], :email_address => ['alice@example.org', 'bob@example.org']}
18
-
19
- alice.diff({:name => 'eve'}) # => {:name => ['alice', 'eve']}
20
-
21
-
22
- By default, ActiveRecord::Base.content_columns is used to decide which attributes
23
- to compare. You can include or exclude attributes from this as follows:
24
-
25
- class User < ActiveRecord::Base
26
- diff :include => [:id], :exclude => [:password_hash]
27
- end
28
-
29
-
30
- Alternatively, you can specify exactly which columns to compare:
31
-
32
- class User < ActiveRecord::Base
33
- diff :id, :name, :email_address
34
- end
35
-
36
-
37
- This is an updated version of the "riff" rails plugin.
38
-
39
-
40
- To the extent possible under law, Tim Fletcher has waived all copyright and
41
- related or neighboring rights to activerecord-diff. This work is published
42
- from the United Kingdom. http://creativecommons.org/publicdomain/zero/1.0/
data/Rakefile DELETED
@@ -1,11 +0,0 @@
1
- require 'bundler'
2
- require 'rake/testtask'
3
-
4
- Bundler::GemHelper.install_tasks
5
-
6
- Rake::TestTask.new do |t|
7
- t.libs << "test"
8
- t.test_files = FileList['test/test*.rb']
9
- t.verbose = true
10
- end
11
-
data/lib/..rb DELETED
@@ -1,3 +0,0 @@
1
- module .
2
- # Your code goes here...
3
- end
@@ -1,3 +0,0 @@
1
- module ActiveRecordDiff
2
- VERSION = "0.0.2"
3
- end
@@ -1,73 +0,0 @@
1
- require 'active_support/core_ext'
2
- require 'active_record'
3
-
4
- module ActiveRecord
5
- module Diff
6
- module ClassMethods
7
- def diff(*attrs)
8
- write_inheritable_attribute(:diff_attrs, attrs)
9
- end
10
-
11
- def diff_attrs
12
- attrs = read_inheritable_attribute(:diff_attrs)
13
-
14
- if attrs.nil?
15
- content_columns.map { |column| column.name }
16
- elsif attrs.length == 1 && Hash === attrs.first
17
- columns = content_columns.map { |column| column.name.to_sym }
18
-
19
- columns + (attrs.first[:include] || []) - (attrs.first[:exclude] || [])
20
- else
21
- attrs
22
- end
23
- end
24
- end
25
-
26
- def self.included(base)
27
- base.extend ClassMethods
28
- end
29
-
30
- def diff?(record = nil)
31
- not diff(record).empty?
32
- end
33
-
34
- def diff(other_record = nil)
35
-
36
- if other_record.nil?
37
- old_record, new_record = self.class.find(id), self
38
- else
39
- old_record, new_record = self, other_record
40
- end
41
-
42
- if new_record.is_a?(Hash)
43
- diff_each(new_record) do |(attr_name, hash_value)|
44
- if block_given?
45
- yield attr_name, old_record.send(attr_name), hash_value
46
- else
47
- [attr_name, old_record.send(attr_name), hash_value]
48
- end
49
- end
50
- else
51
- diff_each(self.class.diff_attrs) do |attr_name|
52
- if block_given?
53
- yield attr_name, old_record.send(attr_name), new_record.send(attr_name)
54
- else
55
- [attr_name, old_record.send(attr_name), new_record.send(attr_name)]
56
- end
57
- end
58
- end
59
- end
60
-
61
- def diff_each(enum)
62
- enum.inject({}) do |diff_hash, attr_name|
63
- attr_name, old_value, new_value = *yield(attr_name)
64
-
65
- unless old_value === new_value
66
- diff_hash[attr_name.to_sym] = [old_value, new_value]
67
- end
68
-
69
- diff_hash
70
- end
71
- end
72
- end
73
- end
@@ -1,90 +0,0 @@
1
- require 'activerecord-diff'
2
- require 'test/unit'
3
-
4
- require 'pry'
5
-
6
- class Person < ActiveRecord::Base
7
- include ActiveRecord::Diff
8
- end
9
-
10
- ActiveRecord::Base.establish_connection('adapter' => 'sqlite3', 'database' => ':memory:')
11
-
12
- ActiveRecord::Schema.define do
13
- create_table :people do |table|
14
- table.column :name, :string
15
- table.column :email_address, :string
16
- end
17
- end
18
-
19
- Person.create :name => 'alice', :email_address => 'alice@example.org'
20
-
21
- Person.create :name => 'bob', :email_address => 'bob@example.org'
22
- Person.create :name => 'BOB', :email_address => 'BOB@EXAMPLE.ORG'
23
-
24
- Person.create :name => 'eve', :email_address => 'bob@example.org'
25
-
26
-
27
- class TestCase < Test::Unit::TestCase
28
- def setup
29
- @people = Person.find(:all)
30
-
31
- @alice, @bob, @capital_bob, @eve = *@people
32
- end
33
-
34
- def keysort(hash)
35
- hash.sort_by { |k, v| k.to_s }
36
- end
37
-
38
- def assert_diff(a, b, diff)
39
- assert_equal keysort(diff), keysort(a.diff(b))
40
- end
41
-
42
- def test_diff_query
43
- @people.each do |person|
44
- @people.each do |other_person|
45
- if other_person == person
46
- assert_equal false, person.diff?(other_person)
47
- else
48
- assert person.diff?(other_person)
49
- end
50
- end
51
- end
52
- end
53
-
54
- def test_diff_against_other_record
55
- assert_diff @bob, @alice, {:name => %w( bob alice ), :email_address => %w( bob@example.org alice@example.org )}
56
-
57
- assert_diff @bob, @eve, {:name => %w( bob eve )}
58
- end
59
-
60
- def test_diff_with_block
61
- assert_diff @bob, @capital_bob, {:name => %w( bob BOB), :email_address => %w( bob@example.org BOB@EXAMPLE.ORG )}
62
-
63
- diff = @bob.diff(@capital_bob) do |attrib, old, new|
64
- [attrib, old.downcase, new.downcase]
65
- end
66
-
67
- assert diff.empty?
68
- end
69
-
70
-
71
- def test_diff_against_saved_self
72
- assert ! @eve.diff?
73
-
74
- @eve.name = 'alice'
75
-
76
- assert @eve.diff?
77
-
78
- assert_diff @eve, nil, {:name => ['eve', 'alice']}
79
- end
80
-
81
- def test_diff_against_hash
82
- assert_diff @bob, {:name => 'joe'}, {:name => ['bob', 'joe']}
83
- end
84
-
85
- def test_inclusion_and_exclusion
86
- Person.diff :include => [:id], :exclude => [:email_address]
87
-
88
- assert_diff @alice, @bob, {:id => [1, 2], :name => %w( alice bob )}
89
- end
90
- end