historyable 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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NWE3OTczNmRmZmQxY2RhMzc0OTk1MTJlY2JjMGUwY2E1YjlkMTJkNQ==
5
+ data.tar.gz: !binary |-
6
+ OTZhYWFhOWQwZGIzNGNhNWMwNTlhM2U4OTJlNWY3YjM5OGUwMmU4NA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YjUyZTBiZDRhMmRmYmVhZmYyOTU4ZjBjMGU5MDc1ODZhOTUwZjE3ZWIxY2Vm
10
+ ZDM5MGE5ZDhmOGIwZWY3OTY1MDUzZDM3YWQ4MzBlY2NiYzE3YWQ3YzkwZTMw
11
+ ZjJlMzNjOGNhMTQwNTM3OWU1YThhMmM2MmQ0YTYwNTYyNzJjY2M=
12
+ data.tar.gz: !binary |-
13
+ MWI1YzFmZmZiODZkNzg4ZDU2ZTRlM2RlN2NjYjk0YzY0NmI0NDc1M2Y5ZWEy
14
+ ZDU4MTRhZDZjMmNmMzEzZDJmNmUyYTU5NjllOWI4MDA3YzQ5Y2NkYmQ3NTUw
15
+ NThhYTczM2FiOWFmNjY3YWE3MTc2MzYxNmRjMmVlMTlmNTU5YWI=
checksums.yaml.gz.sig ADDED
Binary file
@@ -0,0 +1,2 @@
1
+ Description:
2
+ The historyable:install generator generates a migration creating a `changes` table in your database.
@@ -0,0 +1,24 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module Historyable
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ # Implement the required interface for Rails::Generators::Migration.
11
+ def self.next_migration_number(dirname)
12
+ if ActiveRecord::Base.timestamped_migrations
13
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
14
+ else
15
+ "%.3d" % (current_migration_number(dirname) + 1)
16
+ end
17
+ end
18
+
19
+ def create_migration_file
20
+ migration_template 'migration.rb', 'db/migrate/create_changes.rb'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ class CreateChanges < ActiveRecord::Migration
2
+ def up
3
+ create_table :changes do |t|
4
+ t.references :item, polymorphic: true
5
+ t.string :object_attribute
6
+ t.text :object_attribute_value
7
+ t.datetime :created_at
8
+ end
9
+
10
+ add_index :changes, [:item_type, :item_id]
11
+ end
12
+
13
+ def down
14
+ drop_table :changes
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ class Change < ActiveRecord::Base
2
+ belongs_to :historyable, polymorphic: true
3
+ serialize :object_attribute_value
4
+ end
@@ -0,0 +1,3 @@
1
+ module Historyable
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,102 @@
1
+ require "historyable/version"
2
+
3
+ require "active_record"
4
+ require "historyable/change"
5
+
6
+ module Historyable
7
+ class Item < Struct.new(:attribute, :association_name); end
8
+
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ class_attribute :historyable_items, instance_writer: false
13
+ end
14
+
15
+
16
+ module ClassMethods
17
+
18
+ # @param attributes [Array, Symbol]
19
+ def has_history(*attributes)
20
+ self.historyable_items = attributes.map do |attribute|
21
+ attribute = attribute.to_sym
22
+ association_name = attribute.to_s.insert(-1, '_changes').to_sym
23
+
24
+ Historyable::Item.new(attribute, association_name)
25
+ end
26
+
27
+ # Associations
28
+ historyable_items.each do |historyable|
29
+ has_many historyable.association_name,
30
+ as: :item,
31
+ class_name: '::Change',
32
+ dependent: :destroy
33
+ end
34
+
35
+
36
+ # Instance methods
37
+ historyable_items.each do |historyable|
38
+
39
+ # raw_attribute_history
40
+ #
41
+ # @return [ActiveRecord::Relation]
42
+ define_method("raw_#{historyable.attribute.to_s}_history") do
43
+ send(historyable.association_name)
44
+ .where(object_attribute: historyable.attribute)
45
+ .order('created_at DESC')
46
+ .select(:object_attribute_value, :created_at)
47
+ end
48
+
49
+
50
+ # attribute_history
51
+ #
52
+ # @return [Array]
53
+ define_method("#{historyable.attribute.to_s}_history") do
54
+ unless instance_variable_get("@#{historyable.attribute.to_s}_history".to_sym)
55
+ array = []
56
+
57
+ records = send("raw_#{historyable.attribute}_history")
58
+ .pluck(:object_attribute_value, :created_at)
59
+ records.map do |attribute_value, created_at|
60
+ hash = HashWithIndifferentAccess.new
61
+ hash[:attribute_value] = attribute_value
62
+ hash[:changed_at] = created_at
63
+
64
+ array << hash
65
+ end
66
+
67
+ # Sets attribute_history cache
68
+ instance_variable_set("@#{historyable.attribute.to_s}_history".to_sym, array)
69
+ array
70
+ else
71
+ instance_variable_get("@#{historyable.attribute.to_s}_history".to_sym)
72
+ end
73
+ end
74
+ end
75
+
76
+
77
+ # Callbacks
78
+ around_save :save_changes
79
+ end
80
+ end
81
+
82
+
83
+ private
84
+
85
+ # Creates a Change record when an attribute marked as 'historyable' changes
86
+ def save_changes
87
+ changed_historyable_items = historyable_items.select do |historyable|
88
+ changed.include?(historyable.attribute.to_s)
89
+ end
90
+
91
+ yield # saves the records
92
+
93
+ changed_historyable_items.each do |historyable|
94
+ send(historyable.association_name).create(object_attribute: historyable.attribute,
95
+ object_attribute_value: send(historyable.attribute))
96
+ # Expires attribute_history cache
97
+ instance_variable_set("@#{historyable.attribute.to_s}_history".to_sym, nil)
98
+ end
99
+
100
+ true
101
+ end
102
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: historyable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Philippe Dionne
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - !binary |-
12
+ LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURmRENDQW1TZ0F3SUJB
13
+ Z0lCQVRBTkJna3Foa2lHOXcwQkFRVUZBREJDTVJRd0VnWURWUVFEREF0a2FX
14
+ OXUKYm1VdWNHaHBiREVWTUJNR0NnbVNKb21UOGl4a0FSa1dCV2R0WVdsc01S
15
+ TXdFUVlLQ1pJbWlaUHlMR1FCR1JZRApZMjl0TUI0WERURXpNRE13T1RFek1q
16
+ TXpOVm9YRFRFME1ETXdPVEV6TWpNek5Wb3dRakVVTUJJR0ExVUVBd3dMClpH
17
+ bHZibTVsTG5Cb2FXd3hGVEFUQmdvSmtpYUprL0lzWkFFWkZnVm5iV0ZwYkRF
18
+ VE1CRUdDZ21TSm9tVDhpeGsKQVJrV0EyTnZiVENDQVNJd0RRWUpLb1pJaHZj
19
+ TkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMdEdLMk5vRnlWWApzZUtsZkhi
20
+ OG51aEJ5OHJ3MW5QM0pWSFdveXFhbExzMHQzYXhVV2U2c0RDZ1FYQU9MM0Z0
21
+ a2ZZUFlseVg2WDRzCkZnZ2NTeVNVdDBQdkdkYXMweW0vbFcrc2ZHVDZnWERC
22
+ S2JQdmtXRk50cFhhSUo4RkxocW5KUjJtNTdiOFI2cGYKVk1CRGthOTVOODBY
23
+ dTlOUXJBZXNGK3dXL2M2WmlBT04yVkRzV2FiWkVmajE0Nnk3WnZ2aUI3cFpI
24
+ bFB6bkk0VwpHVmZPazBNQ2wwUTYwSnlrN1d3TmVjK05BOXJHN3ZFL2RXZEdP
25
+ S2Z4VTZaSm5DNmRyQzNrQnNCS2tSWnMrR1JoCjZYb0NBc3JLYlJ3Yi9aSTNB
26
+ MVMvSjl5dnEvTlExQi9VM0Npc0JGaHQrQ2Jkc3BlWFZVRHg1ZGZmRFZ4bnhk
27
+ by8KdzJSM3dKTXZEMk1DQXdFQUFhTjlNSHN3Q1FZRFZSMFRCQUl3QURBTEJn
28
+ TlZIUThFQkFNQ0JMQXdIUVlEVlIwTwpCQllFRkErNjlkR3h2RnRMeEorYUg4
29
+ bDRVTzl5eTg1M01DQUdBMVVkRVFRWk1CZUJGV1JwYjI1dVpTNXdhR2xzClFH
30
+ ZHRZV2xzTG1OdmJUQWdCZ05WSFJJRUdUQVhnUlZrYVc5dWJtVXVjR2hwYkVC
31
+ bmJXRnBiQzVqYjIwd0RRWUoKS29aSWh2Y05BUUVGQlFBRGdnRUJBRDdWcHV5
32
+ bTBWdm5YT3lkb0NCa3Yvdzh1MzJOamlndDNiRjNpL1A5MTEwOAphRHZPUlV5
33
+ bVlyUHhhQmUrQXNTSlVrSkIwTUh5d0pkTWM0TUYzWUlTZWxDdlVGR3phOExZ
34
+ dnZVSWd5VktGb20rClROOFdDUFpMbzRtWWFZbzRzU3RrRi9HNXY4STNydVpP
35
+ YnI3by9mMjB4RzVyOEU0TkQyR0VHVGVGSmhncE1jSE8KSXIxdVluL0xMZUdH
36
+ NWcyRUFLQ2RZeTJYb29odGNTUFlBcGJlRlFnV09HS29pb1FWUkNERzNjSG1h
37
+ a2ZWQVY1TQpEdU5senZqaFd0UER3RTVtWU81eDVYcXVXUXVFTnc3OHVydDFh
38
+ aW9OckllMC8xNWRIcERvSUVESUxhNnpVNDZCClhEdHAxWXhkZVZHSUJ1Tm9Q
39
+ MXZqRFN2TktZajBwTWpSQUVQcnFLMzlqS0U9Ci0tLS0tRU5EIENFUlRJRklD
40
+ QVRFLS0tLS0K
41
+ date: 2013-08-21 00:00:00.000000000 Z
42
+ dependencies:
43
+ - !ruby/object:Gem::Dependency
44
+ prerelease: false
45
+ name: active_record
46
+ version_requirements: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: 3.0.0
51
+ requirement: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: 3.0.0
56
+ type: :runtime
57
+ description: Tracks model attributes changes.
58
+ email:
59
+ - philippe.dionne@hooktstudios.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - lib/generators/historyable/USAGE
65
+ - lib/generators/historyable/install_generator.rb
66
+ - lib/generators/historyable/templates/migration.rb
67
+ - lib/historyable.rb
68
+ - lib/historyable/change.rb
69
+ - lib/historyable/version.rb
70
+ homepage: https://github.com/hooktstudios/historyable
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project: ! '[none]'
90
+ rubygems_version: 2.0.3
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Tracks model attributes changes.
94
+ test_files: []
95
+ has_rdoc:
metadata.gz.sig ADDED
Binary file