hydra_attribute 0.3.1 → 0.3.2.beta

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ **0.3.1 (July 28, 2012)**
2
+ * Fix bug "ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: name, backend_type, default_value" during creation hydra attributes
3
+
1
4
  **0.3.0 (July 27, 2012)**
2
5
  * All attribibutes are now stored in database
3
6
  * Support default value for attributes
data/README.md CHANGED
@@ -71,11 +71,15 @@ Product.hydra_attributes.create(name: 'title', backend_type: 'string')
71
71
  Product.hydra_attributes.create(name: 'total', backend_type: 'integer', default_value: 1)
72
72
  ```
73
73
 
74
- So we created three hydra attributes: **color**, **title** and **total**.
75
- * `name` is **required** and it is the name of attribute.
76
- * `backend_type` is **required** and tells us in what table the value for this attribute will be stored.
77
- The whole list of allowed backend types are: `string`, `text`, `integer`, `float`, `boolean` and `datetime`
78
- * `default_value` is **optional** and it sets the default value for attribute.
74
+ Creating method accepts the following options:
75
+ * **name**. The **required** parameter. Allowed any string.
76
+ * **backend_type**. The **required** parameter. Allowed one of the following strings: `string`, `text`, `integer`, `float`, `boolean` and `datetime`.
77
+ * **default_value**. The **optional** parameter. Allowed any value. By default is `nil`.
78
+ * **white_list**. The **optional** parameter. Should be `true` or `flase`. By defauls is `false`. if pass `white_list: true` this attribute will be added to white list and will be allowed for mass-assignment. This parameter is in black list for creation by default so if you want to pass it, you have to pass the role `as: :admin` too.
79
+
80
+ ```ruby
81
+ Product.hydra_attributes.create({name: 'title', backend_type: 'string', white_list: true}, as: :admin)
82
+ ```
79
83
 
80
84
  ##### Create several objects
81
85
 
@@ -3,20 +3,20 @@ Feature: create hydra attributes
3
3
  Then entity should respond to it
4
4
 
5
5
  Background: create hydra attributes
6
- Given create "HydraAttribute::HydraAttribute" model with attributes as "hashes":
7
- | entity_type | name | backend_type |
8
- | Product | price | float |
6
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
7
+ | name | backend_type | white_list |
8
+ | [string:price] | [string:float] | [boolean:true] |
9
9
 
10
10
  Scenario: create hydra attribute in runtime
11
11
  # Important: when respond_to? is called the hydra attributes are being loaded for entity class
12
12
  Then model "Product" should respond to "price"
13
- Given create "HydraAttribute::HydraAttribute" model with attributes as "hashes":
14
- | entity_type | name | backend_type |
15
- | Product | title | string |
13
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
14
+ | name | backend_type |
15
+ | title | string |
16
16
  Then model "Product" should respond to "title"
17
17
 
18
18
  Scenario: create hydra attribute from entity class
19
- Given create "hydra_attributes" association for "Product" with attributes as "hashes":
19
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
20
20
  | name | backend_type |
21
21
  | code | integer |
22
22
  Then model "Product" should respond to "code"
@@ -4,15 +4,14 @@ Feature: destroy hydra attributes
4
4
  And all values for this attribute should be removed
5
5
 
6
6
  Background: create hydra attributes
7
- Given create "HydraAttribute::HydraAttribute" model with attributes as "hashes":
8
- | entity_type | name | backend_type |
9
- | Product | price | float |
7
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
8
+ | name | backend_type | white_list |
9
+ | [string:price] | [string:float] | [boolean:true] |
10
10
 
11
11
  Scenario: destroy hydra attribute in runtime
12
12
  Given create "Product" model with attributes as "rows_hash":
13
13
  | price | 10 |
14
- When destroy all "HydraAttribute::HydraAttribute" models with attributes as "hashes":
15
- | entity_type | name |
16
- | Product | price |
14
+ When destroy all "HydraAttribute::HydraAttribute" models with attributes as "rows_hash":
15
+ |name | price |
17
16
  Then model "Product" should not respond to "price"
18
17
  And total "HydraAttribute::HydraFloatProduct" records should be "0"
@@ -3,9 +3,9 @@ Feature: update hydra attribute
3
3
  Then model should be notified about this
4
4
 
5
5
  Background: create hydra attributes
6
- Given create "HydraAttribute::HydraAttribute" model with attributes as "hashes":
7
- | entity_type | name | backend_type | default_value |
8
- | Product | code | integer | 1 |
6
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
7
+ | name | backend_type | default_value | white_list |
8
+ | [string:code] | [string:integer] | [integer:1] | [boolean:true] |
9
9
 
10
10
  Scenario: update default value in runtime
11
11
  Given create "Product" model
@@ -3,13 +3,13 @@ Feature: create models with hydra attributes
3
3
  Then hydra attributes should be saved with default values
4
4
 
5
5
  Background: create hydra attributes
6
- Given create "HydraAttribute::HydraAttribute" models with attributes as "hashes":
7
- | entity_type | name | backend_type | default_value |
8
- | Product | code | string | [nil:] |
9
- | Product | price | float | [string:0] |
10
- | Product | active | boolean | [string:0] |
11
- | Product | info | text | [string:] |
12
- | Product | started | datetime | [string:2012-01-01] |
6
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
7
+ | name | backend_type | default_value | white_list |
8
+ | [string:code] | [string:string] | [nil:] | [boolean:true] |
9
+ | [string:price] | [string:float] | [string:0] | [boolean:true] |
10
+ | [string:active] | [string:boolean] | [string:0] | [boolean:true] |
11
+ | [string:info] | [string:text] | [string:] | [boolean:true] |
12
+ | [string:started] | [string:datetime] | [string:2012-01-01] | [boolean:true] |
13
13
 
14
14
  Scenario: create model without hydra attributes
15
15
  Given create "Product" model
@@ -3,10 +3,10 @@ Feature: define hydra attributes
3
3
  Then entity should respond to attributes which are saved in hydra_attributes table
4
4
 
5
5
  Background: create hydra attributes
6
- Given create "HydraAttribute::HydraAttribute" models with attributes as "hashes":
7
- | entity_type | name | backend_type |
8
- | Product | code | string |
9
- | Product | price | float |
6
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
7
+ | name | backend_type |
8
+ | [string:code] | [string:string] |
9
+ | [string:price] | [string:float] |
10
10
 
11
11
  Scenario Outline: models should respond to hydra attributes
12
12
  Then model "<model>" <action> respond to "<attributes>"
@@ -3,13 +3,13 @@ Feature: destroy model
3
3
  Then all associated values should be deleted too
4
4
 
5
5
  Background: create hydra attributes
6
- Given create "HydraAttribute::HydraAttribute" models with attributes as "hashes":
7
- | entity_type | name | backend_type | default_value |
8
- | Product | code | string | [nil:] |
9
- | Product | price | float | [string:0] |
10
- | Product | active | boolean | [string:0] |
11
- | Product | info | text | [string:] |
12
- | Product | started | datetime | [string:2012-01-01] |
6
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
7
+ | name | backend_type | default_value | white_list |
8
+ | [string:code] | [string:string] | [nil:] | [boolean:true] |
9
+ | [string:price] | [string:float] | [string:0] | [boolean:true] |
10
+ | [string:active] | [string:boolean] | [string:0] | [boolean:true] |
11
+ | [string:info] | [string:text] | [string:] | [boolean:true] |
12
+ | [string:started] | [string:datetime] | [string:2012-01-01] | [boolean:true] |
13
13
 
14
14
  Scenario: destroy model
15
15
  Given create "Product" model with attributes as "hashes":
@@ -3,11 +3,11 @@ Feature: group conditions by hydra attributes
3
3
  Then correct table should be joined and group condition should be added
4
4
 
5
5
  Background: create models and describe hydra attributes
6
- Given create "HydraAttribute::HydraAttribute" models with attributes as "hashes":
7
- | entity_type | name | backend_type |
8
- | Product | code | integer |
9
- | Product | title | string |
10
- | Product | total | integer |
6
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
7
+ | name | backend_type | white_list |
8
+ | [string:code] | [string:integer] | [boolean:true] |
9
+ | [string:title] | [string:string] | [boolean:true] |
10
+ | [string:total] | [string:integer] | [boolean:true] |
11
11
  Given create "Product" model with attributes as "hashes":
12
12
  | name | code | title | total |
13
13
  | [string:a] | [integer:1] | [string:q] | [integer:5] |
@@ -12,11 +12,11 @@ Feature: order conditions by hydra attributes
12
12
  Then old hydra attributes should be removed and new should be added
13
13
 
14
14
  Background: create hydra attributes
15
- Given create "HydraAttribute::HydraAttribute" models with attributes as "hashes":
16
- | entity_type | name | backend_type |
17
- | Product | code | integer |
18
- | Product | state | integer |
19
- | Product | title | string |
15
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
16
+ | name | backend_type | white_list |
17
+ | [string:code] | [string:integer] | [boolean:true] |
18
+ | [string:state] | [string:integer] | [boolean:true] |
19
+ | [string:title] | [string:string] | [boolean:true] |
20
20
 
21
21
  Scenario Outline: order by one field
22
22
  Given create "Product" model with attributes as "hashes":
@@ -3,14 +3,14 @@ Feature: select concrete attributes
3
3
  Then model should response only to these attributes
4
4
 
5
5
  Background: create hydra attributes
6
- Given create "HydraAttribute::HydraAttribute" models with attributes as "hashes":
7
- | entity_type | name | backend_type |
8
- | Product | code | integer |
9
- | Product | price | float |
10
- | Product | title | string |
11
- | Product | note | text |
12
- | Product | active | boolean |
13
- | Product | schedule | datetime |
6
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
7
+ | name | backend_type | white_list |
8
+ | [string:code] | [string:integer] | [boolean:true] |
9
+ | [string:price] | [string:float] | [boolean:true] |
10
+ | [string:title] | [string:string] | [boolean:true] |
11
+ | [string:note] | [string:text] | [boolean:true] |
12
+ | [string:active] | [string:boolean] | [boolean:true] |
13
+ | [string:schedule] | [string:datetime] | [boolean:true] |
14
14
  And create "Product" model with attributes as "hashes":
15
15
  | name | code | price | title | note | active | schedule |
16
16
  | [string:a] | [integer:1] | [float:4] | [string:q] | [string:z] | [boolean:true] | [datetime:2012-06-01] |
@@ -6,14 +6,14 @@ Feature: hydra attribute where conditions
6
6
  Then records with nil and blank value should be selected
7
7
 
8
8
  Background: create hydra attributes
9
- Given create "HydraAttribute::HydraAttribute" models with attributes as "hashes":
10
- | entity_type | name | backend_type |
11
- | Product | code | string |
12
- | Product | summary | string |
13
- | Product | title | string |
14
- | Product | price | float |
15
- | Product | active | boolean |
16
- | Product | state | integer |
9
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
10
+ | name | backend_type | white_list |
11
+ | [string:code] | [string:string] | [boolean:true] |
12
+ | [string:summary] | [string:string] | [boolean:true] |
13
+ | [string:title] | [string:string] | [boolean:true] |
14
+ | [string:price] | [string:float] | [boolean:true] |
15
+ | [string:active] | [string:boolean] | [boolean:true] |
16
+ | [string:state] | [string:integer] | [boolean:true] |
17
17
 
18
18
  Scenario: filter by one hydra attribute
19
19
  Given create "Product" model with attributes as "hashes":
@@ -8,6 +8,12 @@ Given /^create "([^"]+)" model with attributes as "([^"]+):"$/ do |klass, format
8
8
  end
9
9
  end
10
10
 
11
+ Given /^create hydra attributes for "([^"]+)" with role "([^"]+)" as "([^"]+)":$/ do |klass, role, format, table|
12
+ Array.wrap(table.send(format)).each do |hash|
13
+ klass.constantize.hydra_attributes.create!(type_cast_hash(hash), as: role.to_sym)
14
+ end
15
+ end
16
+
11
17
  Given /^(load and )?(save|create|update(?: all| attributes)?|destroy(?: all)?|delete(?: all)?)(?: for)? "([^"]+)" models? with attributes as "([^"]+)":$/ do |load, action, klass, format, table|
12
18
  action = action.gsub(' ', '_')
13
19
  klass = klass.constantize
@@ -20,12 +26,6 @@ Given /^(load and )?(save|create|update(?: all| attributes)?|destroy(?: all)?|de
20
26
  end
21
27
  end
22
28
 
23
- Given /^create "([^"]+)" association for "([^"]+)" with attributes as "([^"]+)":$/ do |association, klass, format, table|
24
- Array.wrap(table.send(format)).each do |hash|
25
- klass.constantize.send(association).create(hash)
26
- end
27
- end
28
-
29
29
  Then /^model "([^"]+)" (should(?:\snot)?) respond to "([^"]+)"$/ do |klass, method, attributes|
30
30
  model = klass.constantize.new
31
31
  method = method.gsub(/\s+/, '_')
@@ -3,11 +3,16 @@ require 'hydra_attribute'
3
3
  require 'database_cleaner'
4
4
  require 'database_cleaner/cucumber'
5
5
 
6
+ ActiveSupport.on_load(:active_record) do
7
+ self.attr_accessible :name # we create entity model with one column "name" for testing
8
+ self.default_timezone = :utc
9
+ unless ActiveRecord::VERSION::STRING.start_with?('3.1.')
10
+ self.mass_assignment_sanitizer = :strict
11
+ end
12
+ extend HydraAttribute::ActiveRecord
13
+ end
6
14
 
7
- ActiveRecord::Base.default_timezone = :utc
8
15
  ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
9
- ActiveRecord::Base.extend(HydraAttribute::ActiveRecord)
10
-
11
16
  DatabaseCleaner.strategy = :truncation
12
17
 
13
18
  Before do
@@ -10,6 +10,7 @@ ActiveRecord::Schema.define do
10
10
  t.string "name", :limit => 32, :null => false
11
11
  t.string "backend_type", :limit => 16, :null => false
12
12
  t.string "default_value"
13
+ t.boolean "white_list", :null => false, :default => false
13
14
  t.datetime "created_at", :null => false
14
15
  t.datetime "updated_at", :null => false
15
16
  end
@@ -3,11 +3,11 @@ Feature: update hydra attributes
3
3
  Then entity should be touched
4
4
 
5
5
  Background: create hydra attributes
6
- Given create "HydraAttribute::HydraAttribute" models with attributes as "hashes":
7
- | entity_type | name | backend_type | default_value |
8
- | Product | code | string | [string:###] |
9
- | Product | title | string | |
10
- | Product | total | integer | [integer:1] |
6
+ Given create hydra attributes for "Product" with role "admin" as "hashes":
7
+ | name | backend_type | default_value | white_list |
8
+ | [string:code] | [string:string] | [string:###] | [boolean:true] |
9
+ | [string:title] | [string:string] | | [boolean:true] |
10
+ | [string:total] | [string:integer] | [integer:1] | [boolean:true] |
11
11
  And create "Product" model
12
12
 
13
13
  Scenario Outline: update attributes
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/kostyantyn/Sites/github/gems/hydra_attribute
3
3
  specs:
4
- hydra_attribute (0.3.0.beta1)
4
+ hydra_attribute (0.3.2.beta)
5
5
  activerecord (>= 3.1.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/kostyantyn/Sites/github/gems/hydra_attribute
3
3
  specs:
4
- hydra_attribute (0.3.0.beta1)
4
+ hydra_attribute (0.3.2.beta)
5
5
  activerecord (>= 3.1.0)
6
6
 
7
7
  GEM
@@ -19,9 +19,22 @@ module HydraAttribute
19
19
  end
20
20
 
21
21
  def build
22
+ build_associations
23
+ build_white_list
24
+ end
25
+
26
+ private
27
+
28
+ def build_associations
22
29
  SUPPORT_TYPES.each do |type|
23
30
  AssociationBuilder.build(klass, type)
24
31
  end
25
32
  end
33
+
34
+ def build_white_list
35
+ klass.hydra_attributes.each do |hydra_attribute|
36
+ klass.accessible_attributes.add(hydra_attribute.name) if hydra_attribute.white_list?
37
+ end
38
+ end
26
39
  end
27
40
  end
@@ -4,7 +4,10 @@ module HydraAttribute
4
4
  class HydraAttribute < ActiveRecord::Base
5
5
  self.table_name = 'hydra_attributes'
6
6
 
7
- attr_accessible :name, :backend_type, :default_value
7
+ with_options as: [:default, :admin] do |klass|
8
+ klass.attr_accessible :name, :backend_type, :default_value
9
+ end
10
+ attr_accessible :white_list, as: :admin
8
11
 
9
12
  with_options presence: true do |klass|
10
13
  klass.validates :entity_type, inclusion: { in: lambda { |attr| [(attr.entity_type.constantize.name rescue nil)] } }
@@ -23,7 +26,19 @@ module HydraAttribute
23
26
  end
24
27
 
25
28
  def reload_entity_attributes
26
- entity_type.constantize.reset_hydra_attribute_methods
29
+ entity_type.constantize.reset_hydra_attribute_methods # TODO should not remove all generated methods just for this attribute
30
+ destroyed? ? remove_from_white_list : add_to_white_list
31
+ end
32
+
33
+ # Add attribute to white list for entity if it has a white list mark
34
+ def add_to_white_list
35
+ entity_type.constantize.accessible_attributes.add(name) if white_list?
36
+ end
37
+
38
+ # Don't check if this attribute is in white list or has a white list mark.
39
+ # Just remove it from white list for entity
40
+ def remove_from_white_list
41
+ entity_type.constantize.accessible_attributes.remove(name)
27
42
  end
28
43
  end
29
44
  end
@@ -47,10 +47,11 @@ module HydraAttribute
47
47
 
48
48
  def create_attribute
49
49
  create_table :hydra_attributes do |t|
50
- t.string :entity_type, limit: 32, null: false
51
- t.string :name, limit: 32, null: false
52
- t.string :backend_type, limit: 16, null: false
53
- t.string :default_value
50
+ t.string :entity_type, limit: 32, null: false
51
+ t.string :name, limit: 32, null: false
52
+ t.string :backend_type, limit: 16, null: false
53
+ t.string :default_value
54
+ t.boolean :white_list, null: false, default: false
54
55
  t.timestamps
55
56
  end
56
57
  add_index :hydra_attributes, [:entity_type, :name], unique: true, name: 'hydra_attributes_index'
@@ -1,3 +1,3 @@
1
1
  module HydraAttribute
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.2.beta'
3
3
  end
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hydra_attribute
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
5
- prerelease:
4
+ version: 0.3.2.beta
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Kostyantyn Stepanyuk
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-28 00:00:00.000000000Z
12
+ date: 2012-07-29 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
- requirement: &2152245340 !ruby/object:Gem::Requirement
16
+ requirement: &2152216280 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2152245340
24
+ version_requirements: *2152216280
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2152244520 !ruby/object:Gem::Requirement
27
+ requirement: &2152215740 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2152244520
35
+ version_requirements: *2152215740
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: cucumber
38
- requirement: &2152243160 !ruby/object:Gem::Requirement
38
+ requirement: &2152215160 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2152243160
46
+ version_requirements: *2152215160
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sqlite3
49
- requirement: &2152241780 !ruby/object:Gem::Requirement
49
+ requirement: &2152214620 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2152241780
57
+ version_requirements: *2152214620
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: database_cleaner
60
- requirement: &2152240900 !ruby/object:Gem::Requirement
60
+ requirement: &2152214080 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2152240900
68
+ version_requirements: *2152214080
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: appraisal
71
- requirement: &2152240020 !ruby/object:Gem::Requirement
71
+ requirement: &2152191360 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2152240020
79
+ version_requirements: *2152191360
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rake
82
- requirement: &2152238740 !ruby/object:Gem::Requirement
82
+ requirement: &2152190940 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *2152238740
90
+ version_requirements: *2152190940
91
91
  description: hydra_attribute is an implementation of EAV pattern for ActiveRecord
92
92
  models.
93
93
  email: kostya.stepanyuk@gmail.com
@@ -164,9 +164,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
164
  required_rubygems_version: !ruby/object:Gem::Requirement
165
165
  none: false
166
166
  requirements:
167
- - - ! '>='
167
+ - - ! '>'
168
168
  - !ruby/object:Gem::Version
169
- version: '0'
169
+ version: 1.3.1
170
170
  requirements: []
171
171
  rubyforge_project:
172
172
  rubygems_version: 1.8.10