hydra_attribute 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/Appraisals +7 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +122 -0
- data/Rakefile +12 -0
- data/features/attribute_methods.feature +151 -0
- data/features/define_attributes.feature +61 -0
- data/features/load_associations.feature +45 -0
- data/features/order_conditions.feature +93 -0
- data/features/select_attributes.feature +56 -0
- data/features/step_definitions/class_steps.rb +32 -0
- data/features/step_definitions/model_steps.rb +31 -0
- data/features/step_definitions/record_steps.rb +103 -0
- data/features/support/env.rb +24 -0
- data/features/support/schema.rb +51 -0
- data/features/support/world.rb +31 -0
- data/features/typecast_attributes.feature +29 -0
- data/features/where_conditions.feature +77 -0
- data/gemfiles/3.1.gemfile +7 -0
- data/gemfiles/3.1.gemfile.lock +60 -0
- data/gemfiles/3.2.gemfile +7 -0
- data/gemfiles/3.2.gemfile.lock +60 -0
- data/hydra_attribute.gemspec +24 -0
- data/lib/generators/hydra_attribute/install/USAGE +8 -0
- data/lib/generators/hydra_attribute/install/install_generator.rb +11 -0
- data/lib/generators/hydra_attribute/install/templates/hydra_attribute.txt +11 -0
- data/lib/hydra_attribute.rb +31 -0
- data/lib/hydra_attribute/active_record.rb +7 -0
- data/lib/hydra_attribute/active_record/attribute_methods.rb +72 -0
- data/lib/hydra_attribute/active_record/attribute_methods/before_type_cast.rb +16 -0
- data/lib/hydra_attribute/active_record/attribute_methods/read.rb +13 -0
- data/lib/hydra_attribute/active_record/relation.rb +44 -0
- data/lib/hydra_attribute/active_record/relation/query_methods.rb +162 -0
- data/lib/hydra_attribute/active_record/scoping.rb +15 -0
- data/lib/hydra_attribute/association_builder.rb +40 -0
- data/lib/hydra_attribute/attribute_builder.rb +57 -0
- data/lib/hydra_attribute/attribute_proxy.rb +16 -0
- data/lib/hydra_attribute/builder.rb +25 -0
- data/lib/hydra_attribute/configuration.rb +47 -0
- data/lib/hydra_attribute/migration.rb +27 -0
- data/lib/hydra_attribute/railtie.rb +9 -0
- data/lib/hydra_attribute/version.rb +3 -0
- data/spec/hydra_attribute/active_record/relation/query_methods_spec.rb +286 -0
- data/spec/hydra_attribute/active_record/relation_spec.rb +93 -0
- data/spec/hydra_attribute/active_record/scoping_spec.rb +19 -0
- data/spec/hydra_attribute/active_record_spec.rb +20 -0
- data/spec/hydra_attribute/association_builder_spec.rb +95 -0
- data/spec/hydra_attribute/attribute_builder_spec.rb +70 -0
- data/spec/hydra_attribute/attribute_helpers_spec.rb +70 -0
- data/spec/hydra_attribute/builder_spec.rb +39 -0
- data/spec/hydra_attribute/configuration_spec.rb +96 -0
- data/spec/hydra_attribute_spec.rb +20 -0
- data/spec/spec_helper.rb +17 -0
- metadata +196 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
Feature: order conditions by hydra attributes
|
2
|
+
When order records by hydra attribute
|
3
|
+
Then correct table should be joined and order by value should be added
|
4
|
+
|
5
|
+
When correct table is already joined
|
6
|
+
Then only order condition should be added
|
7
|
+
|
8
|
+
When order by several attributes
|
9
|
+
Then order all of them by ascending
|
10
|
+
|
11
|
+
When reorder by attributes
|
12
|
+
Then old hydra attributes should be removed and new should be added
|
13
|
+
|
14
|
+
Background: create models and describe hydra attributes
|
15
|
+
Given removed constants if they exist:
|
16
|
+
| name |
|
17
|
+
| GroupProduct |
|
18
|
+
| SimpleProduct |
|
19
|
+
| Product |
|
20
|
+
And create model class "Product"
|
21
|
+
And create model class "SimpleProduct" as "Product" with hydra attributes:
|
22
|
+
| type | name |
|
23
|
+
| integer | code |
|
24
|
+
| integer | state |
|
25
|
+
| string | title |
|
26
|
+
|
27
|
+
Scenario Outline: order by one field
|
28
|
+
Given create models:
|
29
|
+
| model | attributes |
|
30
|
+
| SimpleProduct | name=[string:c] code=[integer:1] state=[integer:1] |
|
31
|
+
| SimpleProduct | name=[string:b] code=[integer:2] state=[integer:2] |
|
32
|
+
| SimpleProduct | name=[string:a] code=[integer:3] state=[integer:3] |
|
33
|
+
When order "SimpleProduct" records by "<attributes>"
|
34
|
+
Then "first" record should have "<first>"
|
35
|
+
And "last" record should have "<last>"
|
36
|
+
|
37
|
+
Scenarios: order conditions
|
38
|
+
| attributes | first | last |
|
39
|
+
| state=asc | code=[integer:1] | code=[integer:3] |
|
40
|
+
| state=desc | code=[integer:3] | code=[integer:1] |
|
41
|
+
| name=asc | code=[integer:3] | code=[integer:1] |
|
42
|
+
| name=desc | code=[integer:1] | code=[integer:3] |
|
43
|
+
|
44
|
+
Scenario Outline: order by several fields
|
45
|
+
Given create models:
|
46
|
+
| model | attributes |
|
47
|
+
| SimpleProduct | name=[string:c] code=[integer:1] state=[integer:1] title=[string:b] |
|
48
|
+
| SimpleProduct | name=[string:b] code=[integer:2] state=[integer:2] title=[string:a] |
|
49
|
+
| SimpleProduct | name=[string:a] code=[integer:3] state=[integer:3] title=[string:c] |
|
50
|
+
When order "SimpleProduct" records by "<attributes>"
|
51
|
+
Then "first" record should have "<first>"
|
52
|
+
And "last" record should have "<last>"
|
53
|
+
|
54
|
+
Scenarios: order conditions
|
55
|
+
| attributes | first | last |
|
56
|
+
| name state | code=[integer:3] | code=[integer:1] |
|
57
|
+
| state title | code=[integer:1] | code=[integer:3] |
|
58
|
+
| title state | code=[integer:2] | code=[integer:3] |
|
59
|
+
|
60
|
+
Scenario Outline: order by already joined field
|
61
|
+
Given create models:
|
62
|
+
| model | attributes |
|
63
|
+
| SimpleProduct | code=[integer:1] state=[integer:1] |
|
64
|
+
| SimpleProduct | code=[integer:2] title=[nil:] |
|
65
|
+
| SimpleProduct | code=[integer:3] state=[integer:1] title=[string:a] |
|
66
|
+
When filter "SimpleProduct" records by "<filter>"
|
67
|
+
And order records by "<order>"
|
68
|
+
Then total records should be "<count>"
|
69
|
+
And "first" record should have "<first>"
|
70
|
+
And "last" record should have "<last>"
|
71
|
+
|
72
|
+
Scenarios:
|
73
|
+
| filter | order | count | first | last |
|
74
|
+
| state=[integer:1] | state code | 2 | code=[integer:1] | code=[integer:3] |
|
75
|
+
| state=[nil:] | state code | 1 | code=[integer:2] | code=[integer:2] |
|
76
|
+
| title=[nil:] | title code | 2 | code=[integer:1] | code=[integer:2] |
|
77
|
+
|
78
|
+
Scenario Outline: reorder by hydra attributes
|
79
|
+
Given create models:
|
80
|
+
| model | attributes |
|
81
|
+
| SimpleProduct | code=[integer:1] name=[string:a] title=[string:c] |
|
82
|
+
| SimpleProduct | code=[integer:2] name=[string:b] title=[string:b] |
|
83
|
+
| SimpleProduct | code=[integer:3] name=[string:c] title=[string:a] |
|
84
|
+
When order "SimpleProduct" records by "<order>"
|
85
|
+
And reorder records by "<reorder>"
|
86
|
+
Then total records should be "<count>"
|
87
|
+
And "first" record should have "<first>"
|
88
|
+
And "last" record should have "<last>"
|
89
|
+
|
90
|
+
Scenarios:
|
91
|
+
| order | reorder | count | first | last |
|
92
|
+
| title | name title | 3 | code=[integer:1] | code=[integer:3] |
|
93
|
+
| name | title name | 3 | code=[integer:3] | code=[integer:1] |
|
@@ -0,0 +1,56 @@
|
|
1
|
+
Feature: select concrete attributes
|
2
|
+
When select hydra attribute
|
3
|
+
Then hydra attribute table should be joined and concrete attribute should be selected
|
4
|
+
|
5
|
+
Background: create models and describe hydra attributes
|
6
|
+
Given removed constants if they exist:
|
7
|
+
| name |
|
8
|
+
| GroupProduct |
|
9
|
+
| SimpleProduct |
|
10
|
+
| Product |
|
11
|
+
And create model class "Product"
|
12
|
+
And create model class "SimpleProduct" as "Product" with hydra attributes:
|
13
|
+
| type | name |
|
14
|
+
| integer | code |
|
15
|
+
| float | price |
|
16
|
+
| string | title |
|
17
|
+
| text | note |
|
18
|
+
| boolean | active |
|
19
|
+
| datetime | schedule |
|
20
|
+
And create models:
|
21
|
+
| model | attributes |
|
22
|
+
| SimpleProduct | name=[string:a] code=[integer:1] price=[float:4] title=[string:q] note=[string:z] active=[boolean:true] schedule=[datetime:2012-06-01] |
|
23
|
+
| SimpleProduct | name=[string:b] code=[integer:2] price=[float:5] title=[string:w] note=[string:x] active=[boolean:false] schedule=[datetime:2012-06-02] |
|
24
|
+
| SimpleProduct | name=[string:c] code=[integer:3] price=[float:6] note=[string:c] active=[boolean:true] schedule=[datetime:2012-06-03] |
|
25
|
+
| SimpleProduct | name=[string:d] code=[nil:] price=[float:7] note=[string:v] active=[boolean:false] schedule=[datetime:2012-06-04] |
|
26
|
+
|
27
|
+
Scenario Outline: select concrete attributes
|
28
|
+
When "SimpleProduct" select only the following columns "<columns>"
|
29
|
+
Then records should have only the following "<columns>" names
|
30
|
+
And records should raise "ActiveModel::MissingAttributeError" when call the following "<methods>"
|
31
|
+
And total records should be "4"
|
32
|
+
|
33
|
+
Scenarios: select attributes
|
34
|
+
| columns | methods |
|
35
|
+
| name | code price title note active schedule |
|
36
|
+
| name code | price title note active schedule |
|
37
|
+
| name code price | title note active schedule |
|
38
|
+
| code price title | name note active schedule |
|
39
|
+
| title note active | name code price schedule |
|
40
|
+
| schedule | name code price title note active |
|
41
|
+
| id schedule | name code price title note active |
|
42
|
+
|
43
|
+
Scenario Outline: filter collection and select concrete attributes
|
44
|
+
When "SimpleProduct" select only the following columns "<columns>"
|
45
|
+
And filter records by "<filter attributes>"
|
46
|
+
Then records should have only the following "<columns>" names
|
47
|
+
And records should raise "ActiveModel::MissingAttributeError" when call the following "<methods>"
|
48
|
+
And total records should be "<total>"
|
49
|
+
|
50
|
+
Scenarios: filter and select attributes
|
51
|
+
| columns | filter attributes | methods | total |
|
52
|
+
| name code | name=[string:a] | price title note active schedule | 1 |
|
53
|
+
| code | code=[integer:1] | name price title note active schedule | 1 |
|
54
|
+
| name code | code=[integer:1] | price title note active schedule | 1 |
|
55
|
+
| code title | title=[nil:] | name price note active schedule | 2 |
|
56
|
+
| code note | title=[nil:] | name price title active schedule | 2 |
|
@@ -0,0 +1,32 @@
|
|
1
|
+
Given /^removed constants if they exist:$/ do |table|
|
2
|
+
table.hashes.each do |hash|
|
3
|
+
Object.send(:remove_const, hash[:name]) if Object.const_defined?(hash[:name])
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
Given /^create model class "([^"]+)"$/ do |klass|
|
8
|
+
Object.const_set(klass, Class.new(ActiveRecord::Base))
|
9
|
+
end
|
10
|
+
|
11
|
+
Given /^create model class "([^"]+)" as "([^"]+)" with hydra attributes:$/ do |klass, sti_class, table|
|
12
|
+
Object.const_set klass, Class.new(Object.const_get(sti_class)) {
|
13
|
+
define_hydra_attributes do |hydra|
|
14
|
+
table.hashes.each do |hash|
|
15
|
+
hydra.send(hash[:type], hash[:name].to_sym)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /^class "([^"]+)"::"([^"]+)" "(should|should_not)" have (string|symbol) "([^"]+)" in array$/ do |klass, method, behavior, type, params|
|
22
|
+
klass = Object.const_get(klass)
|
23
|
+
params = params.split
|
24
|
+
params.map!(&:to_sym) if type == 'symbol'
|
25
|
+
klass.send(method).send(behavior) =~ params
|
26
|
+
end
|
27
|
+
|
28
|
+
Then /^class "([^"]+)"::"([^"]+)" "(should|should_not)" have "([^"]+)" hash$/ do |klass, method, behavior, params|
|
29
|
+
klass = Object.const_get(klass)
|
30
|
+
array = params.split.map{ |item| item.split('=').map(&:to_sym) }
|
31
|
+
klass.send(method).send(behavior) == Hash[array].stringify_keys
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Given /^create models:$/ do |table|
|
2
|
+
table.hashes.each do |hash|
|
3
|
+
attributes = typecast_attributes(hash[:attributes])
|
4
|
+
Object.const_get(hash[:model]).create!(attributes)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
Given /^create model "([^"]+)" with attributes "([^"]+)"$/ do |klass, attributes|
|
9
|
+
attrs = typecast_attributes(attributes)
|
10
|
+
@model = Object.const_get(klass).create!(attrs)
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^model "([^"]+)" should "(should|should_not)" to "([^"]+)"$/ do |klass, method, attributes|
|
14
|
+
model = Object.const_get(klass).new
|
15
|
+
attributes.split.each do |attribute|
|
16
|
+
model.send(method, respond_to(attribute))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Then /^it should have typecast attributes "([^"]+)"$/ do |attributes|
|
21
|
+
@model.reload # ensure that all attributes have correct type
|
22
|
+
typecast_attributes(attributes).each do |name, value|
|
23
|
+
@model.send(name).should == value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Then /^model "([^"]+)" should have only the following ((?:hydra )?attributes(?: before type cast)?) "([^"]+)"$/ do |klass, method, attributes|
|
28
|
+
model = Object.const_get(klass).new
|
29
|
+
method = method.gsub(/\s+/, '_')
|
30
|
+
model.send(method).keys.should =~ attributes.split(/\s+/)
|
31
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
When /^load all "([^"]+)" records$/ do |klass|
|
2
|
+
@records = Object.const_get(klass).all
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^select "(first|last)" "([^"]+)" record$/ do |method, klass|
|
6
|
+
@record = Object.const_get(klass).send(method)
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^filter "([^"]+)" by:$/ do |klass, table|
|
10
|
+
condition = table.hashes.each_with_object({}) { |item, hash| hash[item[:field].to_sym] = typecast_value(item[:value]) }
|
11
|
+
@records = Object.const_get(klass).where(condition)
|
12
|
+
end
|
13
|
+
|
14
|
+
When /^filter "([^"]+)" records by "([^"]+)"$/ do |klass, attribute|
|
15
|
+
@records = Object.const_get(klass)
|
16
|
+
step %Q(filter records by "#{attribute}")
|
17
|
+
end
|
18
|
+
|
19
|
+
When /^filter records by "([^"]+)"$/ do |attribute|
|
20
|
+
name, value = typecast_attribute(attribute)
|
21
|
+
@records = @records.where(name => value)
|
22
|
+
end
|
23
|
+
|
24
|
+
When /^(order|reorder) "([^"]+)" records by "([^"]+)"$/ do |sort_method, klass, attributes|
|
25
|
+
@records = Object.const_get(klass)
|
26
|
+
step %Q(#{sort_method} records by "#{attributes}")
|
27
|
+
end
|
28
|
+
|
29
|
+
When /^(order|reorder) records by "([^"]+)"$/ do |sort_method, attributes|
|
30
|
+
reverse = false
|
31
|
+
fields = attributes.split.inject([]) do |items, attribute|
|
32
|
+
name, direction = attribute.split('=')
|
33
|
+
reverse = true if direction == 'desc'
|
34
|
+
items << name.to_sym
|
35
|
+
end
|
36
|
+
|
37
|
+
@records = @records.send(sort_method, fields)
|
38
|
+
@records = @records.reverse_order if reverse
|
39
|
+
end
|
40
|
+
|
41
|
+
When /^"([^"]+)" select only the following columns "([^"]+)"$/ do |klass, columns|
|
42
|
+
@records = Object.const_get(klass).select(columns.split(/\s+/).map(&:to_sym))
|
43
|
+
end
|
44
|
+
|
45
|
+
Then /^record should have the following ((?:hydra )?attributes(?: before type cast)?) "([^"]+)" in attribute hash$/ do |method, attributes|
|
46
|
+
method = method.gsub(/\s+/, '_')
|
47
|
+
typecast_attributes(attributes).each do |(name, value)|
|
48
|
+
@record.send(method)[name.to_s].should == value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
Then /^record (read attribute(?: before type cast)?) "([^"]+)" and value should be "([^"]+)"$/ do |method, attribute, value|
|
53
|
+
method = method.gsub(/\s+/, '_')
|
54
|
+
@record.send(method, attribute).should == typecast_value(value)
|
55
|
+
end
|
56
|
+
|
57
|
+
Then /^"(first|last)" record should have "([^"]+)"$/ do |method, attribute|
|
58
|
+
name, value = typecast_attribute(attribute)
|
59
|
+
@records.send(method).send(name).should == value
|
60
|
+
end
|
61
|
+
|
62
|
+
Then /^records should have the following attributes:$/ do |table|
|
63
|
+
table.hashes.each do |hash|
|
64
|
+
record = @records.detect { |r| r.send(hash[:field]) == typecast_value(hash[:value]) }
|
65
|
+
record.should_not be_nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
Then /^records should have only the following "([^"]+)" names$/ do |attributes|
|
70
|
+
@records.each do |record|
|
71
|
+
record.attributes.keys.should == attributes.split(/\s+/)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
Then /^records should raise "([^"]+)" when call the following "([^"]+)"$/ do |error, methods|
|
76
|
+
error_class = error.constantize
|
77
|
+
@records.each do |record|
|
78
|
+
methods.split(/\s+/).each do |method|
|
79
|
+
lambda { record.send(method) }.should raise_error(error_class)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
Then /^total records should be "([^"]+)"$/ do |count|
|
85
|
+
@records.should have(count.to_i).items
|
86
|
+
end
|
87
|
+
|
88
|
+
Then /^records "(should|should_not)" have loaded associations:$/ do |should, table|
|
89
|
+
table.hashes.each do |hash|
|
90
|
+
@records.each do |record|
|
91
|
+
record.association(hash[:association].to_sym).send(should, be_loaded)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Then /^"([^"]+)" records "(should|should_not)" have loaded associations:$/ do |klass, should, table|
|
97
|
+
table.hashes.each do |hash|
|
98
|
+
records = @records.select { |record| record.class.name == klass }
|
99
|
+
records.each do |record|
|
100
|
+
record.association(hash[:association].to_sym).send(should, be_loaded)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'hydra_attribute'
|
3
|
+
require 'database_cleaner'
|
4
|
+
require 'database_cleaner/cucumber'
|
5
|
+
|
6
|
+
|
7
|
+
ActiveRecord::Base.default_timezone = :utc
|
8
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
9
|
+
ActiveRecord::Base.extend(HydraAttribute::ActiveRecord)
|
10
|
+
|
11
|
+
DatabaseCleaner.strategy = :truncation
|
12
|
+
|
13
|
+
Before do
|
14
|
+
HydraAttribute::SUPPORT_TYPES.each do |type|
|
15
|
+
const = HydraAttribute.config.associated_const_name(type)
|
16
|
+
HydraAttribute.send(:remove_const, const) if HydraAttribute.const_defined?(const)
|
17
|
+
end
|
18
|
+
ActiveSupport::Dependencies::Reference.clear!
|
19
|
+
DatabaseCleaner.start
|
20
|
+
end
|
21
|
+
|
22
|
+
After do
|
23
|
+
DatabaseCleaner.clean
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table "products", :force => true do |t|
|
3
|
+
t.string "type"
|
4
|
+
t.string "name"
|
5
|
+
t.string "info"
|
6
|
+
t.datetime "created_at", :null => false
|
7
|
+
t.datetime "updated_at", :null => false
|
8
|
+
end
|
9
|
+
|
10
|
+
create_table "hydra_string_attributes", :force => true do |t|
|
11
|
+
t.integer "entity_id"
|
12
|
+
t.string "entity_type"
|
13
|
+
t.string "name"
|
14
|
+
t.string "value"
|
15
|
+
end
|
16
|
+
|
17
|
+
create_table "hydra_float_attributes", :force => true do |t|
|
18
|
+
t.integer "entity_id"
|
19
|
+
t.string "entity_type"
|
20
|
+
t.string "name"
|
21
|
+
t.float "value"
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table "hydra_boolean_attributes", :force => true do |t|
|
25
|
+
t.integer "entity_id"
|
26
|
+
t.string "entity_type"
|
27
|
+
t.string "name"
|
28
|
+
t.boolean "value"
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table "hydra_integer_attributes", :force => true do |t|
|
32
|
+
t.integer "entity_id"
|
33
|
+
t.string "entity_type"
|
34
|
+
t.string "name"
|
35
|
+
t.integer "value"
|
36
|
+
end
|
37
|
+
|
38
|
+
create_table "hydra_text_attributes", :force => true do |t|
|
39
|
+
t.integer "entity_id"
|
40
|
+
t.string "entity_type"
|
41
|
+
t.string "name"
|
42
|
+
t.text "value"
|
43
|
+
end
|
44
|
+
|
45
|
+
create_table "hydra_datetime_attributes", :force => true do |t|
|
46
|
+
t.integer "entity_id"
|
47
|
+
t.string "entity_type"
|
48
|
+
t.string "name"
|
49
|
+
t.datetime "value"
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module HydraAttribute
|
2
|
+
module Cucumber
|
3
|
+
module World
|
4
|
+
def typecast_value(schema)
|
5
|
+
type, value = schema.gsub(/\[|\]/, '').split(':', 2)
|
6
|
+
case type
|
7
|
+
when 'integer' then value.to_i
|
8
|
+
when 'float' then value.to_f
|
9
|
+
when 'boolean' then value == 'true' ? true : false
|
10
|
+
when 'nil' then nil
|
11
|
+
when 'datetime' then ActiveSupport::TimeZone.new('UTC').parse(value)
|
12
|
+
else value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def typecast_attribute(attribute)
|
17
|
+
name, schema = attribute.split('=')
|
18
|
+
[name.to_sym, typecast_value(schema)]
|
19
|
+
end
|
20
|
+
|
21
|
+
def typecast_attributes(attributes)
|
22
|
+
attributes.split(/(?<=\])\s+/).flatten.each_with_object({}) do |attribute, hash|
|
23
|
+
name, value = typecast_attribute(attribute)
|
24
|
+
hash[name] = value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
World(HydraAttribute::Cucumber::World)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Feature: create model
|
2
|
+
Model should be created with typecast hydra attributes.
|
3
|
+
|
4
|
+
Background: create models and describe hydra attributes
|
5
|
+
Given removed constants if they exist:
|
6
|
+
| name |
|
7
|
+
| GroupProduct |
|
8
|
+
| SimpleProduct |
|
9
|
+
| Product |
|
10
|
+
And create model class "Product"
|
11
|
+
And create model class "SimpleProduct" as "Product" with hydra attributes:
|
12
|
+
| type | name |
|
13
|
+
| string | code |
|
14
|
+
| float | price |
|
15
|
+
And create model class "GroupProduct" as "Product" with hydra attributes:
|
16
|
+
| type | name |
|
17
|
+
| float | price |
|
18
|
+
| string | title |
|
19
|
+
| boolean | active |
|
20
|
+
|
21
|
+
Scenario Outline: create model with hydra attributes
|
22
|
+
Given create model "<model>" with attributes "<attributes>"
|
23
|
+
Then it should have typecast attributes "<typecast_attributes>"
|
24
|
+
|
25
|
+
Scenarios:
|
26
|
+
| model | attributes | typecast_attributes |
|
27
|
+
| SimpleProduct | code=[integer:1] price=[string:2.75] | code=[string:1] price=[float:2.75] |
|
28
|
+
| GroupProduct | price=[string:2] title=[integer:1] active=[integer:1] | price=[float:2] title=[string:1] active=[boolean:true] |
|
29
|
+
| GroupProduct | active=[integer:0] | price=[nil:] title=[nil:] active=[boolean:false] |
|