acts_as_customized_attributes 0.0.6 → 0.0.7
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 +5 -13
- data/README.md +3 -3
- data/Rakefile +15 -11
- data/config/routes.rb +1 -0
- data/lib/acts_as_customized_attributes.rb +1 -0
- data/lib/acts_as_customized_attributes/class_methods.rb +95 -13
- data/lib/acts_as_customized_attributes/compatibility.rb +1 -0
- data/lib/acts_as_customized_attributes/engine.rb +4 -2
- data/lib/acts_as_customized_attributes/instance_methods.rb +7 -6
- data/lib/acts_as_customized_attributes/version.rb +2 -1
- data/lib/tasks/acts_as_customized_attributes_tasks.rake +1 -0
- data/spec/dummy/Rakefile +2 -1
- data/spec/dummy/app/controllers/application_controller.rb +1 -0
- data/spec/dummy/app/helpers/application_helper.rb +1 -0
- data/spec/dummy/app/models/order.rb +1 -0
- data/spec/dummy/app/models/user.rb +1 -0
- data/spec/dummy/config.ru +2 -1
- data/spec/dummy/config/application.rb +4 -4
- data/spec/dummy/config/boot.rb +6 -5
- data/spec/dummy/config/database.example.yml +6 -37
- data/spec/dummy/config/database.shippable.yml +2 -5
- data/spec/dummy/config/database.yml +9 -16
- data/spec/dummy/config/environment.rb +2 -1
- data/spec/dummy/config/environments/development.rb +2 -0
- data/spec/dummy/config/environments/production.rb +3 -1
- data/spec/dummy/config/environments/test.rb +4 -2
- data/spec/dummy/config/initializers/backtrace_silencers.rb +1 -0
- data/spec/dummy/config/initializers/inflections.rb +1 -0
- data/spec/dummy/config/initializers/mime_types.rb +1 -0
- data/spec/dummy/config/initializers/secret_token.rb +3 -1
- data/spec/dummy/config/initializers/session_store.rb +2 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +1 -0
- data/spec/dummy/config/routes.rb +1 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20141118114902_create_users.rb +1 -0
- data/spec/dummy/db/migrate/20141118114941_create_user_customized_attributes.rb +1 -0
- data/spec/dummy/db/migrate/20141118134833_create_orders.rb +1 -0
- data/spec/dummy/db/migrate/20141118135027_create_order_customized_attributes.rb +1 -0
- data/spec/dummy/db/schema.rb +16 -16
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +153 -0
- data/spec/dummy/log/test.log +2278 -0
- data/spec/dummy/script/rails +4 -3
- data/spec/factories/order.rb +1 -0
- data/spec/factories/user.rb +1 -0
- data/spec/models/user_spec.rb +23 -22
- data/spec/spec_helper.rb +8 -7
- metadata +64 -34
- data/app/models/acts_as_customized_attributes/data.rb +0 -29
- data/app/models/acts_as_customized_attributes/data_key.rb +0 -52
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MjM5NGRkYzIzZTBlYTUzYWU2MDljNGI0ZTAwZWE5ODAxMjM4M2Y2Zg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6cf3da61d6819da1a7d8562dcad8619affda62f5
|
4
|
+
data.tar.gz: 36bc64c145508ac95af5dfe0045854979bc13412
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MjRjMWVhMWI5MDllNTEwYWVhMzNkZDhkODYzNjFkODc2MGRmZGRmN2FmNzA3
|
11
|
-
MTI2NzgwYzc4NDgxOGI4ZTU3NjEzYWExN2ZmZDNiNTA3ODU0NzI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ODM1NWFkM2FjZDY1ODUxMGZiZDhiZjYyMWExYTAzODUxYWY1ZGIyZThlZTQx
|
14
|
-
YzdhYWRmYTI4ZmVlMjE5NTFkNGQ3ZmU1ZGMxOGIzNjgxMDgyYzc2NTcxODA0
|
15
|
-
YzcwMGUxYmZmZDUzZmYzZmEwZTFlNjFiNzE0NGNhODkyYzg4Yjk=
|
6
|
+
metadata.gz: b0947725f00d7d5f619a78f7a291f0a7250752a8730f2f29ffb6d6dc5da16e8eb65109a31b87a81962ca44ceeb140a8ed13d50f4123c2b8c619f90af3e78b037
|
7
|
+
data.tar.gz: 82dfbf339ae77a97b164b94ed38c61ee5e4fa2fd0689af80108a5c743cab765f24c72186b0948f36f26e93f092352438d3ed06f4867e623a75c2823c57494440
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
[](https://app.shippable.com/projects/546b3f7bd46935d5fbbde6b9/builds/latest)
|
2
1
|
[](https://codeclimate.com/github/kaspernj/acts_as_customized_attributes)
|
3
2
|
[](https://codeclimate.com/github/kaspernj/acts_as_customized_attributes)
|
3
|
+
[](https://app.shippable.com/projects/546b3f7bd46935d5fbbde6b9/builds/latest)
|
4
4
|
|
5
5
|
# ActsAsCustomizedAttributes
|
6
6
|
|
@@ -59,13 +59,13 @@ some_model.customized_attributes #=> {:my_custom_attribute => 5}
|
|
59
59
|
#### Query keys.
|
60
60
|
|
61
61
|
```ruby
|
62
|
-
|
62
|
+
SomeModelDataKey.where("name LIKE '%facebook%'")
|
63
63
|
```
|
64
64
|
|
65
65
|
### Query data
|
66
66
|
|
67
67
|
```ruby
|
68
|
-
|
68
|
+
SomeModelData.where("resource_id > 5")
|
69
69
|
```
|
70
70
|
|
71
71
|
### Optimize inserts with transactions for inserts / updates.
|
data/Rakefile
CHANGED
@@ -1,26 +1,30 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
+
# frozen_string_literal: true
|
2
3
|
begin
|
3
|
-
require
|
4
|
+
require "bundler/setup"
|
4
5
|
rescue LoadError
|
5
|
-
puts
|
6
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
6
7
|
end
|
7
8
|
begin
|
8
|
-
require
|
9
|
+
require "rdoc/task"
|
9
10
|
rescue LoadError
|
10
|
-
require
|
11
|
-
require
|
11
|
+
require "rdoc/rdoc"
|
12
|
+
require "rake/rdoctask"
|
12
13
|
RDoc::Task = Rake::RDocTask
|
13
14
|
end
|
14
15
|
|
15
16
|
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
-
rdoc.rdoc_dir =
|
17
|
-
rdoc.title =
|
18
|
-
rdoc.options <<
|
19
|
-
rdoc.rdoc_files.include(
|
20
|
-
rdoc.rdoc_files.include(
|
17
|
+
rdoc.rdoc_dir = "rdoc"
|
18
|
+
rdoc.title = "ActsAsCustomizedAttributes"
|
19
|
+
rdoc.options << "--line-numbers"
|
20
|
+
rdoc.rdoc_files.include("README.md")
|
21
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
21
22
|
end
|
22
23
|
|
23
24
|
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
-
load
|
25
|
+
load "rails/tasks/engine.rake"
|
26
|
+
|
27
|
+
require "best_practice_project"
|
28
|
+
BestPracticeProject.load_tasks
|
25
29
|
|
26
30
|
Bundler::GemHelper.install_tasks
|
data/config/routes.rb
CHANGED
@@ -1,20 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ActsAsCustomizedAttributes::ClassMethods
|
2
|
-
def acts_as_customized_attributes(
|
3
|
+
def acts_as_customized_attributes(_args = {})
|
3
4
|
$aaca_class_name_key = "#{name}DataKey"
|
4
5
|
$aaca_class_name_data = "#{name}Data"
|
5
6
|
$original_class_name = name
|
6
7
|
|
7
|
-
class_data_key = Class.new(
|
8
|
-
set_table_name
|
8
|
+
class_data_key = Class.new(ActiveRecord::Base) do
|
9
|
+
if respond_to?(:set_table_name)
|
10
|
+
set_table_name $aaca_class_name_key.tableize
|
11
|
+
else
|
12
|
+
self.table_name = $aaca_class_name_key.tableize
|
13
|
+
end
|
14
|
+
|
15
|
+
after_create :add_to_cache
|
16
|
+
after_update :add_to_cache
|
17
|
+
after_destroy :remove_from_cache
|
18
|
+
before_update :remove_from_cache
|
19
|
+
|
20
|
+
validates_presence_of :name
|
21
|
+
validate :validate_unique_name
|
9
22
|
|
10
|
-
has_many :data, class_name: $aaca_class_name_data, foreign_key: "data_key_id", dependent: :destroy
|
23
|
+
has_many :data, class_name: $aaca_class_name_data.to_s, table_name: $aaca_class_name_data.tableize.to_s, foreign_key: "data_key_id", dependent: :destroy
|
24
|
+
|
25
|
+
def self.id_for_name(name)
|
26
|
+
cache_name_to_id.fetch(name.to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.name_for_id(id)
|
30
|
+
cache_name_to_id.key(id) || raise(KeyError, "No such ID: #{id}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.cache_name_to_id
|
34
|
+
update_cache_name_to_id unless @cache_name_to_id
|
35
|
+
@cache_name_to_id
|
36
|
+
end
|
37
|
+
|
38
|
+
# Initializes / reloads the cache.
|
39
|
+
def self.update_cache_name_to_id
|
40
|
+
@cache_name_to_id = {}
|
41
|
+
find_each do |data_key|
|
42
|
+
@cache_name_to_id[data_key.name] = data_key.id
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def add_to_cache
|
49
|
+
self.class.cache_name_to_id[name.to_s] = id
|
50
|
+
end
|
51
|
+
|
52
|
+
def remove_from_cache
|
53
|
+
self.class.cache_name_to_id.delete(name_was)
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_unique_name
|
57
|
+
id_exists = self.class.id_for_name(name)
|
58
|
+
|
59
|
+
errors.add :name, :taken if id_exists != id
|
60
|
+
rescue KeyError
|
61
|
+
# No problem.
|
62
|
+
end
|
11
63
|
end
|
12
64
|
|
13
|
-
class_data = Class.new(
|
14
|
-
set_table_name
|
65
|
+
class_data = Class.new(ActiveRecord::Base) do
|
66
|
+
if respond_to?(:set_table_name)
|
67
|
+
set_table_name $aaca_class_name_data.tableize
|
68
|
+
else
|
69
|
+
self.table_name = $aaca_class_name_data.tableize
|
70
|
+
end
|
71
|
+
|
72
|
+
belongs_to :resource, class_name: $original_class_name.to_s
|
73
|
+
belongs_to :data_key, class_name: $aaca_class_name_key.to_s
|
74
|
+
|
75
|
+
validate :associated_resource_and_data_key
|
76
|
+
|
77
|
+
def self.key_class=(key_class)
|
78
|
+
@key_class = key_class
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.key_class
|
82
|
+
@key_class
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def associated_resource_and_data_key
|
88
|
+
return errors.add :data_key_id, "not valid" unless data_key_id?
|
15
89
|
|
16
|
-
|
17
|
-
|
90
|
+
if !resource_id? || !resource
|
91
|
+
return errors.add :resource_id, "not associated"
|
92
|
+
end
|
93
|
+
|
94
|
+
begin
|
95
|
+
self.class.key_class.name_for_id(data_key_id)
|
96
|
+
rescue KeyError
|
97
|
+
errors.add :data_key_id, "doesn't exist"
|
98
|
+
end
|
99
|
+
end
|
18
100
|
end
|
19
101
|
|
20
102
|
Object.const_set($aaca_class_name_key, class_data_key)
|
@@ -59,8 +141,9 @@ private
|
|
59
141
|
def migration_class
|
60
142
|
$acts_as_customized_attributes_keys_table_name = "#{name.downcase}_data_keys"
|
61
143
|
$acts_as_customized_attributes_table_name = "#{name.downcase}_data"
|
144
|
+
$table_name = table_name
|
62
145
|
|
63
|
-
|
146
|
+
Class.new(ActiveRecord::Migration) do
|
64
147
|
def up
|
65
148
|
create_table $acts_as_customized_attributes_keys_table_name do |t|
|
66
149
|
t.string :name
|
@@ -71,14 +154,13 @@ private
|
|
71
154
|
add_index $acts_as_customized_attributes_keys_table_name, :name, unique: true
|
72
155
|
|
73
156
|
create_table $acts_as_customized_attributes_table_name do |t|
|
74
|
-
t.belongs_to :resource
|
75
|
-
t.belongs_to :data_key
|
157
|
+
t.belongs_to :resource, index: true
|
158
|
+
t.belongs_to :data_key, index: true
|
76
159
|
t.string :value
|
77
160
|
t.timestamps
|
78
161
|
end
|
79
162
|
|
80
|
-
|
81
|
-
add_index $acts_as_customized_attributes_table_name, :resource_id
|
163
|
+
add_foreign_key $acts_as_customized_attributes_table_name, $table_name, column: "data_key_id", on_delete: :cascade
|
82
164
|
add_index $acts_as_customized_attributes_table_name, [:data_key_id, :resource_id], unique: true
|
83
165
|
end
|
84
166
|
|
@@ -1,13 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ActsAsCustomizedAttributes::InstanceMethods
|
2
3
|
def update_customized_attributes(data)
|
3
4
|
update_customized_attributes_with_args(data: data)
|
4
5
|
end
|
5
6
|
|
6
|
-
UPDATE_CUSTOMIZED_ATTRIBUTES_VALID_ARGS = [:data, :transactioner]
|
7
|
+
UPDATE_CUSTOMIZED_ATTRIBUTES_VALID_ARGS = [:data, :transactioner].freeze
|
7
8
|
def update_customized_attributes_with_args(args)
|
8
|
-
args.each { |key,
|
9
|
+
args.each { |key, _value| raise "Invalid argument: '#{key}'." unless UPDATE_CUSTOMIZED_ATTRIBUTES_VALID_ARGS.include?(key) }
|
9
10
|
|
10
|
-
args
|
11
|
+
args.fetch(:data).each do |key, value|
|
11
12
|
begin
|
12
13
|
key_id = self.class.aaca_key_class.id_for_name(key)
|
13
14
|
rescue KeyError
|
@@ -15,12 +16,12 @@ module ActsAsCustomizedAttributes::InstanceMethods
|
|
15
16
|
key_id = key_model.id
|
16
17
|
end
|
17
18
|
|
18
|
-
data_model =
|
19
|
+
data_model = data.where(data_key_id: key_id).first
|
19
20
|
if data_model
|
20
21
|
data_model.resource = self # Saves query when validating.
|
21
22
|
else
|
22
23
|
# Set resource in order to skip query when validating.
|
23
|
-
data_model =
|
24
|
+
data_model = data.new(data_key_id: key_id, resource: self)
|
24
25
|
end
|
25
26
|
|
26
27
|
data_model.value = value
|
@@ -45,6 +46,6 @@ module ActsAsCustomizedAttributes::InstanceMethods
|
|
45
46
|
hash[key_name.to_sym] = data_i.value
|
46
47
|
end
|
47
48
|
|
48
|
-
|
49
|
+
hash
|
49
50
|
end
|
50
51
|
end
|
data/spec/dummy/Rakefile
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
3
4
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
4
5
|
|
5
|
-
require File.expand_path(
|
6
|
+
require File.expand_path("../config/application", __FILE__)
|
6
7
|
|
7
8
|
Dummy::Application.load_tasks
|
data/spec/dummy/config.ru
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require File.expand_path("../boot", __FILE__)
|
2
3
|
|
3
|
-
require
|
4
|
+
require "rails/all"
|
4
5
|
|
5
6
|
Bundler.require
|
6
7
|
require "acts_as_customized_attributes"
|
@@ -39,7 +40,6 @@ module Dummy
|
|
39
40
|
config.assets.enabled = true
|
40
41
|
|
41
42
|
# Version of your assets, change this if you want to expire all your assets
|
42
|
-
config.assets.version =
|
43
|
+
config.assets.version = "1.0"
|
43
44
|
end
|
44
45
|
end
|
45
|
-
|
data/spec/dummy/config/boot.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "rubygems"
|
3
|
+
gemfile = File.expand_path("../../../../Gemfile", __FILE__)
|
3
4
|
|
4
5
|
if File.exist?(gemfile)
|
5
|
-
ENV[
|
6
|
-
require
|
6
|
+
ENV["BUNDLE_GEMFILE"] = gemfile
|
7
|
+
require "bundler"
|
7
8
|
Bundler.setup
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
+
$LOAD_PATH.unshift File.expand_path("../../../../lib", __FILE__)
|
@@ -1,42 +1,11 @@
|
|
1
|
-
# MySQL. Versions 4.1 and 5.0 are recommended.
|
2
|
-
#
|
3
|
-
# Install the MYSQL driver
|
4
|
-
# gem install mysql2
|
5
|
-
#
|
6
|
-
# Ensure the MySQL gem is defined in your Gemfile
|
7
|
-
# gem 'mysql2'
|
8
|
-
#
|
9
|
-
# And be sure to use new-style password hashing:
|
10
|
-
# http://dev.mysql.com/doc/refman/5.0/en/old-client.html
|
11
1
|
development:
|
12
|
-
adapter:
|
13
|
-
|
14
|
-
reconnect: false
|
15
|
-
database: dummy_development
|
16
|
-
pool: 5
|
17
|
-
username: root
|
18
|
-
password:
|
19
|
-
socket: /var/run/mysqld/mysqld.sock
|
2
|
+
adapter: sqlite3
|
3
|
+
database: db/development.sqlite3
|
20
4
|
|
21
|
-
# Warning: The database defined as "test" will be erased and
|
22
|
-
# re-generated from your development database when you run "rake".
|
23
|
-
# Do not set this db to the same as development or production.
|
24
5
|
test:
|
25
|
-
adapter:
|
26
|
-
|
27
|
-
reconnect: false
|
28
|
-
database: dummy_test
|
29
|
-
pool: 5
|
30
|
-
username: root
|
31
|
-
password:
|
32
|
-
socket: /var/run/mysqld/mysqld.sock
|
6
|
+
adapter: sqlite3
|
7
|
+
database: db/test.sqlite3
|
33
8
|
|
34
9
|
production:
|
35
|
-
adapter:
|
36
|
-
|
37
|
-
reconnect: false
|
38
|
-
database: dummy_production
|
39
|
-
pool: 5
|
40
|
-
username: root
|
41
|
-
password:
|
42
|
-
socket: /var/run/mysqld/mysqld.sock
|
10
|
+
adapter: sqlite3
|
11
|
+
database: db/production.sqlite3
|