citier4 0.0.3 → 0.0.4
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 +4 -4
- data/lib/citier4.rb +1 -1
- data/lib/citier4/acts_as_citier4.rb +16 -5
- data/lib/citier4/child_instance_methods.rb +43 -36
- data/lib/citier4/core_ext.rb +41 -1
- data/lib/citier4/instance_methods.rb +25 -1
- data/lib/citier4/root_instance_methods.rb +2 -1
- data/lib/citier4/version.rb +1 -1
- data/test/callback_test.rb +26 -0
- data/test/changed_test.rb +25 -0
- data/test/child_instance_methods_test.rb +5 -3
- data/test/deleting_methods_test.rb +5 -5
- data/test/dummy/app/models/book.rb +1 -1
- data/test/dummy/app/models/product.rb +1 -1
- data/test/dummy/config/database.yml +12 -4
- data/test/dummy/db/schema.rb +6 -3
- data/test/dummy/log/development.log +986 -0
- data/test/dummy/log/test.log +36160 -0
- data/test/keep.rb +46 -0
- data/test/model_test.rb +3 -3
- data/test/saving_methods_test.rb +27 -0
- data/test/test_helper.rb +14 -4
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 487b7108d47f5766250f0f68a7d133828d4bb5bd
|
|
4
|
+
data.tar.gz: 138a93acf1ca20151b5d45038c14340a2236e798
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37b8851436ce2b16be48b0615c8bd2d143c0a99373b095d5b0b4a61f108fbf1b484b0dea168a28465572c957c70f5691e7abf9cefddacd051e3790582cd87927
|
|
7
|
+
data.tar.gz: e326fcbfb3a9a5300a133b5fb250ad81b3ad2b0fa29ac3dbc7b6865c15a8c7d994870ca4fcb549aa9838dc5f912f0b904774558afe492be400749acad66f252d
|
data/lib/citier4.rb
CHANGED
|
@@ -17,7 +17,6 @@ module Citier4
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
module ClassMethods
|
|
20
|
-
@@first_call=true
|
|
21
20
|
|
|
22
21
|
def acts_as_citier4(options = {})
|
|
23
22
|
# your code will go here
|
|
@@ -34,9 +33,7 @@ module Citier4
|
|
|
34
33
|
|
|
35
34
|
table_name = (options[:table_name] || self.name.tableize.gsub(/\//,'_')).to_s
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
# Unfortunatly, first_call is not a good solution when we are in developpement : acts_as_citier4 could be reload for the root class ...
|
|
39
|
-
if ! superclass.acts_as_citier?
|
|
36
|
+
if ! superclass.acts_as_citier?
|
|
40
37
|
# Root class
|
|
41
38
|
# Option for setting the inheritance columns, default value = 'type'
|
|
42
39
|
# authorized only in root
|
|
@@ -51,6 +48,8 @@ module Citier4
|
|
|
51
48
|
citier_debug("Root Class, in home directory")
|
|
52
49
|
self.table_name = "#{table_name}"
|
|
53
50
|
citier_debug("table_name -> #{self.table_name}")
|
|
51
|
+
|
|
52
|
+
self.const_set("Writeable", create_class_root_writable(self))
|
|
54
53
|
|
|
55
54
|
# Add the functions required for root classes only
|
|
56
55
|
# include is for adding methods to an instance of a class
|
|
@@ -85,7 +84,19 @@ module Citier4
|
|
|
85
84
|
# Add the functions required for children only
|
|
86
85
|
send :include, Citier4::ChildInstanceMethods
|
|
87
86
|
end
|
|
88
|
-
|
|
87
|
+
|
|
88
|
+
def changes_applied
|
|
89
|
+
super
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def clear_attribute_changes(att)
|
|
93
|
+
super
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def clear_changes_information
|
|
97
|
+
super
|
|
98
|
+
end
|
|
99
|
+
|
|
89
100
|
end
|
|
90
101
|
|
|
91
102
|
end
|
|
@@ -13,16 +13,14 @@ module Citier4
|
|
|
13
13
|
# Run save and create/update callbacks, just like ActiveRecord does
|
|
14
14
|
self.run_callbacks(:save) do
|
|
15
15
|
self.run_callbacks(self.new_record? ? :create : :update) do
|
|
16
|
-
|
|
17
|
-
#
|
|
18
|
-
#get the attributes of the class which are inherited from it's parent.
|
|
19
|
-
attributes_for_parent = self.attributes.reject { |key,value| !self.class.superclass.column_names.include?(key) }
|
|
20
|
-
changed_attributes_for_parent = self.changed_attributes.reject { |key,value| !self.class.superclass.column_names.include?(key) }
|
|
16
|
+
|
|
17
|
+
# changed_attributes_for_parent = self.changed_attributes.reject { |key,value| !self.class.superclass.column_names.include?(key) }
|
|
21
18
|
|
|
22
19
|
# Get the attributes of the class which are unique to this class and not inherited.
|
|
23
|
-
attributes_for_current = self.attributes.reject { |key,value| self.class.superclass.column_names.include?(key) }
|
|
24
|
-
changed_attributes_for_current = self.changed_attributes.reject { |key,value| self.class.superclass.column_names.include?(key) }
|
|
20
|
+
#attributes_for_current = self.attributes.reject { |key,value| self.class.superclass.column_names.include?(key) }
|
|
21
|
+
#changed_attributes_for_current = self.changed_attributes.reject { |key,value| self.class.superclass.column_names.include?(key) }
|
|
25
22
|
|
|
23
|
+
# debugger
|
|
26
24
|
citier_debug("Attributes for #{self.class.superclass.to_s}: #{attributes_for_parent.inspect}")
|
|
27
25
|
citier_debug("Changed attributes for #{self.class.superclass.to_s}: #{changed_attributes_for_parent.keys.inspect}")
|
|
28
26
|
citier_debug("Attributes for #{self.class.to_s}: #{attributes_for_current.inspect}")
|
|
@@ -34,23 +32,31 @@ module Citier4
|
|
|
34
32
|
|
|
35
33
|
#create a new instance of the superclass, passing the inherited attributes.
|
|
36
34
|
|
|
37
|
-
#
|
|
38
35
|
parent = self.class.superclass.new
|
|
39
|
-
parent.
|
|
40
|
-
|
|
36
|
+
parent.id = self.id # nul if create, a real id otherwise
|
|
37
|
+
parent.clear_changes_information
|
|
38
|
+
# Natural Rail STI process, in new, change the "type" colomn from nil to "class.superclass.name"
|
|
39
|
+
# so we have a flaged change for this "type" colomun.
|
|
40
|
+
# And we have to clear these change
|
|
41
|
+
# Clear all changes is more simple and probably more efficient that a specific clear on the STI "type" column
|
|
42
|
+
# like the line bellow
|
|
43
|
+
# parent.clear_attribute_change(parent.class.inheritance_column)
|
|
44
|
+
parent.force_attributes(changed_attributes_for_parent)
|
|
45
|
+
# parent.force_attributes(attributes_for_parent, :merge => true)
|
|
46
|
+
# parent = self.class.superclass.new self.changed_attributes_for_parent
|
|
47
|
+
# these doen't work, because parent.class IS NOT self.superclass, but self.class
|
|
48
|
+
# sinon, TODO, pourquoi descendre en superclass. Il faut sauter et aller a la prochaine superclass dure ...
|
|
49
|
+
parent.is_new_record(self.new_record?)
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
parent.
|
|
51
|
+
# parent.force_changed_attributes(changed_attributes_for_parent)
|
|
52
|
+
# parent.type = self.type
|
|
53
|
+
# parent.is_new_record(new_record?)
|
|
44
54
|
|
|
45
|
-
|
|
46
|
-
parent.type = self.type
|
|
47
|
-
|
|
48
|
-
parent.is_new_record(new_record?)
|
|
49
|
-
|
|
50
|
-
# If we're root (AR subclass) this will just be saved as normal through AR. If we're a child it will call this method again.
|
|
55
|
+
# If we're root this will just be saved as normal through AR. If we're a child it will call this method again.
|
|
51
56
|
# It will try and save it's parent and then save itself through the Writeable constant.
|
|
57
|
+
# For a new record, we will have an id, only when the root is saved.
|
|
52
58
|
parent_saved = parent.save
|
|
53
|
-
|
|
59
|
+
# self.id = parent.id
|
|
54
60
|
|
|
55
61
|
if !parent_saved
|
|
56
62
|
# Couldn't save parent class
|
|
@@ -58,25 +64,24 @@ module Citier4
|
|
|
58
64
|
citier_debug("Errors = #{parent.errors.to_s}")
|
|
59
65
|
return false # Return false and exit run_callbacks :save and :create/:update, so the after_ callback won't run.
|
|
60
66
|
end
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
######
|
|
65
|
-
##
|
|
66
|
-
## Self Saving
|
|
67
|
-
##
|
|
68
|
-
|
|
67
|
+
###### End of parent saving #####
|
|
68
|
+
###### Self Saving
|
|
69
69
|
# If there are attributes for the current class (unique & not inherited), save current model
|
|
70
|
+
# attention, si aucun attribut pour le parent, mais que on est en new_record
|
|
71
|
+
# il faut quand meme sauver le current. DOTO Faire un test.
|
|
70
72
|
if !attributes_for_current.empty?
|
|
71
|
-
|
|
73
|
+
# ici, parrent est sauvé, et on a un ID
|
|
72
74
|
current = self.class::Writeable.new
|
|
73
|
-
current.force_attributes(attributes_for_current, :merge => true)
|
|
75
|
+
# current.force_attributes(attributes_for_current, :merge => true)
|
|
76
|
+
current.force_attributes(attributes_for_current)
|
|
74
77
|
# marche pas non plus current = self.class::Writeable.new attributes_for_current
|
|
75
78
|
|
|
76
79
|
current.force_changed_attributes(changed_attributes_for_current)
|
|
77
80
|
|
|
78
|
-
current.id = self.id
|
|
81
|
+
# current.id = self.id # NON
|
|
82
|
+
current.id = parent.id
|
|
79
83
|
current.is_new_record(new_record?)
|
|
84
|
+
clear_attribute_changes(:id) if !current.new_record?
|
|
80
85
|
|
|
81
86
|
current_saved = current.save
|
|
82
87
|
|
|
@@ -89,12 +94,14 @@ module Citier4
|
|
|
89
94
|
end
|
|
90
95
|
end
|
|
91
96
|
|
|
92
|
-
# at this point, parent_saved && current_saved
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
# at this point, parent_saved && current_saved
|
|
98
|
+
|
|
99
|
+
# if self.class.name == self.attributes[self.class.inheritance_column]
|
|
100
|
+
is_new_record(false) # This is no longer a new record
|
|
101
|
+
#self.force_changed_attributes({}) # Reset changed_attributes so future changes will be tracked correctly
|
|
102
|
+
self.id = parent.id
|
|
103
|
+
self.clear_changes_information
|
|
104
|
+
# end
|
|
98
105
|
# No return, because we want the after callback to run.
|
|
99
106
|
end
|
|
100
107
|
end
|
data/lib/citier4/core_ext.rb
CHANGED
|
@@ -18,6 +18,34 @@ class ActiveRecord::Base
|
|
|
18
18
|
@new_record = state
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
|
|
22
|
+
#create the writeable class which inherits from ActiveRecord::Base
|
|
23
|
+
# for the root class (TODO merge the code with the cild)
|
|
24
|
+
def self.create_class_root_writable(class_reference)
|
|
25
|
+
Class.new(ActiveRecord::Base) do
|
|
26
|
+
# include Citier4::InstanceMethods::ForcedWriters
|
|
27
|
+
|
|
28
|
+
# set the name of the table associated to this class
|
|
29
|
+
# this class will be associated to the writable table of the class_reference class
|
|
30
|
+
# self.table_name = view_name[5..view_name.length]
|
|
31
|
+
self.table_name = class_reference.table_name
|
|
32
|
+
# remove the STI mecanizm
|
|
33
|
+
self.inheritance_column = :_type_disabled
|
|
34
|
+
|
|
35
|
+
def changes_applied
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def clear_attribute_changes(att)
|
|
40
|
+
super
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def clear_changes_information
|
|
44
|
+
super
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
21
49
|
#create the writeable class which inherits from ActiveRecord::Base
|
|
22
50
|
def self.create_class_writable(class_reference)
|
|
23
51
|
Class.new(ActiveRecord::Base) do
|
|
@@ -27,6 +55,18 @@ class ActiveRecord::Base
|
|
|
27
55
|
# set the name of the table associated to this class
|
|
28
56
|
# this class will be associated to the writable table of the class_reference class
|
|
29
57
|
self.table_name = view_name[5..view_name.length]
|
|
58
|
+
|
|
59
|
+
def changes_applied
|
|
60
|
+
super
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def clear_attribute_changes(att)
|
|
64
|
+
super
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def clear_changes_information
|
|
68
|
+
super
|
|
69
|
+
end
|
|
30
70
|
end
|
|
31
71
|
end
|
|
32
72
|
end
|
|
@@ -110,7 +150,7 @@ module ActiveRecord
|
|
|
110
150
|
def load
|
|
111
151
|
puts "in load de citier4"
|
|
112
152
|
exec_queries unless loaded?
|
|
113
|
-
|
|
153
|
+
# debugger
|
|
114
154
|
self
|
|
115
155
|
end
|
|
116
156
|
end
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
module Citier4
|
|
2
|
-
module InstanceMethods
|
|
2
|
+
module InstanceMethods
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#get the attributes of the class which are inherited from it's parent.
|
|
6
|
+
def attributes_for_parent
|
|
7
|
+
attributes.select { |key,value| self.class.superclass.column_names.include?(key) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
#get the changes attributes of the class which are inherited from it's parent.
|
|
11
|
+
def changed_attributes_for_parent
|
|
12
|
+
key_changed = changed.select{ |key| self.class.superclass.column_names.include?(key) }
|
|
13
|
+
attributes.select { |key,vlaue| key_changed.include?(key) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def attributes_for_current
|
|
17
|
+
attributes.select { |key,value| self.class::Writeable.column_names.include?(key) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def changed_attributes_for_current
|
|
21
|
+
key_changed = changed.select{ |key| self.class::Writeable.column_names.include?(key) }
|
|
22
|
+
attributes.select { |key,vlaue| key_changed.include?(key) }
|
|
23
|
+
end
|
|
24
|
+
|
|
3
25
|
def self.included(base)
|
|
4
26
|
base.send :include, ForcedWriters
|
|
5
27
|
end
|
|
@@ -20,6 +42,8 @@ module Citier4
|
|
|
20
42
|
end
|
|
21
43
|
end
|
|
22
44
|
|
|
45
|
+
# TODO : Is is still usefull ? Can we remove by using ActiveRecord::Dirty ?
|
|
46
|
+
# see http://api.rubyonrails.org/classes/ActiveModel/Dirty.html
|
|
23
47
|
def force_changed_attributes(new_changed_attributes, options = {})
|
|
24
48
|
new_changed_attributes = @attributes.merge(new_changed_attributes) if options[:merge]
|
|
25
49
|
@changed_attributes = new_changed_attributes
|
data/lib/citier4/version.rb
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class Record
|
|
2
|
+
include ActiveSupport::Callbacks
|
|
3
|
+
define_callbacks :save
|
|
4
|
+
|
|
5
|
+
def save
|
|
6
|
+
puts "start save"
|
|
7
|
+
run_callbacks :save do
|
|
8
|
+
puts "- save"
|
|
9
|
+
end
|
|
10
|
+
puts "end save"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class PersonRecord < Record
|
|
15
|
+
set_callback :save, :before, :saving_message
|
|
16
|
+
def saving_message
|
|
17
|
+
puts "saving..."
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
set_callback :save, :after do |object|
|
|
21
|
+
puts "saved"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
person = PersonRecord.new
|
|
26
|
+
person.save
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class Changed < ActiveSupport::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
Book.create name: "book1", author: "auteur1"
|
|
7
|
+
Product.create name: "product1"
|
|
8
|
+
Book.create name: "book2", author: "auteur2"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
test "changed in find in root or child" do
|
|
14
|
+
book = Book.first
|
|
15
|
+
book_changed = book.changed
|
|
16
|
+
|
|
17
|
+
product = Product.first
|
|
18
|
+
product_changed = product.changed
|
|
19
|
+
|
|
20
|
+
assert_not book.changed?
|
|
21
|
+
assert_not product.changed?
|
|
22
|
+
assert_equal book_changed, product_changed
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -25,10 +25,12 @@ class ChildInstanceMethods < ActiveSupport::TestCase
|
|
|
25
25
|
# in rails 4.2 lire au niveau de Product ne permet pas de récuperer les champs Book ..
|
|
26
26
|
Product.delete_all
|
|
27
27
|
assert_equal Book.count, 0
|
|
28
|
-
Book.create( name: "
|
|
29
|
-
product = Product.find_by( name: "
|
|
28
|
+
book=Book.create( name: "UnLivreAvecUnNomSuperCompliqué", author: "Inconnu")
|
|
29
|
+
product = Product.find_by( name: "UnLivreAvecUnNomSuperCompliqué")
|
|
30
|
+
assert_equal book.id, product.id
|
|
30
31
|
assert_equal product.class.name, "Book"
|
|
31
|
-
assert_equal
|
|
32
|
+
assert_equal book.class.name, "Book"
|
|
33
|
+
assert_equal product.author, book.author
|
|
32
34
|
product.delete
|
|
33
35
|
assert_equal Book.count, 0
|
|
34
36
|
end
|
|
@@ -49,9 +49,9 @@ class DeletingMethods < ActiveSupport::TestCase
|
|
|
49
49
|
### DESTROY
|
|
50
50
|
|
|
51
51
|
test "destroy by id, in root, the first in root" do
|
|
52
|
+
# debugger
|
|
52
53
|
puts "TODO Destroy work in rails 4.1, but not any more in 4.2"
|
|
53
54
|
# return true
|
|
54
|
-
debugger
|
|
55
55
|
id = Product.first.id # first could be a child or a root ...
|
|
56
56
|
Product.destroy(id)
|
|
57
57
|
assert data_base_is_clean?(id), "data base is not clean after delete first in root"
|
|
@@ -59,7 +59,7 @@ class DeletingMethods < ActiveSupport::TestCase
|
|
|
59
59
|
|
|
60
60
|
test "destroy by id, in root, the first in child" do
|
|
61
61
|
puts "TODO Destroy work in rails 4.1, but not any more in 4.2"
|
|
62
|
-
return true
|
|
62
|
+
#return true
|
|
63
63
|
id = Book.first.id
|
|
64
64
|
Product.destroy(id)
|
|
65
65
|
assert data_base_is_clean?(id), "data base is not clean after delete first in root"
|
|
@@ -69,7 +69,7 @@ class DeletingMethods < ActiveSupport::TestCase
|
|
|
69
69
|
|
|
70
70
|
test "destroy by id, in child, the first in child" do
|
|
71
71
|
puts "TODO Destroy work in rails 4.1, but not any more in 4.2"
|
|
72
|
-
return true
|
|
72
|
+
#return true
|
|
73
73
|
id = Book.first.id
|
|
74
74
|
Book.destroy(id)
|
|
75
75
|
assert data_base_is_clean?(id), "data base is not clean after delete first in root"
|
|
@@ -80,7 +80,7 @@ class DeletingMethods < ActiveSupport::TestCase
|
|
|
80
80
|
|
|
81
81
|
test "destroy by instance the first in root" do
|
|
82
82
|
puts "TODO Destroy work in rails 4.1, but not any more in 4.2"
|
|
83
|
-
return true
|
|
83
|
+
#return true
|
|
84
84
|
product = Product.first
|
|
85
85
|
id = product.id
|
|
86
86
|
product.delete
|
|
@@ -88,7 +88,7 @@ class DeletingMethods < ActiveSupport::TestCase
|
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
test "destroy by instance the first in book" do
|
|
91
|
-
puts "TODO Destroy work in rails 4.1, but not any more in 4.2"
|
|
91
|
+
#puts "TODO Destroy work in rails 4.1, but not any more in 4.2"
|
|
92
92
|
return true
|
|
93
93
|
book = Book.first
|
|
94
94
|
id = book.id
|
|
@@ -10,15 +10,23 @@ default: &default
|
|
|
10
10
|
timeout: 5000
|
|
11
11
|
|
|
12
12
|
development:
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
adapter: postgresql
|
|
14
|
+
encoding: unicode
|
|
15
|
+
database: citier4_development
|
|
15
16
|
|
|
16
17
|
# Warning: The database defined as "test" will be erased and
|
|
17
18
|
# re-generated from your development database when you run "rake".
|
|
18
19
|
# Do not set this db to the same as development or production.
|
|
20
|
+
|
|
21
|
+
#test:
|
|
22
|
+
# <<: *default
|
|
23
|
+
# database: db/test.sqlite3
|
|
24
|
+
|
|
19
25
|
test:
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
adapter: postgresql
|
|
27
|
+
encoding: unicode
|
|
28
|
+
database: citier4_test
|
|
29
|
+
|
|
22
30
|
|
|
23
31
|
production:
|
|
24
32
|
<<: *default
|