moribus 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 +15 -0
- data/.gitignore +35 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +42 -0
- data/.travis.yml +8 -0
- data/Gemfile +19 -0
- data/LICENSE +20 -0
- data/README.md +104 -0
- data/Rakefile +15 -0
- data/lib/colorized_text.rb +33 -0
- data/lib/moribus.rb +133 -0
- data/lib/moribus/aggregated_behavior.rb +80 -0
- data/lib/moribus/aggregated_cache_behavior.rb +76 -0
- data/lib/moribus/alias_association.rb +106 -0
- data/lib/moribus/extensions.rb +37 -0
- data/lib/moribus/extensions/delegate_associated.rb +48 -0
- data/lib/moribus/extensions/has_aggregated_extension.rb +94 -0
- data/lib/moribus/extensions/has_current_extension.rb +17 -0
- data/lib/moribus/macros.rb +120 -0
- data/lib/moribus/tracked_behavior.rb +91 -0
- data/lib/moribus/version.rb +3 -0
- data/moribus.gemspec +33 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +61 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/moribus/alias_association_spec.rb +88 -0
- data/spec/moribus/macros_spec.rb +7 -0
- data/spec/moribus_spec.rb +332 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/moribus_spec_model.rb +57 -0
- metadata +209 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZDcwN2E3NWU5NjI0MDk4OTU1NWE4OGVlYjEwZmViNmRkZTkzMDZjNQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGM1MjU5YzVmMzA0YzViZWNlNDBkZWNjYjljNTQ1YWNlOGNkODkzOA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YjRmMTY0MWJiNjcwNjU0ZDI3OGIyNDk4ZDQ3ZTVkNmY5YTJjNzU0NTE3NWI0
|
10
|
+
NzFmNWM3MWQ3YmNkNzliZmUzZWMzNjg2ZWQzOGNlN2FlMDA4NzJiNWYwMDAy
|
11
|
+
OTg1OWNhYmUwNTA2NDNmZjJiYzM0NGUwODk2OTZiMGIyM2FkMGQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YWQ4MmRjYzBkZGE4MWVlNmExNmJiNDk3ZjFjY2Y2OGZlMTZmOGRmMmRiOTll
|
14
|
+
Yjk1YzFkNjA1OGIxMTJjNTRmMTYyZWQ4ZWRlMTg2ZWQzODQ5ZWFhZDhlNWQ3
|
15
|
+
MDNmOGVkZTYwZjE4OGQ4ZjI4MGQxNDk1ZThkYjIzODhhMTliM2U=
|
data/.gitignore
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# simplecov generated
|
2
|
+
coverage
|
3
|
+
coverage.data
|
4
|
+
!coverage/.resultset.json
|
5
|
+
|
6
|
+
# rdoc generated
|
7
|
+
rdoc
|
8
|
+
|
9
|
+
# yard generated
|
10
|
+
doc
|
11
|
+
.yardoc
|
12
|
+
|
13
|
+
# bundler
|
14
|
+
.bundle
|
15
|
+
|
16
|
+
# jeweler generated
|
17
|
+
pkg
|
18
|
+
|
19
|
+
*.gem
|
20
|
+
Gemfile.lock
|
21
|
+
|
22
|
+
# IDE generated
|
23
|
+
.idea
|
24
|
+
|
25
|
+
log/*.log
|
26
|
+
spec/dummy/log/*.log
|
27
|
+
|
28
|
+
# exclude everything in tmp
|
29
|
+
tmp/*
|
30
|
+
# except the metric_fu directory
|
31
|
+
!tmp/metric_fu/
|
32
|
+
# but exclude everything *in* the metric_fu directory
|
33
|
+
tmp/metric_fu/*
|
34
|
+
# except for the _data directory to track metrical outputs
|
35
|
+
!tmp/metric_fu/_data/
|
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
moribus
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3
|
data/.simplecov
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "simplecov-rcov-text"
|
2
|
+
require "colorized_text"
|
3
|
+
include ColorizedText
|
4
|
+
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
6
|
+
SimpleCov::Formatter::RcovTextFormatter,
|
7
|
+
SimpleCov::Formatter::HTMLFormatter
|
8
|
+
]
|
9
|
+
SimpleCov.start do
|
10
|
+
add_filter "/spec/"
|
11
|
+
|
12
|
+
# Fail the build when coverage is weak:
|
13
|
+
at_exit do
|
14
|
+
SimpleCov.result.format!
|
15
|
+
threshold, actual = 98.475, SimpleCov.result.covered_percent
|
16
|
+
if actual < threshold
|
17
|
+
msg = "\nLow coverage: "
|
18
|
+
msg << red("#{actual}%")
|
19
|
+
msg << " is #{red 'under'} the threshold: "
|
20
|
+
msg << green("#{threshold}%.")
|
21
|
+
msg << "\n"
|
22
|
+
$stderr.puts msg
|
23
|
+
exit 1
|
24
|
+
else
|
25
|
+
# Precision: three decimal places:
|
26
|
+
actual_trunc = (actual * 1000).floor / 1000.0
|
27
|
+
msg = "\nCoverage: "
|
28
|
+
msg << green("#{actual}%")
|
29
|
+
msg << " is #{green 'over'} the threshold: "
|
30
|
+
if actual_trunc > threshold
|
31
|
+
msg << bold(yellow("#{threshold}%. "))
|
32
|
+
msg << "Please update the threshold to: "
|
33
|
+
msg << bold(green("#{actual_trunc}% "))
|
34
|
+
msg << "in ./.simplecov."
|
35
|
+
else
|
36
|
+
msg << green("#{threshold}%.")
|
37
|
+
end
|
38
|
+
msg << "\n"
|
39
|
+
$stdout.puts msg
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in moribus.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem "power_enum", "~> 1.3"
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem "redcarpet"
|
10
|
+
gem "yard"
|
11
|
+
gem "pry"
|
12
|
+
end
|
13
|
+
|
14
|
+
group :test do
|
15
|
+
gem "simplecov", :require => false
|
16
|
+
gem "simplecov-rcov-text", :require => false
|
17
|
+
|
18
|
+
gem "timecop"
|
19
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 TMXCredit, authors Artem Kuzko, Sergey Potapov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# Moribus
|
2
|
+
|
3
|
+
[](http://travis-ci.org/TMXCredit/moribus)
|
4
|
+
|
5
|
+
Moribus is a set of tools for managing complex graphs of ActiveRecord objects
|
6
|
+
for which there are many inbound foreign keys, attributes and associations with
|
7
|
+
high rates of change, and business demands for well-tracked change history.
|
8
|
+
|
9
|
+
##AggregatedBehavior
|
10
|
+
|
11
|
+
AggregatedBehavior implements a pattern in which an object's identity
|
12
|
+
is modeled apart from its attributes and outbound associations. This enables
|
13
|
+
higher level of normalization of your data, since one set of properties
|
14
|
+
may be shared among multiple objects. This set of properties - attributes
|
15
|
+
and outbound associations - are modeled on an object called an "info object".
|
16
|
+
And we say that this info object is aggregated by host object(s) and it acts
|
17
|
+
(behaves) as aggregated. When an aggregated object is about to be saved, it
|
18
|
+
looks up for an existing record with the same attributes in the database under
|
19
|
+
the hood, and if it founds, it 'replaces' itself by that record. This allows
|
20
|
+
you to work with attributes of your entity as if they are properties of an
|
21
|
+
actual model and normalize your data at the same time.
|
22
|
+
|
23
|
+
Inbound foreign keys will always point at the same object in memory, and the
|
24
|
+
object will never be stale, as it has no attributes of its own that are subject
|
25
|
+
to change. This is useful for objects with many inbound foreign keys and
|
26
|
+
high-traffic attributes/associations, such as statuses. Without this pattern
|
27
|
+
it would be difficult to avoid many StaleObjectErrors.
|
28
|
+
|
29
|
+
##TrackedBehavior
|
30
|
+
|
31
|
+
TrackedBehavior implements history tracking on the stack of objects
|
32
|
+
representing the identity object's attributes and outbound associations.
|
33
|
+
When a model behaves as a tracked behavior, it will never get actually
|
34
|
+
updated. Instead, it will update it's own 'is_current' column to false
|
35
|
+
and will be saved as a new record with new attribute values and
|
36
|
+
'is_current' column as 'true'. Thus, under the hood, new attributes
|
37
|
+
will supersede old attributes, leaving old record as history one.
|
38
|
+
|
39
|
+
##Macros, Associations and Combination
|
40
|
+
|
41
|
+
Despite the fact that Behaviors may be used by models on they're own,
|
42
|
+
they main purpose is to be used within associations and in conjunction.
|
43
|
+
The best way to demonstrate this is by example.
|
44
|
+
|
45
|
+
Lets assume we have a User entity with attributes that should be tracked
|
46
|
+
and normalized. Those attributes may be, for example, `:first_name`,
|
47
|
+
`:last_name` and `:status` as enumerated integer value. This makes entity
|
48
|
+
may be represented with three models: `User` - as main model for interactions,
|
49
|
+
tracked `UserInfo` (`user_id`, `person_name_id`, `status`) for tracking, and
|
50
|
+
aggregated `UserName` (`first_name`, `last_name`) for name normalization.
|
51
|
+
Class definitions for that models will look as follows:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
class User < ActiveRecord::Base
|
55
|
+
has_one_current :user_info
|
56
|
+
delegate_associated :user_name, :to => :user_info
|
57
|
+
end
|
58
|
+
|
59
|
+
class UserInfo < ActiveRecord::Base
|
60
|
+
has_aggregated :person_name
|
61
|
+
acts_as_tracked
|
62
|
+
end
|
63
|
+
|
64
|
+
class UserName < ActiveRecord::Base
|
65
|
+
acts_as_aggregated
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
Despite the fact that internal representation is more complicated now,
|
70
|
+
top-level operations will look exactly the same:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
user = User.create(:first_name => 'John', :last_name => 'Smith', :status => 0)
|
74
|
+
# This creates User(id: 1) record, PersonName(id: 1, first_name: 'John', last_name: 'Smith')
|
75
|
+
# record and UserInfo(id: 1, user_id: 1, person_name_id: 1, status: 0, is_current: true)
|
76
|
+
|
77
|
+
user.update_attributes(:status => 1)
|
78
|
+
# This creates new UserInfo(id: 2, user_id: 1, person_name_id: 1, status: 1, is_current: true)
|
79
|
+
# record, and changes UserInfo(id: 1) record's 'is_current' attribute to false.
|
80
|
+
|
81
|
+
user.update_attributes(:first_name => 'Mike')
|
82
|
+
# This creates new PersonName(id: 2, first_name: 'Mike', last_name: 'Smith') record and new
|
83
|
+
# current UserInfo(id: 3, user_id: 1, person_name_id: 2, :status: 1, is_current: true)
|
84
|
+
|
85
|
+
# Now, if we want to create another 'John Smith' user:
|
86
|
+
user2 = User.create(:first_name => 'John', :last_name => 'Smith', :status => 5)
|
87
|
+
# This creates User(id: 2) record and UserInfo(id: 4, user_id: 2, person_name_id: 1, status: 5, is_current: true)
|
88
|
+
# record that reuses existing UserName information.
|
89
|
+
```
|
90
|
+
|
91
|
+
## Run tests
|
92
|
+
|
93
|
+
```sh
|
94
|
+
rake spec
|
95
|
+
```
|
96
|
+
|
97
|
+
## Credits
|
98
|
+
|
99
|
+
* [Artem Kuzko](https://github.com/akuzko)
|
100
|
+
* [Potapov Sergey](https://github.com/greyblake)
|
101
|
+
|
102
|
+
## Copyright
|
103
|
+
|
104
|
+
Copyright (c) 2013 TMX Credit.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
task :default => :spec
|
5
|
+
RSpec::Core::RakeTask.new
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
Rake::RDocTask.new do |rdoc|
|
9
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
10
|
+
|
11
|
+
rdoc.rdoc_dir = 'rdoc'
|
12
|
+
rdoc.title = "moribus #{version}"
|
13
|
+
rdoc.rdoc_files.include('README*')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Colorizes text with ASCII colors.
|
2
|
+
# == Usage:
|
3
|
+
# include ColorizedText
|
4
|
+
#
|
5
|
+
# puts green "OK" # => green output
|
6
|
+
# puts bold "Running... # => bold output
|
7
|
+
# puts bold green "OK!!!" # => bold green output
|
8
|
+
module ColorizedText
|
9
|
+
# Colorize text using ASCII color code
|
10
|
+
def colorize(text, code)
|
11
|
+
"\033[#{code}m#{text}\033[0m"
|
12
|
+
end
|
13
|
+
|
14
|
+
# :nodoc:
|
15
|
+
def yellow(text)
|
16
|
+
colorize(text, 33)
|
17
|
+
end
|
18
|
+
|
19
|
+
# :nodoc:
|
20
|
+
def green(text)
|
21
|
+
colorize(text, 32)
|
22
|
+
end
|
23
|
+
|
24
|
+
# :nodoc:
|
25
|
+
def red(text)
|
26
|
+
colorize(text, 31)
|
27
|
+
end
|
28
|
+
|
29
|
+
# :nodoc:
|
30
|
+
def bold(text)
|
31
|
+
colorize(text, 1)
|
32
|
+
end
|
33
|
+
end
|
data/lib/moribus.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Introduces Aggregated and Tracked behavior to ActiveRecord::Base models, as well
|
2
|
+
# as Macros and Extensions modules for more efficient usage. Effectively replaces
|
3
|
+
# both Aggregatable and Trackable modules.
|
4
|
+
module Moribus
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
extend ActiveSupport::Autoload
|
7
|
+
|
8
|
+
autoload :AliasAssociation
|
9
|
+
autoload :AggregatedBehavior
|
10
|
+
autoload :AggregatedCacheBehavior
|
11
|
+
autoload :TrackedBehavior
|
12
|
+
autoload :Macros
|
13
|
+
autoload :Extensions
|
14
|
+
|
15
|
+
included do
|
16
|
+
include AliasAssociation
|
17
|
+
include Extensions
|
18
|
+
extend Macros
|
19
|
+
end
|
20
|
+
|
21
|
+
# :nodoc:
|
22
|
+
module ClassMethods
|
23
|
+
# Adds aggregated behavior to a model.
|
24
|
+
def acts_as_aggregated(options = {})
|
25
|
+
options.symbolize_keys!
|
26
|
+
|
27
|
+
options.assert_valid_keys(:cache_by, :non_content_columns)
|
28
|
+
include AggregatedBehavior
|
29
|
+
|
30
|
+
if options[:cache_by].present?
|
31
|
+
@aggregated_caching_column = options[:cache_by]
|
32
|
+
include AggregatedCacheBehavior
|
33
|
+
end
|
34
|
+
|
35
|
+
if options[:non_content_columns]
|
36
|
+
self.aggregated_behaviour_non_content_columns += Array.wrap(options[:non_content_columns]).map(&:to_s)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
private :acts_as_aggregated
|
40
|
+
|
41
|
+
# Adds tracked behavior to a model
|
42
|
+
def acts_as_tracked(options = {})
|
43
|
+
options.symbolize_keys!
|
44
|
+
|
45
|
+
options.assert_valid_keys(:preceding_key)
|
46
|
+
include TrackedBehavior
|
47
|
+
|
48
|
+
@preceding_key_column = options[:preceding_key]
|
49
|
+
end
|
50
|
+
private :acts_as_tracked
|
51
|
+
|
52
|
+
# Return +true+ if self was declared as +acts_as_aggregated+.
|
53
|
+
def acts_as_aggregated?
|
54
|
+
self < AggregatedBehavior
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return +true+ if self was declared as +acts_as_tracked+.
|
58
|
+
def acts_as_tracked?
|
59
|
+
self < TrackedBehavior
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Marks +self+ as a new record. Sets +id+ attribute to nil, but memorizes
|
64
|
+
# the old value in case of exception.
|
65
|
+
def to_new_record!
|
66
|
+
store_before_to_new_record_values
|
67
|
+
reset_persistence_values
|
68
|
+
@new_record = true
|
69
|
+
end
|
70
|
+
|
71
|
+
# Marks +self+ as persistent record. If another record is passed, uses its
|
72
|
+
# persistence attributes (id, timestamps). If nil is passed as an argument,
|
73
|
+
# marks +self+ as persisted record and sets +id+ to memorized value.
|
74
|
+
def to_persistent!(existing = nil)
|
75
|
+
if existing
|
76
|
+
self.id = existing.id
|
77
|
+
self.created_at = existing.created_at if respond_to?(:created_at)
|
78
|
+
self.updated_at = existing.updated_at if respond_to?(:updated_at)
|
79
|
+
@changed_attributes = {}
|
80
|
+
else
|
81
|
+
restore_before_to_new_record_values
|
82
|
+
end
|
83
|
+
@new_record = false
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
# Stores original record id for tracking purposes.
|
88
|
+
def set_parent
|
89
|
+
tbc = self.class.preceding_key_column
|
90
|
+
if tbc && self.respond_to?(tbc)
|
91
|
+
write_attribute(tbc, @_before_to_new_record_values[:id])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Helper method used by has_aggregated (in fact, belongs_to)
|
96
|
+
# association during autosave.
|
97
|
+
def updated_as_aggregated?
|
98
|
+
!!@updated_as_aggregated
|
99
|
+
end
|
100
|
+
|
101
|
+
# Save persistence values of id, updated_at and created_at to instance
|
102
|
+
# variable to have an ability to set them back if object fails to
|
103
|
+
# be saved.
|
104
|
+
def store_before_to_new_record_values
|
105
|
+
values = {:id => id}
|
106
|
+
values[:updated_at] = updated_at if respond_to?(:updated_at)
|
107
|
+
values[:created_at] = created_at if respond_to?(:created_at)
|
108
|
+
@_before_to_new_record_values = values
|
109
|
+
end
|
110
|
+
private :store_before_to_new_record_values
|
111
|
+
|
112
|
+
# Set persistence values of id, updated_at and created_at back.
|
113
|
+
def restore_before_to_new_record_values
|
114
|
+
values = @_before_to_new_record_values
|
115
|
+
self.id = values[:id]
|
116
|
+
self.created_at = values[:created_at] if respond_to?(:updated_at=)
|
117
|
+
self.updated_at = values[:updated_at] if respond_to?(:updated_at=)
|
118
|
+
end
|
119
|
+
private :restore_before_to_new_record_values
|
120
|
+
|
121
|
+
# Set id, updated_at and created_at to nil in order to
|
122
|
+
# update them when new record is created.
|
123
|
+
def reset_persistence_values
|
124
|
+
self.id = nil
|
125
|
+
self.updated_at = nil if respond_to?(:updated_at=)
|
126
|
+
self.created_at = nil if respond_to?(:created_at=)
|
127
|
+
end
|
128
|
+
private :reset_persistence_values
|
129
|
+
end
|
130
|
+
|
131
|
+
ActiveRecord::Base.class_eval do
|
132
|
+
include Moribus
|
133
|
+
end
|