hydra_attribute 0.3.1 → 0.3.2.beta

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/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