activerecord-diff 0.0.1
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.txt +42 -0
- data/Rakefile +11 -0
- data/activerecord-diff.gemspec +28 -0
- data/lib/..rb +3 -0
- data/lib/active_record_diff/version.rb +3 -0
- data/lib/activerecord-diff.rb +64 -0
- data/test/test.rb +77 -0
- metadata +112 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.txt
ADDED
@@ -0,0 +1,42 @@
|
|
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
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "active_record_diff/version"
|
4
|
+
|
5
|
+
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')
|
24
|
+
|
25
|
+
s.add_development_dependency('bundler')
|
26
|
+
s.add_development_dependency('rake')
|
27
|
+
s.add_development_dependency('sqlite3-ruby')
|
28
|
+
end
|
data/lib/..rb
ADDED
@@ -0,0 +1,64 @@
|
|
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
|
+
if other_record.nil?
|
36
|
+
old_record, new_record = self.class.find(id), self
|
37
|
+
else
|
38
|
+
old_record, new_record = self, other_record
|
39
|
+
end
|
40
|
+
|
41
|
+
if new_record.is_a?(Hash)
|
42
|
+
diff_each(new_record) do |(attr_name, hash_value)|
|
43
|
+
[attr_name, old_record.send(attr_name), hash_value]
|
44
|
+
end
|
45
|
+
else
|
46
|
+
diff_each(self.class.diff_attrs) do |attr_name|
|
47
|
+
[attr_name, old_record.send(attr_name), new_record.send(attr_name)]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def diff_each(enum)
|
53
|
+
enum.inject({}) do |diff_hash, attr_name|
|
54
|
+
attr_name, old_value, new_value = *yield(attr_name)
|
55
|
+
|
56
|
+
unless old_value === new_value
|
57
|
+
diff_hash[attr_name.to_sym] = [old_value, new_value]
|
58
|
+
end
|
59
|
+
|
60
|
+
diff_hash
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/test/test.rb
ADDED
@@ -0,0 +1,77 @@
|
|
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
|
+
|
23
|
+
Person.create :name => 'eve', :email_address => 'bob@example.org'
|
24
|
+
|
25
|
+
class TestCase < Test::Unit::TestCase
|
26
|
+
def setup
|
27
|
+
@people = Person.find(:all)
|
28
|
+
|
29
|
+
@alice, @bob, @eve = *@people
|
30
|
+
end
|
31
|
+
|
32
|
+
def keysort(hash)
|
33
|
+
hash.sort_by { |k, v| k.to_s }
|
34
|
+
end
|
35
|
+
|
36
|
+
def assert_diff(a, b, diff)
|
37
|
+
assert_equal keysort(diff), keysort(a.diff(b))
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_diff_query
|
41
|
+
@people.each do |person|
|
42
|
+
@people.each do |other_person|
|
43
|
+
if other_person == person
|
44
|
+
assert_equal false, person.diff?(other_person)
|
45
|
+
else
|
46
|
+
assert person.diff?(other_person)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_diff_against_other_record
|
53
|
+
assert_diff @bob, @alice, {:name => %w( bob alice ), :email_address => %w( bob@example.org alice@example.org )}
|
54
|
+
|
55
|
+
assert_diff @bob, @eve, {:name => %w( bob eve )}
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_diff_against_saved_self
|
59
|
+
assert ! @eve.diff?
|
60
|
+
|
61
|
+
@eve.name = 'alice'
|
62
|
+
|
63
|
+
assert @eve.diff?
|
64
|
+
|
65
|
+
assert_diff @eve, nil, {:name => ['eve', 'alice']}
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_diff_against_hash
|
69
|
+
assert_diff @bob, {:name => 'joe'}, {:name => ['bob', 'joe']}
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_inclusion_and_exclusion
|
73
|
+
Person.diff :include => [:id], :exclude => [:email_address]
|
74
|
+
|
75
|
+
assert_diff @alice, @bob, {:id => [1, 2], :name => %w( alice bob )}
|
76
|
+
end
|
77
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-diff
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Stephen Prater
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-13 00:00:00.000000000 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
requirement: &10351960 !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: *10351960
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: activesupport
|
28
|
+
requirement: &10351750 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *10351750
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: bundler
|
39
|
+
requirement: &10351540 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *10351540
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rake
|
50
|
+
requirement: &10351330 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *10351330
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: sqlite3-ruby
|
61
|
+
requirement: &10351120 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *10351120
|
70
|
+
description: ! 'Simple diff for ActiveRecord '
|
71
|
+
email:
|
72
|
+
- stephenp@agrussell.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- README.txt
|
80
|
+
- Rakefile
|
81
|
+
- 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
|
88
|
+
licenses: []
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project: activerecord-diff
|
107
|
+
rubygems_version: 1.5.2
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: Gemify Simple diff for ActiveRecord objects.
|
111
|
+
test_files:
|
112
|
+
- test/test.rb
|