hydra_attribute 0.3.2 → 0.4.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +1 -1
- data/README.md +7 -0
- data/features/entity/create.feature +128 -0
- data/features/entity/destroy.feature +111 -0
- data/features/entity/new.feature +121 -0
- data/features/entity/update.feature +147 -0
- data/features/{attributes → hydra_attribute}/create.feature +7 -7
- data/features/{attributes → hydra_attribute}/destroy.feature +2 -4
- data/features/{attributes → hydra_attribute}/update.feature +10 -10
- data/features/hydra_set/destroy.feature +31 -0
- data/features/migrations/create_and_drop.feature +165 -0
- data/features/migrations/migrate_and_rollback.feature +211 -0
- data/features/relation/query_methods/group.feature +42 -0
- data/features/relation/query_methods/order.feature +67 -0
- data/features/relation/query_methods/reorder.feature +29 -0
- data/features/relation/query_methods/reverse_order.feature +29 -0
- data/features/relation/query_methods/select.feature +50 -0
- data/features/relation/query_methods/where.feature +70 -0
- data/features/step_definitions/connections.rb +65 -0
- data/features/step_definitions/model_steps.rb +79 -6
- data/features/step_definitions/query_methods.rb +3 -3
- data/features/step_definitions/record_steps.rb +3 -4
- data/features/support/env.rb +17 -3
- data/features/support/world.rb +15 -10
- data/gemfiles/3.1.gemfile.lock +15 -15
- data/gemfiles/3.2.gemfile.lock +15 -15
- data/lib/hydra_attribute/active_record/association.rb +74 -38
- data/lib/hydra_attribute/active_record/association_preloader.rb +49 -49
- data/lib/hydra_attribute/active_record/attribute_methods.rb +37 -85
- data/lib/hydra_attribute/active_record/migration.rb +2 -2
- data/lib/hydra_attribute/active_record/reflection.rb +1 -1
- data/lib/hydra_attribute/active_record/relation/query_methods.rb +8 -7
- data/lib/hydra_attribute/active_record/relation.rb +1 -0
- data/lib/hydra_attribute/active_record.rb +20 -12
- data/lib/hydra_attribute/association_builder.rb +1 -2
- data/lib/hydra_attribute/builder.rb +7 -8
- data/lib/hydra_attribute/entity_callbacks.rb +12 -32
- data/lib/hydra_attribute/hydra_attribute.rb +25 -16
- data/lib/hydra_attribute/hydra_attribute_methods.rb +85 -0
- data/lib/hydra_attribute/hydra_methods.rb +123 -0
- data/lib/hydra_attribute/hydra_set.rb +36 -0
- data/lib/hydra_attribute/hydra_set_methods.rb +39 -0
- data/lib/hydra_attribute/hydra_value_methods.rb +14 -0
- data/lib/hydra_attribute/memoize.rb +37 -0
- data/lib/hydra_attribute/migrator.rb +100 -51
- data/lib/hydra_attribute/railtie.rb +1 -3
- data/lib/hydra_attribute/version.rb +1 -1
- data/lib/hydra_attribute.rb +7 -1
- data/spec/hydra_attribute_methods_spec.rb +458 -0
- data/spec/hydra_attribute_spec.rb +19 -0
- data/spec/hydra_methods_spec.rb +457 -0
- data/spec/hydra_set_methods_spec.rb +203 -0
- data/spec/hydra_set_spec.rb +19 -0
- data/spec/memoize_spec.rb +95 -0
- data/spec/spec_helper.rb +42 -2
- metadata +71 -43
- data/features/create.feature +0 -47
- data/features/define.feature +0 -38
- data/features/destroy.feature +0 -102
- data/features/query_methods/group.feature +0 -42
- data/features/query_methods/order.feature +0 -99
- data/features/query_methods/select.feature +0 -50
- data/features/query_methods/where.feature +0 -70
- data/features/support/schema.rb +0 -79
- data/features/update.feature +0 -114
@@ -0,0 +1,70 @@
|
|
1
|
+
Feature: hydra attribute where conditions
|
2
|
+
When filter by hydra attribute and this value is not nil
|
3
|
+
Then records with this attribute should be selected
|
4
|
+
|
5
|
+
When filter by hydra attribute and this value is nil
|
6
|
+
Then records with nil and blank value should be selected
|
7
|
+
|
8
|
+
Background: create hydra attributes
|
9
|
+
Given create hydra attributes for "Product" with role "admin" as "hashes":
|
10
|
+
| name | backend_type | white_list |
|
11
|
+
| code | string | [bool:t] |
|
12
|
+
| summary | string | [bool:t] |
|
13
|
+
| title | string | [bool:t] |
|
14
|
+
| price | float | [bool:t] |
|
15
|
+
| active | boolean | [bool:t] |
|
16
|
+
| state | integer | [bool:t] |
|
17
|
+
|
18
|
+
Scenario: filter by one hydra attribute
|
19
|
+
Given create "Product" model with attributes as "hashes":
|
20
|
+
| code | price |
|
21
|
+
| 1 | 2.75 |
|
22
|
+
| 2 | 2.75 |
|
23
|
+
| 3 | 2.76 |
|
24
|
+
| 4 | |
|
25
|
+
When filter "Product" by:
|
26
|
+
| field | value |
|
27
|
+
| price | 2.75 |
|
28
|
+
Then total records should be "2"
|
29
|
+
And records should have the following attributes:
|
30
|
+
| field | value |
|
31
|
+
| code | 1 |
|
32
|
+
| code | 2 |
|
33
|
+
|
34
|
+
Scenario: filter by one hydra attribute with nil value
|
35
|
+
Given create "Product" model with attributes as "hashes":
|
36
|
+
| code | price |
|
37
|
+
| 1 | |
|
38
|
+
| 2 | 0 |
|
39
|
+
| 3 | |
|
40
|
+
When filter "Product" by:
|
41
|
+
| field | value |
|
42
|
+
| price | [nil:] |
|
43
|
+
Then total records should be "2"
|
44
|
+
And records should have the following attributes:
|
45
|
+
| field | value |
|
46
|
+
| code | 1 |
|
47
|
+
| code | 3 |
|
48
|
+
|
49
|
+
Scenario: filter by several fields including both the hydra and general attributes
|
50
|
+
Given create "Product" model with attributes as "hashes":
|
51
|
+
| name | code | title | price | active | state | summary |
|
52
|
+
| toy | 1 | story | 2.40 | 1 | | |
|
53
|
+
| toy | 2 | story | 2.45 | 1 | | |
|
54
|
+
| toy | 3 | story | 2.45 | 1 | | |
|
55
|
+
| toy | 4 | | 2.45 | 0 | | |
|
56
|
+
| | 5 | | 2.45 | 1 | | |
|
57
|
+
| toy | 6 | | 2.46 | 1 | | |
|
58
|
+
When filter "Product" by:
|
59
|
+
| field | value |
|
60
|
+
| name | toy |
|
61
|
+
| title | story |
|
62
|
+
| summary | [nil:] |
|
63
|
+
| price | [float:2.45] |
|
64
|
+
| active | [bool:t] |
|
65
|
+
| state | [nil:] |
|
66
|
+
Then total records should be "2"
|
67
|
+
And records should have the following attributes:
|
68
|
+
| field | value |
|
69
|
+
| code | 2 |
|
70
|
+
| code | 3 |
|
@@ -0,0 +1,65 @@
|
|
1
|
+
Given /^create connection$/ do
|
2
|
+
spec = ActiveRecord::Base::ConnectionSpecification.new({database: ':memory:', adapter: 'sqlite3'}, 'sqlite3_connection')
|
3
|
+
@connection = ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec).connection
|
4
|
+
end
|
5
|
+
|
6
|
+
Given /^(create|drop|migrate|rollback)(?:\sto|\sfrom)? hydra entity "([^"]+)"$/ do |method, table|
|
7
|
+
HydraAttribute::Migrator.send(method, @connection, table)
|
8
|
+
end
|
9
|
+
|
10
|
+
Given /^create table "([^"]+)"$/ do |table|
|
11
|
+
@connection.create_table(table)
|
12
|
+
end
|
13
|
+
|
14
|
+
Then /^should have the following (\d+) tables?:$/ do |count, table|
|
15
|
+
@connection.should have(count.to_i).tables
|
16
|
+
|
17
|
+
table.rows.flatten.each do |name|
|
18
|
+
@connection.tables.should include(name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^should not have any tables$/ do
|
23
|
+
@connection.should have(0).tables
|
24
|
+
end
|
25
|
+
|
26
|
+
Then /^table "([^"]+)" should have the following (columns|indexes):$/ do |table_name, method, table|
|
27
|
+
connection_params = @connection.send(method, table_name).sort_by(&:name)
|
28
|
+
checked_params = table.hashes.map { |hash| type_cast_hash(hash) }.sort_by { |param| param['name'] }
|
29
|
+
|
30
|
+
unless connection_params.length == checked_params.length
|
31
|
+
raise %(Table "#{table_name}" has "#{connection_params.length}" #{method} but in our test "#{checked_params.length}". Diff: is "#{connection_params.map(&:name)}" but should be "#{checked_params.map { |h| h['name'] }}")
|
32
|
+
end
|
33
|
+
|
34
|
+
connection_params.zip(checked_params).each do |(real_params, params)|
|
35
|
+
params.keys.each do |name|
|
36
|
+
params[name].should == real_params.send(name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Then /^table "([^"]+)" should have (\d+) records?$/ do |table_name, count|
|
42
|
+
result = ActiveRecord::Base.connection.select_one("SELECT COUNT(*) AS count FROM #{table_name}")
|
43
|
+
result['count'].should == count.to_i
|
44
|
+
end
|
45
|
+
|
46
|
+
Then /^table "([^"]+)" should have (\d+) records?:$/ do |table_name, count, table|
|
47
|
+
step %(table "#{table_name}" should have #{count} records)
|
48
|
+
|
49
|
+
table.hashes.each do |hash|
|
50
|
+
table = Arel::Table.new(table_name, ActiveRecord::Base)
|
51
|
+
select = Arel.sql('COUNT(*)').as('count')
|
52
|
+
where = hash.map { |name, value| table[name].eq(type_cast_value(value)) }.inject(:and)
|
53
|
+
|
54
|
+
result = ActiveRecord::Base.connection.select_one(table.project(select).where(where))
|
55
|
+
unless result['count']
|
56
|
+
raise %(Query "#{table.project(select).where(where).to_sql}" return nil)
|
57
|
+
end
|
58
|
+
|
59
|
+
unless result['count'] == 1
|
60
|
+
raise %(Query "#{table.project(select).where(where).to_sql}" return "#{result['count']}")
|
61
|
+
end
|
62
|
+
result['count'].should be(1)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -6,6 +6,34 @@ Given /^create "([^"]+)" model$/ do |klass|
|
|
6
6
|
klass.constantize.create!
|
7
7
|
end
|
8
8
|
|
9
|
+
Given /^build "([^"]+)" model$/ do |klass|
|
10
|
+
@model = klass.constantize.new
|
11
|
+
end
|
12
|
+
|
13
|
+
Given /^build "([^"]+)" model:$/ do |klass, table|
|
14
|
+
@model = klass.constantize.new(type_cast_hash(table.rows_hash))
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^set "([^"]+)" to "([^"]+)"$/ do |attribute, value|
|
18
|
+
@model.send("#{attribute}=", type_cast_value(value))
|
19
|
+
end
|
20
|
+
|
21
|
+
When /^(save|destroy) model$/ do |method|
|
22
|
+
@model.send(method)
|
23
|
+
end
|
24
|
+
|
25
|
+
When /^find "([^"]+)" model by attribute "([^"]+)" and value "([^"]+)"$/ do |class_name, attribute, value|
|
26
|
+
@model = class_name.constantize.send("find_by_#{attribute}", type_cast_value(value))
|
27
|
+
end
|
28
|
+
|
29
|
+
When /^find (first|last) "([^"]+)" model$/ do |method, class_name|
|
30
|
+
@model = class_name.constantize.send(method)
|
31
|
+
end
|
32
|
+
|
33
|
+
When /^reload model$/ do
|
34
|
+
@model.reload
|
35
|
+
end
|
36
|
+
|
9
37
|
Given /^create "([^"]+)" model with attributes as "([^"]+):"$/ do |klass, format, table|
|
10
38
|
Array.wrap(table.send(format)).each do |hash|
|
11
39
|
klass.constantize.create!(type_cast_hash(hash))
|
@@ -18,6 +46,26 @@ Given /^create hydra attributes for "([^"]+)" with role "([^"]+)" as "([^"]+)":$
|
|
18
46
|
end
|
19
47
|
end
|
20
48
|
|
49
|
+
Given /^create hydra sets for "([^"]+)" as "([^"]+)":$/ do |klass, format, table|
|
50
|
+
Array.wrap(table.send(format)).each do |hash|
|
51
|
+
step %(create hydra set "#{hash['name']}" for "#{klass}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Given /^create hydra set "([^"]+)" for "([^"]+)"$/ do |hydra_set_name, klass|
|
56
|
+
klass.constantize.hydra_sets.create!(name: type_cast_value(hydra_set_name))
|
57
|
+
end
|
58
|
+
|
59
|
+
Given /^add "([^"]+)" hydra attributes to hydra set:$/ do |klass, table|
|
60
|
+
klass = klass.constantize
|
61
|
+
|
62
|
+
Array.wrap(table.hashes).each do |hash|
|
63
|
+
Array.wrap(type_cast_value(hash['hydra set name'])).each do |set|
|
64
|
+
klass.hydra_sets.find_by_name(set).hydra_attributes << klass.hydra_attributes.find_by_name(type_cast_value(hash['hydra attribute name']))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
21
69
|
Given /^(load and )?(save|create|update(?: all| attributes)?|destroy(?: all)?|delete(?: all)?)(?: for)? "([^"]+)" models? with attributes as "([^"]+)":$/ do |load, action, klass, format, table|
|
22
70
|
action = action.gsub(' ', '_')
|
23
71
|
klass = klass.constantize
|
@@ -30,20 +78,45 @@ Given /^(load and )?(save|create|update(?: all| attributes)?|destroy(?: all)?|de
|
|
30
78
|
end
|
31
79
|
end
|
32
80
|
|
33
|
-
Then /^model
|
34
|
-
|
81
|
+
Then /^model (should(?:\snot)?) respond to "([^"]+)"$/ do |method, attributes|
|
82
|
+
method = method.gsub(/\s+/, '_')
|
83
|
+
attributes.split.each do |attribute|
|
84
|
+
@model.send(method, respond_to(attribute))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Then /^model attributes (should(?:\snot)?) include "([^"]+)"$/ do |method, attributes|
|
35
89
|
method = method.gsub(/\s+/, '_')
|
36
90
|
attributes.split.each do |attribute|
|
37
|
-
model.send(method,
|
91
|
+
@model.attributes.keys.send(method, include(attribute))
|
38
92
|
end
|
39
93
|
end
|
40
94
|
|
41
|
-
Then /^(
|
42
|
-
|
43
|
-
|
95
|
+
Then /^model attributes (should(?:\snot)?) match "([^"]+)"$/ do |match, attribute|
|
96
|
+
@model.attributes.keys.send(match) =~ Array(type_cast_value(attribute))
|
97
|
+
end
|
98
|
+
|
99
|
+
Then /^model "([^"]+)" (should(?:\snot)?) respond to "([^"]+)"$/ do |klass, method, attributes|
|
100
|
+
@model = klass.constantize.new
|
101
|
+
step %(model #{method} respond to "#{attributes}")
|
102
|
+
end
|
103
|
+
|
104
|
+
Then /^error "([^"]+)" (should(?:\snot)?) be risen when methods? "([^"]+)" (?:is|are) called$/ do |error_class, expect, methods|
|
105
|
+
Array.wrap(methods.split).each do |method|
|
106
|
+
lambda { @model.send(method) }.send(expect.gsub(/\s+/, '_'), raise_error(error_class.constantize))
|
44
107
|
end
|
45
108
|
end
|
46
109
|
|
110
|
+
Then /^(last|first) created "([^"]+)" (should|should not) have the following attributes:$/ do |position, klass, match, table|
|
111
|
+
table.rows_hash.each do |attribute, value|
|
112
|
+
step %(#{position} created "#{klass}" #{match} have attribute "#{attribute}" with value "#{value}")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
Then /^(last|first) created "([^"]+)" (should|should not) have attribute "([^"]+)" with value "([^"]+)"$/ do |position, klass, match, attribute, value|
|
117
|
+
klass.constantize.send(position).send(attribute).send(match) == type_cast_value(value)
|
118
|
+
end
|
119
|
+
|
47
120
|
Then /^class "([^"]+)" (should(?:\snot)?) have "([^"]+)" in white list$/ do |klass, accept, attribute|
|
48
121
|
method = accept.sub(' ', '_')
|
49
122
|
klass.constantize.accessible_attributes.send(method, include(attribute))
|
@@ -5,7 +5,7 @@ end
|
|
5
5
|
|
6
6
|
When /^filter "([^"]+)" records by "([^"]+)"$/ do |klass, attribute|
|
7
7
|
@records = Object.const_get(klass)
|
8
|
-
step %
|
8
|
+
step %(filter records by "#{attribute}")
|
9
9
|
end
|
10
10
|
|
11
11
|
When /^filter records by "([^"]+)"$/ do |attribute|
|
@@ -15,7 +15,7 @@ end
|
|
15
15
|
|
16
16
|
When /^group "([^"]+)" by "([^"]+)"$/ do |klass, attributes|
|
17
17
|
@records = Object.const_get(klass)
|
18
|
-
step %
|
18
|
+
step %(group by "#{attributes}")
|
19
19
|
end
|
20
20
|
|
21
21
|
When /^group by "([^"]+)"$/ do |attributes|
|
@@ -24,7 +24,7 @@ end
|
|
24
24
|
|
25
25
|
When /^(order|reorder) "([^"]+)" records by "([^"]+)"$/ do |sort_method, klass, attributes|
|
26
26
|
@records = Object.const_get(klass)
|
27
|
-
step %
|
27
|
+
step %(#{sort_method} records by "#{attributes}")
|
28
28
|
end
|
29
29
|
|
30
30
|
When /^(order|reorder) records by "([^"]+)"$/ do |sort_method, attributes|
|
@@ -58,11 +58,10 @@ Then /^records should have only the following "([^"]+)" names$/ do |attributes|
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
Then /^records should raise "([^"]+)" when call the following "([^"]+)"$/ do |
|
62
|
-
error_class = error.constantize
|
61
|
+
Then /^records should raise "([^"]+)" when call the following "([^"]+)"$/ do |error_class, methods|
|
63
62
|
@records.each do |record|
|
64
63
|
methods.split(/\s+/).each do |method|
|
65
|
-
lambda { record.send(method) }.should raise_error(error_class)
|
64
|
+
lambda { record.send(method) }.should raise_error(error_class.constantize)
|
66
65
|
end
|
67
66
|
end
|
68
67
|
end
|
@@ -73,7 +72,7 @@ end
|
|
73
72
|
|
74
73
|
Then /^total "([^"]+)" records should be "([^"]+)"$/ do |klass, count|
|
75
74
|
@records = klass.constantize.scoped
|
76
|
-
step %
|
75
|
+
step %(total records should be "#{count}")
|
77
76
|
end
|
78
77
|
|
79
78
|
Then /^records "(should|should_not)" have loaded associations:$/ do |should, table|
|
data/features/support/env.rb
CHANGED
@@ -1,19 +1,33 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'hydra_attribute'
|
3
3
|
require 'database_cleaner'
|
4
|
-
require 'database_cleaner/cucumber'
|
5
4
|
|
6
5
|
ActiveSupport.on_load(:active_record) do
|
7
6
|
self.default_timezone = :utc
|
8
|
-
unless ActiveRecord::VERSION::STRING.start_with?('3.1.')
|
7
|
+
unless ActiveRecord::VERSION::STRING.start_with?('3.1.') # @COMPATIBILITY with 3.1.x. active_record 3.1 doesn't have "mass_assignment_sanitizer" method
|
9
8
|
self.mass_assignment_sanitizer = :strict
|
10
9
|
end
|
11
|
-
|
10
|
+
|
11
|
+
ActiveRecord::Migration.send(:include, HydraAttribute::ActiveRecord::Migration)
|
12
12
|
end
|
13
13
|
|
14
14
|
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
15
15
|
DatabaseCleaner.strategy = :truncation
|
16
16
|
|
17
|
+
class Migration < ActiveRecord::Migration
|
18
|
+
def up
|
19
|
+
create_hydra_entity :products do |t|
|
20
|
+
t.string :name
|
21
|
+
t.timestamps
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def down
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Migration.new.up
|
30
|
+
|
17
31
|
Before do
|
18
32
|
redefine_hydra_entity('Product')
|
19
33
|
DatabaseCleaner.start
|
data/features/support/world.rb
CHANGED
@@ -3,15 +3,19 @@ module HydraAttribute
|
|
3
3
|
module World
|
4
4
|
def type_cast_value(schema)
|
5
5
|
return schema unless schema.is_a?(String)
|
6
|
-
type, value = schema.gsub(
|
6
|
+
type, value = schema.gsub(/(^\[)|(\]$)/, '').split(':', 2)
|
7
7
|
return schema if schema == type && value.nil?
|
8
8
|
|
9
9
|
case type
|
10
|
-
when '
|
11
|
-
when 'float'
|
12
|
-
when '
|
13
|
-
when 'nil'
|
14
|
-
when '
|
10
|
+
when 'int' then type_cast_value(value).to_i
|
11
|
+
when 'float' then type_cast_value(value).to_f
|
12
|
+
when 'bool' then ::ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(type_cast_value(value))
|
13
|
+
when 'nil' then nil
|
14
|
+
when 'date' then ActiveSupport::TimeZone.new('UTC').parse(type_cast_value(value))
|
15
|
+
when 'sym' then type_cast_value(value).to_sym
|
16
|
+
when 'array' then value.split(',').map { |v| type_cast_value(v) }
|
17
|
+
when 'eval' then eval(type_cast_value(value))
|
18
|
+
when 'str' then type_cast_value(value).to_s
|
15
19
|
else value
|
16
20
|
end
|
17
21
|
end
|
@@ -22,7 +26,8 @@ module HydraAttribute
|
|
22
26
|
end
|
23
27
|
|
24
28
|
def type_cast_attributes(attributes)
|
25
|
-
|
29
|
+
# 'a=[b c] c=a c=[v abc]' => ["a=[b c]", "c=a", "c=[v abc]"]
|
30
|
+
attributes.gsub(/\s+(\w+=)/, '<###>\1').split('<###>').each_with_object({}) do |attribute, hash|
|
26
31
|
name, value = type_cast_attribute(attribute)
|
27
32
|
hash[name] = value
|
28
33
|
end
|
@@ -39,15 +44,15 @@ module HydraAttribute
|
|
39
44
|
|
40
45
|
Object.send(:remove_const, klass.to_sym) if Object.const_defined?(klass.to_sym)
|
41
46
|
|
42
|
-
::HydraAttribute::
|
47
|
+
::HydraAttribute::SUPPORTED_BACKEND_TYPES.each do |type|
|
43
48
|
class_name = "Hydra#{type.capitalize}#{klass}".to_sym
|
44
49
|
::HydraAttribute.send(:remove_const, class_name) if ::HydraAttribute.const_defined?(class_name)
|
45
50
|
end
|
46
51
|
|
47
52
|
Object.const_set(klass.to_sym, Class.new(::ActiveRecord::Base))
|
48
53
|
klass.to_s.constantize.send(:accessible_attributes_configs).values.each(&:clear)
|
49
|
-
klass.to_s.constantize.attr_accessible :name
|
50
|
-
klass.to_s.constantize.
|
54
|
+
klass.to_s.constantize.attr_accessible :name, :hydra_set_id
|
55
|
+
klass.to_s.constantize.send(:include, ::HydraAttribute::ActiveRecord)
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
data/gemfiles/3.1.gemfile.lock
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
PATH
|
2
2
|
remote: /Users/kostyantyn/Sites/github/gems/hydra_attribute
|
3
3
|
specs:
|
4
|
-
hydra_attribute (0.
|
4
|
+
hydra_attribute (0.4.0.beta)
|
5
5
|
activerecord (>= 3.1.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (3.1.
|
11
|
-
activesupport (= 3.1.
|
10
|
+
activemodel (3.1.7)
|
11
|
+
activesupport (= 3.1.7)
|
12
12
|
builder (~> 3.0.0)
|
13
13
|
i18n (~> 0.6)
|
14
|
-
activerecord (3.1.
|
15
|
-
activemodel (= 3.1.
|
16
|
-
activesupport (= 3.1.
|
14
|
+
activerecord (3.1.7)
|
15
|
+
activemodel (= 3.1.7)
|
16
|
+
activesupport (= 3.1.7)
|
17
17
|
arel (~> 2.2.3)
|
18
18
|
tzinfo (~> 0.3.29)
|
19
|
-
activesupport (3.1.
|
19
|
+
activesupport (3.1.7)
|
20
20
|
multi_json (>= 1.0, < 1.3)
|
21
21
|
appraisal (0.4.1)
|
22
22
|
bundler
|
@@ -33,17 +33,17 @@ GEM
|
|
33
33
|
gherkin (2.11.1)
|
34
34
|
json (>= 1.4.6)
|
35
35
|
i18n (0.6.0)
|
36
|
-
json (1.7.
|
36
|
+
json (1.7.4)
|
37
37
|
multi_json (1.2.0)
|
38
38
|
rake (0.9.2.2)
|
39
|
-
rspec (2.
|
40
|
-
rspec-core (~> 2.
|
41
|
-
rspec-expectations (~> 2.
|
42
|
-
rspec-mocks (~> 2.
|
43
|
-
rspec-core (2.
|
44
|
-
rspec-expectations (2.
|
39
|
+
rspec (2.11.0)
|
40
|
+
rspec-core (~> 2.11.0)
|
41
|
+
rspec-expectations (~> 2.11.0)
|
42
|
+
rspec-mocks (~> 2.11.0)
|
43
|
+
rspec-core (2.11.1)
|
44
|
+
rspec-expectations (2.11.2)
|
45
45
|
diff-lcs (~> 1.1.3)
|
46
|
-
rspec-mocks (2.
|
46
|
+
rspec-mocks (2.11.1)
|
47
47
|
sqlite3 (1.3.6)
|
48
48
|
tzinfo (0.3.33)
|
49
49
|
|
data/gemfiles/3.2.gemfile.lock
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: /Users/kostyantyn/Sites/github/gems/hydra_attribute
|
3
3
|
specs:
|
4
|
-
hydra_attribute (0.
|
4
|
+
hydra_attribute (0.4.0.beta)
|
5
5
|
activerecord (>= 3.1.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (3.2.
|
11
|
-
activesupport (= 3.2.
|
10
|
+
activemodel (3.2.7)
|
11
|
+
activesupport (= 3.2.7)
|
12
12
|
builder (~> 3.0.0)
|
13
|
-
activerecord (3.2.
|
14
|
-
activemodel (= 3.2.
|
15
|
-
activesupport (= 3.2.
|
13
|
+
activerecord (3.2.7)
|
14
|
+
activemodel (= 3.2.7)
|
15
|
+
activesupport (= 3.2.7)
|
16
16
|
arel (~> 3.0.2)
|
17
17
|
tzinfo (~> 0.3.29)
|
18
|
-
activesupport (3.2.
|
18
|
+
activesupport (3.2.7)
|
19
19
|
i18n (~> 0.6)
|
20
20
|
multi_json (~> 1.0)
|
21
21
|
appraisal (0.4.1)
|
@@ -33,17 +33,17 @@ GEM
|
|
33
33
|
gherkin (2.11.1)
|
34
34
|
json (>= 1.4.6)
|
35
35
|
i18n (0.6.0)
|
36
|
-
json (1.7.
|
36
|
+
json (1.7.4)
|
37
37
|
multi_json (1.3.6)
|
38
38
|
rake (0.9.2.2)
|
39
|
-
rspec (2.
|
40
|
-
rspec-core (~> 2.
|
41
|
-
rspec-expectations (~> 2.
|
42
|
-
rspec-mocks (~> 2.
|
43
|
-
rspec-core (2.
|
44
|
-
rspec-expectations (2.
|
39
|
+
rspec (2.11.0)
|
40
|
+
rspec-core (~> 2.11.0)
|
41
|
+
rspec-expectations (~> 2.11.0)
|
42
|
+
rspec-mocks (~> 2.11.0)
|
43
|
+
rspec-core (2.11.1)
|
44
|
+
rspec-expectations (2.11.2)
|
45
45
|
diff-lcs (~> 1.1.3)
|
46
|
-
rspec-mocks (2.
|
46
|
+
rspec-mocks (2.11.1)
|
47
47
|
sqlite3 (1.3.6)
|
48
48
|
tzinfo (0.3.33)
|
49
49
|
|
@@ -2,76 +2,112 @@ module HydraAttribute
|
|
2
2
|
module ActiveRecord
|
3
3
|
class Association < ::ActiveRecord::Associations::HasManyAssociation
|
4
4
|
|
5
|
-
def find_model(
|
5
|
+
def find_model(hydra_attribute_id)
|
6
6
|
load_target unless loaded?
|
7
|
-
|
8
|
-
|
7
|
+
|
8
|
+
hydra_set_target.detect do |model|
|
9
|
+
model.hydra_attribute_id == hydra_attribute_id
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
12
|
-
def find_model_or_build(
|
13
|
-
find_model(
|
13
|
+
def find_model_or_build(options = {})
|
14
|
+
find_model(options[:hydra_attribute_id]) || build(options)
|
14
15
|
end
|
15
16
|
|
16
17
|
def build(attributes = {}, options = {}, &block)
|
17
|
-
return if
|
18
|
+
return if hydra_attribute_ids.exclude?(attributes[:hydra_attribute_id])
|
19
|
+
return if target.any? { |model| model.hydra_attribute_id == attributes[:hydra_attribute_id] }
|
20
|
+
|
18
21
|
super
|
19
22
|
end
|
20
23
|
|
21
24
|
def all_models
|
22
25
|
unless @full_loaded
|
23
|
-
(
|
26
|
+
(hydra_attribute_ids - target.map(&:hydra_attribute_id)).each do |hydra_attribute_id|
|
24
27
|
build(hydra_attribute_id: hydra_attribute_id)
|
25
28
|
end
|
26
29
|
@full_loaded = true
|
27
30
|
end
|
28
|
-
|
31
|
+
hydra_set_target
|
29
32
|
end
|
30
33
|
|
31
|
-
def
|
32
|
-
|
34
|
+
def save
|
35
|
+
changed = false
|
36
|
+
all_models.each do |model|
|
37
|
+
model.entity_id = owner.id
|
38
|
+
model.save
|
39
|
+
changed = true unless model.previous_changes.blank?
|
40
|
+
end
|
41
|
+
changed
|
33
42
|
end
|
34
|
-
alias_method :locked_for_build?, :locked_for_build
|
35
43
|
|
36
|
-
def
|
37
|
-
@
|
38
|
-
@white_list_for_build = Array(white_list_for_build)
|
44
|
+
def lock!(white_list = [])
|
45
|
+
@white_list = Array(white_list)
|
39
46
|
loaded!
|
40
47
|
end
|
41
48
|
|
42
|
-
def
|
43
|
-
@
|
49
|
+
def hydra_attributes
|
50
|
+
if @white_list
|
51
|
+
@hydra_attributes ||= owner.class.hydra_set_attributes_for_backend_type(owner.hydra_set_id, reflection.backend_type)
|
52
|
+
else
|
53
|
+
owner.class.hydra_set_attributes_for_backend_type(owner.hydra_set_id, reflection.backend_type)
|
54
|
+
end
|
44
55
|
end
|
45
56
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
57
|
+
def hydra_attribute_ids
|
58
|
+
if @white_list
|
59
|
+
@hydra_attribute_ids ||= owner.class.hydra_set_attribute_ids_for_backend_type(owner.hydra_set_id, reflection.backend_type) & @white_list
|
60
|
+
else
|
61
|
+
owner.class.hydra_set_attribute_ids_for_backend_type(owner.hydra_set_id, reflection.backend_type)
|
62
|
+
end
|
50
63
|
end
|
51
64
|
|
52
|
-
|
65
|
+
def hydra_attribute_names
|
66
|
+
if @white_list
|
67
|
+
hydra_attributes.map(&:name)
|
68
|
+
else
|
69
|
+
owner.class.hydra_set_attribute_names_for_backend_type(owner.hydra_set_id, reflection.backend_type)
|
70
|
+
end
|
71
|
+
end
|
53
72
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
record
|
73
|
+
def hydra_set_target
|
74
|
+
@hydra_set_target ||= target.select do |model|
|
75
|
+
hydra_attribute_ids.include?(model.hydra_attribute_id)
|
76
|
+
end
|
59
77
|
end
|
60
78
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
79
|
+
def clear_cache!
|
80
|
+
@hydra_attributes = nil
|
81
|
+
@hydra_attribute_ids = nil
|
82
|
+
@full_loaded = nil
|
83
|
+
@hydra_set_target = nil
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
68
87
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
88
|
+
# Optimized method
|
89
|
+
# Remove unnecessary callbacks
|
90
|
+
def add_to_target(record)
|
91
|
+
@target << record
|
92
|
+
record
|
93
|
+
end
|
94
|
+
|
95
|
+
# Optimized method
|
96
|
+
# Attributes are written via low level function without additional checks
|
97
|
+
def build_record(options, _)
|
98
|
+
reflection.klass.new do |record|
|
99
|
+
unless options.has_key?(:value)
|
100
|
+
options[:value] = owner.class.hydra_attribute(options[:hydra_attribute_id]).default_value
|
101
|
+
end
|
102
|
+
|
103
|
+
record.send :write_attribute, 'id', options[:id]
|
104
|
+
record.send :write_attribute, 'entity_id', owner.id
|
105
|
+
record.send :write_attribute, 'hydra_attribute_id', options[:hydra_attribute_id]
|
106
|
+
record.send :write_attribute, 'value', options[:value]
|
107
|
+
|
108
|
+
hydra_set_target << record unless hydra_set_target.include?(record)
|
109
|
+
end
|
73
110
|
end
|
74
|
-
end
|
75
111
|
end
|
76
112
|
end
|
77
113
|
end
|