trackit 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/MIT-LICENSE +20 -0
- data/README.md +128 -0
- data/Rakefile +27 -0
- data/lib/generators/track_it/USAGE +10 -0
- data/lib/generators/track_it/templates/migration.rb +10 -0
- data/lib/generators/track_it/track_it_generator.rb +33 -0
- data/lib/trackit/track_attributes.rb +36 -0
- data/lib/trackit/version.rb +3 -0
- data/lib/trackit/wrapper.rb +62 -0
- data/lib/trackit.rb +5 -0
- metadata +132 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
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.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
TrackIt
|
2
|
+
=======
|
3
|
+
|
4
|
+
TrackIt is a small gem which helps you keep track of changes in you ActiveRecord models persistently.
|
5
|
+
While ActiveModel::Dirty allows you to keep track on changes only when the change occurs, TrackIt will keep attributes as changed until you decide to clear them.
|
6
|
+
|
7
|
+
Getting Started
|
8
|
+
===============
|
9
|
+
|
10
|
+
First you will have to add TrackIt to your gemfile.
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'trackit'
|
14
|
+
```
|
15
|
+
|
16
|
+
Run the `bundle install` command in order to install the gem.
|
17
|
+
|
18
|
+
After the gem was successfully installed you need to run the generator:
|
19
|
+
|
20
|
+
```console
|
21
|
+
rails generate track_it Model attr_a attr_b
|
22
|
+
```
|
23
|
+
|
24
|
+
This will generate tracking for Model class which inherits from ActiveRecord::Base, and only for attributes attr_a, attr_b.
|
25
|
+
|
26
|
+
The last step is migrating your database:
|
27
|
+
|
28
|
+
```console
|
29
|
+
rake db:migrate
|
30
|
+
```
|
31
|
+
|
32
|
+
You may need to restart your app if it is already running.
|
33
|
+
|
34
|
+
Usage
|
35
|
+
=====
|
36
|
+
|
37
|
+
TrackIt provides an interface on your model instance as follows:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
model = Model.new
|
41
|
+
|
42
|
+
model.tracked.changed?
|
43
|
+
model.tracked.changed
|
44
|
+
model.tracked.attr_a_changed?
|
45
|
+
model.tracked.attr_b_changed?
|
46
|
+
.
|
47
|
+
.
|
48
|
+
.
|
49
|
+
```
|
50
|
+
|
51
|
+
Each method corresponds to its similiar named method under [ActiveModel::Dirty](http://api.rubyonrails.org/classes/ActiveModel/Dirty.html).
|
52
|
+
|
53
|
+
Two auxiliary methods are supplied:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
model.tracked.set_all_changed
|
57
|
+
model.tracked.set_all_unchanged
|
58
|
+
```
|
59
|
+
|
60
|
+
Which sets all tracked attributes to changed/unchaged states.
|
61
|
+
|
62
|
+
Concrete Example
|
63
|
+
================
|
64
|
+
Assume you have a User model which has the following attributes: name, address, current_job
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
class User < ActiveRecord::Base
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
And you want to keep track on all those users who changed their current jobs or addresses:
|
72
|
+
|
73
|
+
```console
|
74
|
+
rails generate track_it User address current_job
|
75
|
+
```
|
76
|
+
|
77
|
+
And
|
78
|
+
|
79
|
+
```console
|
80
|
+
rake db:migrate
|
81
|
+
```
|
82
|
+
|
83
|
+
Let's take a look at the effects of our change:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
u = User.create!(:name => "user1", :adderss => "address1", :current_job => "job1")
|
87
|
+
|
88
|
+
u.address = "address2"
|
89
|
+
u.current_job = "job2"
|
90
|
+
|
91
|
+
u.current_job_changed? # => true
|
92
|
+
u.address_changed? # => true
|
93
|
+
u.changed? # => true
|
94
|
+
u.changed # => ['address', 'current_job']
|
95
|
+
|
96
|
+
u.tracked.current_job_changed? # => false
|
97
|
+
u.tracked.address_changed? # => false
|
98
|
+
u.tracked.changed? # => false
|
99
|
+
u.tracked.changed # => []
|
100
|
+
|
101
|
+
u.save!
|
102
|
+
|
103
|
+
u.current_job_changed? # => false
|
104
|
+
u.address_changed? # => false
|
105
|
+
u.changed? # => false
|
106
|
+
u.changed # => []
|
107
|
+
|
108
|
+
|
109
|
+
u.tracked.current_job_changed? # => true
|
110
|
+
u.tracked.address_changed? # => true
|
111
|
+
u.tracked.changed? # => true
|
112
|
+
u.tracked.changed # => ['address', 'current_job']
|
113
|
+
|
114
|
+
u.tracked.set_unchanged(:current_job)
|
115
|
+
u.tracked.current_job_changed? # => false
|
116
|
+
|
117
|
+
u.tracked.set_changed(:current_job)
|
118
|
+
u.tracked.current_job_changed? # => true
|
119
|
+
|
120
|
+
u.tracked.set_all_unchanged
|
121
|
+
u.tracked.changed? # => false
|
122
|
+
u.tracked.changed # => []
|
123
|
+
|
124
|
+
u.tracked.set_all_changed
|
125
|
+
u.tracked.changed? # => true
|
126
|
+
u.tracked.changed # => ['address', 'current_job'] # note name is not changed - only tracked attributes get changed.
|
127
|
+
|
128
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'TrackeIt'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Description:
|
2
|
+
Generates tracked attributes for Model and attributes attr_a attr_b
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate track_it Model attr_a attr_b
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
/db/migrate/add_tracked_attributes_to_models.rb
|
9
|
+
And Inject:
|
10
|
+
track_attributes :attr_a, :attr_b into /app/models/model.rb
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class AddTrackedAttributesTo<%= name.camelize.pluralize %> < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
add_column :<%= table_name %>, :tracked_attributes, :integer, :default => 0, :null => false
|
4
|
+
end
|
5
|
+
|
6
|
+
def down
|
7
|
+
remove_column :<%= table_name %>, :tracked_attributes
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
module TrackIt
|
5
|
+
module Generators
|
6
|
+
class TrackItGenerator < ActiveRecord::Generators::Base
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
argument :attrs, :type => :array, :default => []
|
9
|
+
|
10
|
+
def generate_track_attributes_call_on_model_file
|
11
|
+
inject_into_class model_file_path, model_class, model_content
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_attributes_tracker_migration
|
15
|
+
migration_template "migration.rb", "db/migrate/add_tracked_attributes_to_#{table_name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def model_file_path
|
21
|
+
File.join("app", "models", "#{name.underscore}.rb")
|
22
|
+
end
|
23
|
+
|
24
|
+
def model_class
|
25
|
+
name.camelize.constantize
|
26
|
+
end
|
27
|
+
|
28
|
+
def model_content
|
29
|
+
" track_attributes #{attrs.map {|a| ":#{a}"}.join(", ")}\n"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module TrackIt
|
2
|
+
module TrackAttributes
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def track_attributes(*attrs)
|
10
|
+
self.class_eval do
|
11
|
+
before_save :update_tracked_attributes
|
12
|
+
@tracked_attributes = attrs.flatten
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def tracked_attributes
|
17
|
+
@tracked_attributes ||= []
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_tracked_attributes
|
22
|
+
changed_attrs = self.changes.keys.map(&:to_sym)
|
23
|
+
changed_tracked_attributes = self.class.tracked_attributes.select {|k| changed_attrs.include?(k)}
|
24
|
+
changed_tracked_attributes.each do |attr|
|
25
|
+
self.tracked.set_changed(attr)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def tracked
|
30
|
+
@tracked ||= TrackIt::Wrapper.new(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
ActiveRecord::Base.send :include, TrackIt::TrackAttributes
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module TrackIt
|
2
|
+
|
3
|
+
class Wrapper
|
4
|
+
include ActiveModel::AttributeMethods
|
5
|
+
attribute_method_suffix '_changed?'
|
6
|
+
attr_reader :model
|
7
|
+
|
8
|
+
def initialize(model)
|
9
|
+
@model = model
|
10
|
+
end
|
11
|
+
|
12
|
+
def changed?
|
13
|
+
model.tracked_attributes != 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def changed
|
17
|
+
changed = []
|
18
|
+
bits_num = tracked_attributes.size
|
19
|
+
(bits_num-1).downto(0) do |i|
|
20
|
+
changed << tracked_attributes[i] if model.tracked_attributes[i] == 1
|
21
|
+
end
|
22
|
+
changed
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_changed(attr)
|
26
|
+
@model.tracked_attributes |= 2 ** tracked_attributes.index(attr)
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_unchanged(attr)
|
30
|
+
@model.tracked_attributes &= ~(2 ** tracked_attributes.index(attr))
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_all_unchanged
|
34
|
+
@model.tracked_attributes = 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_all_changed
|
38
|
+
@model.tracked_attributes |= (~0)
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def attributes
|
45
|
+
model.attributes.slice(*tracked_attributes.map(&:to_s))
|
46
|
+
end
|
47
|
+
|
48
|
+
def model_class
|
49
|
+
model.class
|
50
|
+
end
|
51
|
+
|
52
|
+
def tracked_attributes
|
53
|
+
@tracked_attributes ||= model.class.tracked_attributes
|
54
|
+
end
|
55
|
+
|
56
|
+
def attribute_changed?(attr)
|
57
|
+
model.tracked_attributes[tracked_attributes.index(attr.to_sym)] == 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
end
|
data/lib/trackit.rb
ADDED
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: trackit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Erez Rabih
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-21 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: &2169451920 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.6
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2169451920
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: sqlite3
|
27
|
+
requirement: &2169451500 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2169451500
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec-rails
|
38
|
+
requirement: &2169451040 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2169451040
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: guard-rspec
|
49
|
+
requirement: &2169450620 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2169450620
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: guard-spork
|
60
|
+
requirement: &2169450200 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2169450200
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: growl
|
71
|
+
requirement: &2169449780 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2169449780
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: debugger
|
82
|
+
requirement: &2169449360 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *2169449360
|
91
|
+
description: TrackIt allows you to track attributes changes in your ActiveRecord models
|
92
|
+
email:
|
93
|
+
- erez.rabih@gmail.com
|
94
|
+
executables: []
|
95
|
+
extensions: []
|
96
|
+
extra_rdoc_files: []
|
97
|
+
files:
|
98
|
+
- lib/generators/track_it/templates/migration.rb
|
99
|
+
- lib/generators/track_it/track_it_generator.rb
|
100
|
+
- lib/generators/track_it/USAGE
|
101
|
+
- lib/trackit/track_attributes.rb
|
102
|
+
- lib/trackit/version.rb
|
103
|
+
- lib/trackit/wrapper.rb
|
104
|
+
- lib/trackit.rb
|
105
|
+
- MIT-LICENSE
|
106
|
+
- Rakefile
|
107
|
+
- README.md
|
108
|
+
homepage: https://github.com/erez-rabih/tracker
|
109
|
+
licenses: []
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 1.7.2
|
129
|
+
signing_key:
|
130
|
+
specification_version: 3
|
131
|
+
summary: TrackIt allows you to track attributes changes in your ActiveRecord models
|
132
|
+
test_files: []
|