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 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