acts_as_customized_attributes 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +10 -1
- data/app/models/acts_as_customized_attributes/data.rb +27 -1
- data/app/models/acts_as_customized_attributes/data_key.rb +26 -8
- data/lib/acts_as_customized_attributes/class_methods.rb +4 -7
- data/lib/acts_as_customized_attributes/instance_methods.rb +23 -4
- data/lib/acts_as_customized_attributes/version.rb +1 -1
- data/spec/dummy/log/test.log +5232 -0
- data/spec/models/user_spec.rb +21 -15
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OWIxNDQ5MjA4ZjBmYzAxZDU0NDJiYTRhYzExZjMwZGE2Y2E4NDZhYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MjM5NGRkYzIzZTBlYTUzYWU2MDljNGI0ZTAwZWE5ODAxMjM4M2Y2Zg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODQ4MGQyNGMyMjkxYzdiOGEzNWVhYTVhYmU2MTYxNTQyM2UwZmY3ZGNiNDM0
|
10
|
+
MjRjMWVhMWI5MDllNTEwYWVhMzNkZDhkODYzNjFkODc2MGRmZGRmN2FmNzA3
|
11
|
+
MTI2NzgwYzc4NDgxOGI4ZTU3NjEzYWExN2ZmZDNiNTA3ODU0NzI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ODM1NWFkM2FjZDY1ODUxMGZiZDhiZjYyMWExYTAzODUxYWY1ZGIyZThlZTQx
|
14
|
+
YzdhYWRmYTI4ZmVlMjE5NTFkNGQ3ZmU1ZGMxOGIzNjgxMDgyYzc2NTcxODA0
|
15
|
+
YzcwMGUxYmZmZDUzZmYzZmEwZTFlNjFiNzE0NGNhODkyYzg4Yjk=
|
data/README.md
CHANGED
@@ -33,7 +33,7 @@ class AddCustomizedAttributesForSomeModel < ActiveRecord::Migration
|
|
33
33
|
def up
|
34
34
|
SomeModel.create_customized_attributes!
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def down
|
38
38
|
SomeModel.drop_customized_attributes!
|
39
39
|
end
|
@@ -68,6 +68,15 @@ SomeModel::DataKey.where("name LIKE '%facebook%'")
|
|
68
68
|
SomeModel::Data.where("resource_id > 5")
|
69
69
|
```
|
70
70
|
|
71
|
+
### Optimize inserts with transactions for inserts / updates.
|
72
|
+
```ruby
|
73
|
+
ActiveRecordTransactioner.new do |trans|
|
74
|
+
models.each do |model|
|
75
|
+
model.update_customized_attributes_with_args(data: {my_custom_attribute: 5}, transactioner: trans)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
71
80
|
## License
|
72
81
|
|
73
82
|
This project uses MIT-LICENSE.
|
@@ -1,3 +1,29 @@
|
|
1
1
|
class ActsAsCustomizedAttributes::Data < ActiveRecord::Base
|
2
|
-
|
2
|
+
validate :associated_resource_and_data_key
|
3
|
+
|
4
|
+
def self.key_class=(key_class)
|
5
|
+
@key_class = key_class
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.key_class
|
9
|
+
return @key_class
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def associated_resource_and_data_key
|
15
|
+
unless data_key_id?
|
16
|
+
return errors.add :data_key_id, "not valid"
|
17
|
+
end
|
18
|
+
|
19
|
+
if !resource_id? || !resource
|
20
|
+
return errors.add :resource_id, "not associated"
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
self.class.key_class.name_for_id(data_key_id)
|
25
|
+
rescue KeyError
|
26
|
+
errors.add :data_key_id, "doesn't exist"
|
27
|
+
end
|
28
|
+
end
|
3
29
|
end
|
@@ -1,5 +1,11 @@
|
|
1
1
|
class ActsAsCustomizedAttributes::DataKey < ActiveRecord::Base
|
2
|
+
after_create :add_to_cache
|
3
|
+
after_update :add_to_cache
|
4
|
+
after_destroy :remove_from_cache
|
5
|
+
before_update :remove_from_cache
|
6
|
+
|
2
7
|
validates_presence_of :name
|
8
|
+
validate :validate_unique_name
|
3
9
|
|
4
10
|
def self.id_for_name(name)
|
5
11
|
cache_name_to_id.fetch(name.to_s)
|
@@ -9,26 +15,38 @@ class ActsAsCustomizedAttributes::DataKey < ActiveRecord::Base
|
|
9
15
|
cache_name_to_id.key(id) or raise KeyError, "No such ID: #{id}"
|
10
16
|
end
|
11
17
|
|
12
|
-
|
18
|
+
def self.cache_name_to_id
|
19
|
+
update_cache_name_to_id unless @cache_name_to_id
|
20
|
+
return @cache_name_to_id
|
21
|
+
end
|
13
22
|
|
14
23
|
# Initializes / reloads the cache.
|
15
24
|
def self.update_cache_name_to_id
|
16
|
-
|
25
|
+
@cache_name_to_id = {}
|
17
26
|
find_each do |data_key|
|
18
|
-
|
27
|
+
@cache_name_to_id[data_key.name] = data_key.id
|
19
28
|
end
|
20
29
|
end
|
21
30
|
|
22
|
-
|
23
|
-
update_cache_name_to_id unless @cache_name_to_id
|
24
|
-
return @@cache_name_to_id
|
25
|
-
end
|
31
|
+
private
|
26
32
|
|
27
33
|
def add_to_cache
|
28
34
|
self.class.cache_name_to_id[name.to_s] = id
|
29
35
|
end
|
30
36
|
|
31
37
|
def remove_from_cache
|
32
|
-
self.class.cache_name_to_id.delete(
|
38
|
+
self.class.cache_name_to_id.delete(name_was)
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate_unique_name
|
42
|
+
begin
|
43
|
+
id_exists = self.class.id_for_name(name)
|
44
|
+
|
45
|
+
if id_exists != id
|
46
|
+
errors.add :name, :taken
|
47
|
+
end
|
48
|
+
rescue KeyError
|
49
|
+
# No problem.
|
50
|
+
end
|
33
51
|
end
|
34
52
|
end
|
@@ -2,29 +2,26 @@ module ActsAsCustomizedAttributes::ClassMethods
|
|
2
2
|
def acts_as_customized_attributes(args = {})
|
3
3
|
$aaca_class_name_key = "#{name}DataKey"
|
4
4
|
$aaca_class_name_data = "#{name}Data"
|
5
|
+
$original_class_name = name
|
5
6
|
|
6
7
|
class_data_key = Class.new(ActsAsCustomizedAttributes::DataKey) do
|
7
8
|
set_table_name $aaca_class_name_key.tableize
|
8
9
|
|
9
10
|
has_many :data, class_name: $aaca_class_name_data, foreign_key: "data_key_id", dependent: :destroy
|
10
|
-
|
11
|
-
after_create :add_to_cache
|
12
|
-
after_update :add_to_cache
|
13
|
-
after_destroy :remove_from_cache
|
14
|
-
before_update :remove_from_cache
|
15
11
|
end
|
16
12
|
|
17
13
|
class_data = Class.new(ActsAsCustomizedAttributes::Data) do
|
18
14
|
set_table_name $aaca_class_name_data.tableize
|
19
15
|
|
16
|
+
belongs_to :resource, class_name: $original_class_name
|
20
17
|
belongs_to :data_key, class_name: $aaca_class_name_key
|
21
|
-
|
22
|
-
validates_associated :data_key
|
23
18
|
end
|
24
19
|
|
25
20
|
Object.const_set($aaca_class_name_key, class_data_key)
|
26
21
|
Object.const_set($aaca_class_name_data, class_data)
|
27
22
|
|
23
|
+
class_data.key_class = Object.const_get($aaca_class_name_key)
|
24
|
+
|
28
25
|
include ActsAsCustomizedAttributes::InstanceMethods
|
29
26
|
|
30
27
|
has_many :data, class_name: "#{name}Data", foreign_key: "resource_id", dependent: :destroy
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module ActsAsCustomizedAttributes::InstanceMethods
|
2
2
|
def update_customized_attributes(data)
|
3
|
-
data
|
3
|
+
update_customized_attributes_with_args(data: data)
|
4
|
+
end
|
5
|
+
|
6
|
+
UPDATE_CUSTOMIZED_ATTRIBUTES_VALID_ARGS = [:data, :transactioner]
|
7
|
+
def update_customized_attributes_with_args(args)
|
8
|
+
args.each { |key, value| raise "Invalid argument: '#{key}'." unless UPDATE_CUSTOMIZED_ATTRIBUTES_VALID_ARGS.include?(key) }
|
9
|
+
|
10
|
+
args[:data].each do |key, value|
|
4
11
|
begin
|
5
12
|
key_id = self.class.aaca_key_class.id_for_name(key)
|
6
13
|
rescue KeyError
|
@@ -8,9 +15,21 @@ module ActsAsCustomizedAttributes::InstanceMethods
|
|
8
15
|
key_id = key_model.id
|
9
16
|
end
|
10
17
|
|
11
|
-
|
12
|
-
|
13
|
-
|
18
|
+
data_model = self.data.where(data_key_id: key_id).first
|
19
|
+
if data_model
|
20
|
+
data_model.resource = self # Saves query when validating.
|
21
|
+
else
|
22
|
+
# Set resource in order to skip query when validating.
|
23
|
+
data_model = self.data.new(data_key_id: key_id, resource: self)
|
24
|
+
end
|
25
|
+
|
26
|
+
data_model.value = value
|
27
|
+
|
28
|
+
if args[:transactioner]
|
29
|
+
args[:transactioner].save!(data_model)
|
30
|
+
else
|
31
|
+
data_model.save!
|
32
|
+
end
|
14
33
|
end
|
15
34
|
end
|
16
35
|
|