webtranslateit-version_fu 1.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4871354c79d2e70b5f2730b4017bf48246025e650cb267f3114c31f732bc7a3d
4
+ data.tar.gz: a56e7c8a82be42f777c88bff3e9a18ff01005f8d539b05101f94242d06e99bb1
5
+ SHA512:
6
+ metadata.gz: 1deea4674b48d01e206ce24dcdfc70e95d707a90d1b0f6d6000f4726a17a0dce0546a140879a22dd7c2a33eb469a6410fe98c03e62a2708ee724b9b8d6a99da9
7
+ data.tar.gz: 51d15ca7c3090a5ce123e6f6dfa40020188c67a9dff77066797efea08b0a9e20a412954472e5297cae92161d80f4f68c5a90f84a551f76b3d92f98b3e9de5289
data/MIT-LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ == version_fu
2
+ Copyright (c) 2008-9 Jordan McKible
3
+
4
+ == acts_as_versioned
5
+ Copyright (c) 2005 Rick Olson
6
+ ====================================================================
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
9
+ this software and associated documentation files (the "Software"), to deal in
10
+ the Software without restriction, including without limitation the rights to
11
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12
+ of the Software, and to permit persons to whom the Software is furnished to do
13
+ so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # version_fu
2
+
3
+ [![Ruby](https://github.com/webtranslateit/version_fu/actions/workflows/ci.yml/badge.svg)](https://github.com/webtranslateit/version_fu/actions/workflows/ci.yml)
4
+
5
+ version_fu is a ActiveRecord versioning plugin that that is based on the dirty attribute checking introduced in Rails 2.1.
6
+
7
+ ## Installation
8
+
9
+ Add below to your Gemfile
10
+
11
+ `gem 'version_fu'`
12
+
13
+ ## Usage
14
+
15
+ Let's say I have a pages table:
16
+
17
+ ```ruby
18
+ class Page < ActiveRecord::Base
19
+ # attributes: id, type, title, body, created_at, updated_at, creator_id, author_id
20
+ end
21
+ ```
22
+
23
+ I want to track any changes made. First step will be to make a new page_versions table:
24
+
25
+ ```ruby
26
+ class CreatePageVersions < ActiveRecord::Migration
27
+ def self.up
28
+ create_table :page_versions do |t|
29
+ t.integer :page_id, :version, :author_id
30
+ t.string :title
31
+ t.text :body
32
+ t.timestamps
33
+ end
34
+ end
35
+
36
+ def self.down
37
+ drop_table :page_versions
38
+ end
39
+ end
40
+ ```
41
+
42
+ In this case, the author_id column represents the last person to edit the page. We want to track this attribute with every version. However, the creator_id is the person who created the page. The will never change, so it's not part of the versioned table.
43
+
44
+ Don't forget to add a version column to your pages table. Have it default to 1 just to be safe (although the plugin should account for this):
45
+
46
+ ```ruby
47
+ class AddVersionToPages < ActiveRecord::Migration
48
+ def self.up
49
+ add_column :pages, :version, :integer, :default=>1
50
+ end
51
+ def self.down
52
+ remove_column :pages, :version
53
+ end
54
+ end
55
+ ```
56
+
57
+ Of course if you're adding this plugin to a table with existing data, you'll probably want to instantiate some initial versions to start with.
58
+
59
+ Alright, so now that the database tables are in place, we can fire up version_fu. It's quite simple:
60
+
61
+ ```
62
+ class Page < ActiveRecord::Base
63
+ version_fu
64
+ end
65
+ ```
66
+
67
+ That's it.
68
+
69
+
70
+ ## Configuration
71
+
72
+ You can pass a few configuration options if need be. If you stick with the defaults above, you can skip all this.
73
+
74
+ ```ruby
75
+ class Page < ActiveRecord::Base
76
+ version_fu :class_name=>'Version', :foreign_key=>'page_id', :table_name=>'page_versions', :version_column=>'version'
77
+ end
78
+ ```
79
+
80
+ * :class_name - The name of the versioned class. It will be a submodule of the versioning class - e.g. Page::Version
81
+
82
+ * :foreign_key - The column in the versioned table associated with the versioning class
83
+
84
+ * :table_name - The name of the versioned table
85
+
86
+ * :version_column - The name of the version column
87
+
88
+
89
+ ## Extensions
90
+
91
+ Now that you've got some versions, it would be nice to use ActiveRecord associations on it. For example, Page.first.versions.latest.author wouldn't currently work because the Page::Version class doesn't know about the author method. The version_fu call does all you to pass a block which is executed by the versioned class. There is just one gotcha for associations:
92
+
93
+ ```ruby
94
+ class Page < ActiveRecord::Base
95
+ version_fu do
96
+ belongs_to :author, :class_name=>'::Author'
97
+ end
98
+ end
99
+ ```
100
+
101
+ Don't forget the class name, or you'll get a warning
102
+
103
+ ## When to Version
104
+
105
+ By default a new version will be saved whenever a versioned column is changed. However, you can control this at a more fine grained level. Just override the create_new_version? method. For example, let's say you only want to save a new version if both the page title and body changed. Taking advantage of the dirty attribute methods, you could do something like this:
106
+
107
+ ```ruby
108
+ class Page < ActiveRecord::Base
109
+ version_fu do
110
+ belongs_to :author, :class_name=>'::Author'
111
+ end
112
+ def create_new_version?
113
+ title_changed? && body_changed?
114
+ end
115
+ end
116
+ ```
117
+
118
+ ## Author
119
+
120
+ * version_fu was created by Jordan McKible http://jordan.mckible.com
121
+
122
+ * Available on GitHub at http://github.com/jmckible/version_fu
123
+
124
+ * Available on RubyGems.org at http://rubygems.org/gems/version_fu
125
+
126
+ * acts_as_versioned by Rick Olson http://github.com/technoweenie/acts_as_versioned/tree/master
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+ require 'rubygems'
5
+ require 'bundler/gem_tasks'
6
+ require 'rspec/core/rake_task'
7
+ require 'rubocop/rake_task'
8
+
9
+ task default: %i[spec rubocop]
10
+ RSpec::Core::RakeTask.new
11
+
12
+ desc 'Run RuboCop checks'
13
+ RuboCop::RakeTask.new
14
+
15
+ desc 'Default: run unit tests.'
16
+ task default: :test
17
+
18
+ desc 'Test the version_fu plugin.'
19
+ Rake::TestTask.new(:test) do |t|
20
+ t.libs << 'lib'
21
+ t.libs << 'test'
22
+ t.libs << 'test/models'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = true
25
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'version_fu'
2
+ ActiveRecord::Base.class_eval { include VersionFu }
@@ -0,0 +1,3 @@
1
+ module Version_fu
2
+ VERSION = '1.1.0'.freeze
3
+ end
@@ -0,0 +1,112 @@
1
+ module VersionFu
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+ end
5
+
6
+ module ClassMethods
7
+ def version_fu(options = {}, &block)
8
+ return if included_modules.include? VersionFu::InstanceMethods
9
+
10
+ __send__ :include, VersionFu::InstanceMethods
11
+
12
+ cattr_accessor :versioned_class_name, :versioned_foreign_key, :versioned_table_name,
13
+ :version_column, :versioned_columns
14
+
15
+ self.versioned_class_name = options[:class_name] || 'Version'
16
+ self.versioned_foreign_key = options[:foreign_key] || to_s.foreign_key
17
+ self.versioned_table_name = options[:table_name] || "#{table_name_prefix}#{base_class.name.demodulize.underscore}_versions#{table_name_suffix}"
18
+ self.version_column = options[:version_column] || 'version'
19
+
20
+ # Setup versions association
21
+ class_eval do
22
+ has_many :versions, class_name: "#{self}::#{versioned_class_name}",
23
+ foreign_key: versioned_foreign_key,
24
+ dependent: :destroy do
25
+ def latest
26
+ order(version: :desc).first
27
+ end
28
+ end
29
+
30
+ before_save :check_for_new_version
31
+ end
32
+
33
+ # Versioned Model
34
+ const_set(versioned_class_name, Class.new(ActiveRecord::Base)).class_eval do
35
+ # find first version before the given version
36
+ def self.before(version)
37
+ where("#{original_class.versioned_foreign_key} = ? and version < ?",
38
+ version.send(original_class.versioned_foreign_key), version.version)
39
+ .order(version: :desc).first
40
+ end
41
+
42
+ # find first version after the given version.
43
+ def self.after(version)
44
+ where("#{original_class.versioned_foreign_key} = ? and version > ?",
45
+ version.send(original_class.versioned_foreign_key), version.version)
46
+ .order(version: :asc).first
47
+ end
48
+
49
+ def previous
50
+ self.class.before(self)
51
+ end
52
+
53
+ def next
54
+ self.class.after(self)
55
+ end
56
+ end
57
+
58
+ # Housekeeping on versioned class
59
+ versioned_class.cattr_accessor :original_class
60
+ versioned_class.original_class = self
61
+ versioned_class.table_name = versioned_table_name
62
+
63
+ # Version parent association
64
+ versioned_class.belongs_to to_s.demodulize.underscore.to_sym,
65
+ class_name: "::#{self}",
66
+ foreign_key: versioned_foreign_key
67
+
68
+ # Block extension
69
+ versioned_class.class_eval(&block) if block_given?
70
+
71
+ if versioned_class.table_exists?
72
+ # Finally setup which columns to version
73
+ self.versioned_columns = versioned_class.new.attributes.keys -
74
+ [versioned_class.primary_key, versioned_foreign_key, version_column, 'created_at',
75
+ 'updated_at']
76
+ else
77
+ ActiveRecord::Base.logger.warn 'Version Table not found'
78
+ end
79
+ end
80
+
81
+ def versioned_class
82
+ const_get versioned_class_name
83
+ end
84
+ end
85
+
86
+ module InstanceMethods
87
+ def find_version(number)
88
+ versions.find_by_version(number)
89
+ end
90
+
91
+ def check_for_new_version
92
+ instantiate_revision if create_new_version?
93
+ true # Never halt save
94
+ end
95
+
96
+ # This the method to override if you want to have more control over when to version
97
+ def create_new_version?
98
+ # Any versioned column changed?
99
+ self.class.versioned_columns.detect { |a| __send__ "#{a}_changed?" }
100
+ end
101
+
102
+ def instantiate_revision
103
+ new_version = versions.build
104
+ versioned_columns.each do |attribute|
105
+ new_version.__send__ "#{attribute}=", __send__(attribute)
106
+ end
107
+ version_number = new_record? ? 1 : version + 1
108
+ new_version.version = version_number
109
+ self.version = version_number
110
+ end
111
+ end
112
+ end
data/lib/version_fu.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'active_record'
2
+ require 'version_fu/version_fu'
3
+ ActiveRecord::Base.class_eval { include VersionFu }
metadata ADDED
@@ -0,0 +1,238 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: webtranslateit-version_fu
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jordan McKible
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rails-observers
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.1.2
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.1.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: factory_girl
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: factory_girl_rails
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: guard-rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: guard-rubocop
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: mocha
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rails
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '4.0'
124
+ - - "<"
125
+ - !ruby/object:Gem::Version
126
+ version: '5.2'
127
+ type: :development
128
+ prerelease: false
129
+ version_requirements: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '4.0'
134
+ - - "<"
135
+ - !ruby/object:Gem::Version
136
+ version: '5.2'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rspec
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ - !ruby/object:Gem::Dependency
152
+ name: rspec-rails
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '3.5'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '3.5'
165
+ - !ruby/object:Gem::Dependency
166
+ name: rubocop
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ - !ruby/object:Gem::Dependency
180
+ name: sqlite3
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ description: version_fu helps version your ActiveRecord models. It is based on Rick
194
+ Olson's acts_as_versioned and is compatible with Rails 3.
195
+ email: ''
196
+ executables: []
197
+ extensions: []
198
+ extra_rdoc_files: []
199
+ files:
200
+ - MIT-LICENSE
201
+ - README.md
202
+ - Rakefile
203
+ - init.rb
204
+ - lib/version_fu.rb
205
+ - lib/version_fu/version.rb
206
+ - lib/version_fu/version_fu.rb
207
+ homepage:
208
+ licenses:
209
+ - MIT
210
+ metadata:
211
+ rubygems_mfa_required: 'true'
212
+ homepage: https://github.com/webtranslateit/version_fu
213
+ changelog_uri: https://github.com/webtranslateit/webtranslateit/blob/master/history.md
214
+ documentation_uri: https://github.com/webtranslateit/webtranslateit#readme
215
+ homepage_uri: https://webtranslateit.com
216
+ source_code_uri: https://github.com/webtranslateit/webtranslateit
217
+ wiki_uri: https://github.com/webtranslateit/webtranslateit/wiki
218
+ post_install_message:
219
+ rdoc_options:
220
+ - "--charset=UTF-8"
221
+ require_paths:
222
+ - lib
223
+ required_ruby_version: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - ">="
226
+ - !ruby/object:Gem::Version
227
+ version: '0'
228
+ required_rubygems_version: !ruby/object:Gem::Requirement
229
+ requirements:
230
+ - - ">="
231
+ - !ruby/object:Gem::Version
232
+ version: '0'
233
+ requirements: []
234
+ rubygems_version: 3.1.6
235
+ signing_key:
236
+ specification_version: 4
237
+ summary: Gemified version of the version_fu plugin.
238
+ test_files: []