hydra_attribute 0.1.0
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.
- 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] |
|