acts_as_customized_attributes 0.0.5 → 0.0.6

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTcyNDM3Njc0M2MyMTFmZGEyOGQ1OTM3ZjhiNzdkMTFiYmU1YzRkNg==
4
+ OWIxNDQ5MjA4ZjBmYzAxZDU0NDJiYTRhYzExZjMwZGE2Y2E4NDZhYg==
5
5
  data.tar.gz: !binary |-
6
- YWYzN2Q3OWY4ZjE5MDY3MDY2YTYyNGYzYWI4OThkN2E0YjQyNTk4ZA==
6
+ MjM5NGRkYzIzZTBlYTUzYWU2MDljNGI0ZTAwZWE5ODAxMjM4M2Y2Zg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZjRkNWI5YWNmZGFiMjJmNzBjMGM4YmRkYzBhOTk4YjFmOWU4Njc3ODM3M2Jj
10
- NjcyNzBmYTEyYWE0ODZlOGE5OWQ2MTg2NWE1ZTQ5OWYxOGNkZmVhNDI1MWE1
11
- N2Y5ODUzM2ZkMTIyYjkxN2FkNjE5ZTVhNDA0YTE0NmE3MjYwYTU=
9
+ ODQ4MGQyNGMyMjkxYzdiOGEzNWVhYTVhYmU2MTYxNTQyM2UwZmY3ZGNiNDM0
10
+ MjRjMWVhMWI5MDllNTEwYWVhMzNkZDhkODYzNjFkODc2MGRmZGRmN2FmNzA3
11
+ MTI2NzgwYzc4NDgxOGI4ZTU3NjEzYWExN2ZmZDNiNTA3ODU0NzI=
12
12
  data.tar.gz: !binary |-
13
- YzMxMjNiZDI5NGZiY2QyYWY4MzgxZWNiNmUwMGY1ZDFmNDk5YWY2NjQ4YmI5
14
- MTAxNjQ2YjFjOWZlY2E4NTExMGQ5NTgzZWE4MTg5Y2RlYzA2NDRiN2Q4YWFh
15
- MTY5NmI2MmQ3NTE1YjkzYjYxYWNhOTY4YmM3OGZlODhlMTY2MGI=
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
- belongs_to :resource, polymorphic: true
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
- private
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
- @@cache_name_to_id = {}
25
+ @cache_name_to_id = {}
17
26
  find_each do |data_key|
18
- @@cache_name_to_id[data_key.name] = data_key.id
27
+ @cache_name_to_id[data_key.name] = data_key.id
19
28
  end
20
29
  end
21
30
 
22
- def self.cache_name_to_id
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(name)
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.each do |key, value|
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
- data = self.class.aaca_data_class.find_or_initialize_by_data_key_id_and_resource_id(key_id, id)
12
- data.value = value
13
- data.save!
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
 
@@ -1,3 +1,3 @@
1
1
  module ActsAsCustomizedAttributes
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end