activerecord-diff 0.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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