hydra_attribute 0.4.0.rc1 → 0.4.0.rc2

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/README.md CHANGED
@@ -1,8 +1,9 @@
1
- # hydra_attribute
2
- [![Build Status](https://secure.travis-ci.org/kostyantyn/hydra_attribute.png)](http://travis-ci.org/kostyantyn/hydra_attribute)
1
+ # hydra_attribute [![Build Status](https://secure.travis-ci.org/kostyantyn/hydra_attribute.png)](http://travis-ci.org/kostyantyn/hydra_attribute)
2
+
3
+ [Wiki](https://github.com/kostyantyn/hydra_attribute/wiki) | [RDoc](http://rdoc.info/github/kostyantyn/hydra_attribute)
3
4
 
4
5
  hydra_attribute is an implementation of
5
- [EAV pattern](http://en.wikipedia.org/wiki/Entity–attribute–value_model) for ActiveRecord models.
6
+ [EAV (Entity-Attribute-Value) pattern](http://en.wikipedia.org/wiki/Entity–attribute–value_model) for ActiveRecord models. It allows to create or remove attributes in runtime. Also each record may have different sets of attributes, for example: Product with ID 1 can have different set of attributes than Product with ID 2.
6
7
 
7
8
  ## Requirements
8
9
  * ruby >= 1.9.2
@@ -36,7 +37,8 @@ class CreateHydraAttributeTables < ActiveRecord::Migration
36
37
  end
37
38
  ```
38
39
 
39
- ##### or if we have already the entity table
40
+ **or if we have already the entity table**
41
+
40
42
  ```ruby
41
43
  class CreateHydraAttributeTables < ActiveRecord::Migration
42
44
  def up
@@ -51,7 +53,7 @@ end
51
53
 
52
54
  ## Usage
53
55
 
54
- ##### Create model
56
+ ### Create model
55
57
  ```shell
56
58
  rails generate model Product type:string name:string --migration=false
57
59
  rake db:migrate
@@ -71,7 +73,7 @@ class Product < ActiveRecord::Base
71
73
  end
72
74
  ```
73
75
 
74
- ##### Create some hydra attributes from `rails console`
76
+ ### Create hydra attributes
75
77
  ```ruby
76
78
  Product.hydra_attributes.create(name: 'color', backend_type: 'string', default_value: 'green')
77
79
  Product.hydra_attributes.create(name: 'title', backend_type: 'string')
@@ -88,57 +90,85 @@ Creating method accepts the following options:
88
90
  Product.hydra_attributes.create({name: 'title', backend_type: 'string', white_list: true}, as: :admin)
89
91
  ```
90
92
 
91
- ##### Create several objects
92
-
93
+ ### Create records
93
94
  ```ruby
94
- Product.create.attributes
95
- # {"id"=>1, created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>nil, "total"=>1}
96
- Product.create(color: 'red', title: 'toy').attributes
97
- # {"id"=>1, "created_at"=>..., "updated_at"=>..., "color"=>"red", "title"=>"toy", "total"=>1}
98
- Product.create(title: 'book', total: 2).attributes
99
- # {"id"=>1, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>"book", "total"=>2}
95
+ Product.create
96
+ #<Product id: 1, hydra_set_id: nil, created_at: ..., updated_at: ..., color: "green", title: nil, total: 1>
97
+ Product.create(color: 'red', title: 'toy')
98
+ #<Product id: 2, hydra_set_id: nil, created_at: ..., updated_at: ..., color: "red", title: "toy", total: 1>
99
+ Product.create(title: 'book', total: 2)
100
+ #<Product id: 3, hydra_set_id: nil, created_at: ..., updated_at: ..., color: "green", title: "book", total: 2>
100
101
  ```
101
102
 
102
- ##### Add the new attribute in runtime
103
+ ### Add new hydra attribute in runtime
103
104
  ```ruby
104
105
  Product.hydra_attributes.create(name: 'price', backend_type: 'float', default_value: 0.0)
105
- Product.create(title: 'car', price: 2.50).attributes
106
- # {"id"=>4, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>"car", "price"=>2.5, "total"=>1}
106
+ Product.create(title: 'car', price: 2.50)
107
+ #<Product id: 4, hydra_set_id: nil, created_at: ..., updated_at: ..., color: "green", title: "car", total: 2, price: 2.5>
108
+ ```
109
+
110
+ ### Create hydra set
111
+ **Hydra set** allows set unique attribute list for each entity.
112
+
113
+ ```ruby
114
+ hydra_set = Product.hydra_sets.create(name: 'Default')
115
+ hydra_set.hydra_attributes = Product.hydra_attributes.where(name: %w(color title price))
116
+
117
+ Product.create(color: 'black', title: 'ipod', price: 49.95, total: 5) do |product|
118
+ product.hydra_set_id = hydra_set.id
119
+ end
120
+ #<Product id: 5, hydra_set_id: 1, created_at: ..., updated_at: ..., color: "black", title: "ipod", price: 49.95>
107
121
  ```
122
+ **Notice:** the `total` attribute was skipped because it doesn't exist in hydra set.
108
123
 
109
- ##### Obtain data
124
+ ### Obtain data
110
125
  ```ruby
111
- Product.where(color: 'red').map(&:attributes)
112
- # [{"id"=>2, "created_at"=>..., "updated_at"=>..., "color"=>"red", "title"=>"toy", "price"=>0.0, "total"=>1}]
113
- Product.where(color: 'green', price: nil).map(&:attributes)
114
- # [{"id"=>1, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>nil, "price"=>0.0, "total"=>1},
115
- # {"id"=>3, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>"book", "price"=>0.0, "total"=>2}]
126
+ Product.where(color: 'red')
127
+ # [#<Product id: 2, hydra_set_id: nil, created_at: ..., updated_at: ..., color: "red", title: "toy", price: 0.0, total: 1>]
128
+ Product.where(color: 'green', price: nil)
129
+ # [
130
+ #<Product id: 1, hydra_set_id: nil, created_at: ..., updated_at: ..., color: "green", title: nil, price: 0.0, total: 1>,
131
+ #<Product id: 3, hydra_set_id: nil, created_at: ..., updated_at: ..., color: "green", title: "book", price: 0.0, total: 2>
132
+ # ]
116
133
  ```
117
134
  **Notice**: the attribute `price` was added in runtime and records that were created before have not this attribute
118
135
  so they matched this condition `where(price: nil)`
119
136
 
120
- ##### Order data
137
+ ### Order data
121
138
  ```ruby
122
- Product.order(:color).first.attributes
123
- # {"id"=>1, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>nil, "price"=>0.0, "total"=>1}
124
- Product.order(:color).reverse_order.first.attributes
125
- # {"id"=>2, "created_at"=>..., "updated_at"=>..., "color"=>"red", "title"=>"toy", "price"=>0.0, "total"=>1}
139
+ Product.order(:color, :title).first
140
+ #<Product id: 5, hydra_set_id: 1, created_at: ..., updated_at: ..., color: "black", title: "ipod", price: 49.95>
141
+ Product.order(:color, :title).reverse_order.first
142
+ #<Product id: 2, hydra_set_id: nil, created_at: ..., updated_at: ..., color: "red", title: "toy", price: 0.0, total: 1>
126
143
  ```
127
144
 
128
- ##### Select concrete attributes
145
+ ### Select concrete attributes
129
146
  ```ruby
130
- Product.select([:color, :title]).map(&:attributes)
131
- # [{"id"=>1, "color"=>"green", "title"=>nil}, {"id"=>2, "color"=>"red", "title"=>"toy"},
132
- # {"id"=>3, "color"=>"green", "title"=>"book"}, {"id"=>4, "color"=>"green", "title"=>"car"}]
147
+ Product.select([:color, :title])
148
+ # [
149
+ #<Product id: 1, hydra_set_id: nil, color: "green", title: nil>,
150
+ #<Product id: 2, hydra_set_id: nil, color: "red", title: "toy">,
151
+ #<Product id: 3, hydra_set_id: nil, color: "green", title: "book">,
152
+ #<Product id: 4, hydra_set_id: nil, color: "green", title: "car">,
153
+ #<Product id: 5, hydra_set_id: 1, color: "black", title: "ipod">
154
+ # ]
133
155
  ```
134
- **Notice**: `id` attribute will be added if we want to select hydra attribute
156
+ **Notice:** `id` and `hydra_set_id` attributes are forced added because they are important for correct work.
135
157
 
136
- ##### Group by attribute
158
+ ### Group by attribute
137
159
  ```ruby
138
160
  Product.group(:color).count
139
- # {"green"=>3, "red"=>1}
161
+ # {"black"=>1, "green"=>3, "red"=>1}
140
162
  ```
141
163
 
164
+ ## Wiki Docs
165
+ * [Create migration](https://github.com/kostyantyn/hydra_attribute/wiki/Create-migration)
166
+ * [Create attributes in runtime](https://github.com/kostyantyn/hydra_attribute/wiki/Create-attributes-in-runtime)
167
+ * [Create sets of attributes](https://github.com/kostyantyn/hydra_attribute/wiki/Create-sets-of-attributes)
168
+ * [Query methods](https://github.com/kostyantyn/hydra_attribute/wiki/Query-methods)
169
+ * [Database schema](https://github.com/kostyantyn/hydra_attribute/wiki/Database-schema)
170
+ * [Helper methods](https://github.com/kostyantyn/hydra_attribute/wiki/Helper-methods)
171
+
142
172
  ## Notice
143
173
 
144
174
  The each new minor version doesn't guarantee back compatibility with previous one
@@ -53,6 +53,23 @@ Feature: create models with hydra attributes
53
53
  | info | b |
54
54
  | started | [date:2012-05-05] |
55
55
 
56
+ Scenario: create hydra attribute in runtime
57
+ # create product to cache all hydra attributes
58
+ Given create "Product" model
59
+ And create hydra attributes for "Product" with role "admin" as "hashes":
60
+ | name | backend_type | default_value | white_list |
61
+ | quantity | integer | [nil:] | [bool:t] |
62
+ And create "Product" model with attributes as "rows_hash":
63
+ | quantity | 5 |
64
+ Then last created "Product" should have the following attributes:
65
+ | code | [nil:] |
66
+ | info | [str:] |
67
+ | price | [float:0] |
68
+ | total | [int:0] |
69
+ | active | [bool:f] |
70
+ | started | [date:2012-01-01] |
71
+ | quantity | [int:5] |
72
+
56
73
  Scenario: pass only hydra_set_id
57
74
  Given create hydra sets for "Product" as "hashes":
58
75
  | name |
@@ -67,4 +67,49 @@ Feature: hydra attribute where conditions
67
67
  And records should have the following attributes:
68
68
  | field | value |
69
69
  | code | 2 |
70
- | code | 3 |
70
+ | code | 3 |
71
+
72
+ Scenario: select entity if it has attribute in attribute set
73
+ Given create hydra set "Default" for "Product"
74
+ And set hydra attributes "[array:code,title]" to hydra set "Default" for entity "Product"
75
+ And create "Product" models with attributes as "hashes":
76
+ | hydra_set_id | code | title |
77
+ | | abc1 | book |
78
+ | [eval:Product.hydra_set('Default').id] | abc2 | book |
79
+ When filter "Product" by:
80
+ | field | value |
81
+ | title | book |
82
+ Then total records should be "2"
83
+ And records should have the following attributes:
84
+ | field | value |
85
+ | code | abc1 |
86
+ | code | abc2 |
87
+
88
+ Scenario: when filter attribute by nil value then entities without this attribute in attribute set should not be selected
89
+ Given create hydra set "Default" for "Product"
90
+ And create "Product" model
91
+ And create "Product" model with attributes as "rows_hash":
92
+ | hydra_set_id | [eval:Product.hydra_set('Default').id] |
93
+ When filter "Product" by:
94
+ | field | value |
95
+ | code | [nil:] |
96
+ Then total records should be "1"
97
+ And records should have the following attributes:
98
+ | field | value |
99
+ | hydra_set_id | [nil:] |
100
+
101
+ Scenario: when filter attribute by value then entities which don't have this attribute in attribute set any more should not be selected
102
+ Given create hydra set "Default" for "Product"
103
+ And add hydra attribute "code" to hydra set "Default" for entity "Product"
104
+ And create "Product" models with attributes as "hashes":
105
+ | hydra_set_id | code |
106
+ | | abc |
107
+ | [eval:Product.hydra_set('Default').id] | abc |
108
+ And set hydra attributes "title" to hydra set "Default" for entity "Product"
109
+ When filter "Product" by:
110
+ | field | value |
111
+ | code | abc |
112
+ Then total records should be "1"
113
+ And records should have the following attributes:
114
+ | field | value |
115
+ | hydra_set_id | [nil:] |
@@ -66,6 +66,19 @@ Given /^add "([^"]+)" hydra attributes to hydra set:$/ do |klass, table|
66
66
  end
67
67
  end
68
68
 
69
+ Given /^add hydra attribute "([^"]+)" to hydra set "([^"]+)" for entity "([^"]+)"$/ do |hydra_attribute, hydra_set, entity_class|
70
+ entity = entity_class.constantize
71
+ entity.hydra_set(type_cast_value(hydra_set)).hydra_attributes << entity.hydra_attribute(type_cast_value(hydra_attribute))
72
+ end
73
+
74
+ Given /^set hydra attributes? "([^"]+)" to hydra set "([^"]+)" for entity "([^"]+)"$/ do |hydra_attributes, hydra_set, entity_class|
75
+ entity = entity_class.constantize
76
+ hydra_set = entity.hydra_set(type_cast_value(hydra_set))
77
+
78
+ hydra_attributes = Array(type_cast_value(hydra_attributes)).map { |attr| entity.hydra_attribute(attr) }
79
+ hydra_set.hydra_attributes = hydra_attributes
80
+ end
81
+
69
82
  Given /^(load and )?(save|create|update(?: all| attributes)?|destroy(?: all)?|delete(?: all)?)(?: for)? "([^"]+)" models? with attributes as "([^"]+)":$/ do |load, action, klass, format, table|
70
83
  action = action.gsub(' ', '_')
71
84
  klass = klass.constantize
@@ -1,28 +1,28 @@
1
1
  PATH
2
2
  remote: /Users/kostyantyn/Sites/github/gems/hydra_attribute
3
3
  specs:
4
- hydra_attribute (0.4.0.beta)
4
+ hydra_attribute (0.4.0.rc1)
5
5
  activerecord (>= 3.1.0)
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
- activemodel (3.1.7)
11
- activesupport (= 3.1.7)
10
+ activemodel (3.1.8)
11
+ activesupport (= 3.1.8)
12
12
  builder (~> 3.0.0)
13
13
  i18n (~> 0.6)
14
- activerecord (3.1.7)
15
- activemodel (= 3.1.7)
16
- activesupport (= 3.1.7)
14
+ activerecord (3.1.8)
15
+ activemodel (= 3.1.8)
16
+ activesupport (= 3.1.8)
17
17
  arel (~> 2.2.3)
18
18
  tzinfo (~> 0.3.29)
19
- activesupport (3.1.7)
19
+ activesupport (3.1.8)
20
20
  multi_json (>= 1.0, < 1.3)
21
21
  appraisal (0.4.1)
22
22
  bundler
23
23
  rake
24
24
  arel (2.2.3)
25
- builder (3.0.0)
25
+ builder (3.0.3)
26
26
  cucumber (1.2.1)
27
27
  builder (>= 2.1.2)
28
28
  diff-lcs (>= 1.1.3)
@@ -30,10 +30,10 @@ GEM
30
30
  json (>= 1.4.6)
31
31
  database_cleaner (0.8.0)
32
32
  diff-lcs (1.1.3)
33
- gherkin (2.11.1)
33
+ gherkin (2.11.2)
34
34
  json (>= 1.4.6)
35
- i18n (0.6.0)
36
- json (1.7.4)
35
+ i18n (0.6.1)
36
+ json (1.7.5)
37
37
  multi_json (1.2.0)
38
38
  rake (0.9.2.2)
39
39
  rspec (2.11.0)
@@ -41,9 +41,9 @@ GEM
41
41
  rspec-expectations (~> 2.11.0)
42
42
  rspec-mocks (~> 2.11.0)
43
43
  rspec-core (2.11.1)
44
- rspec-expectations (2.11.2)
44
+ rspec-expectations (2.11.3)
45
45
  diff-lcs (~> 1.1.3)
46
- rspec-mocks (2.11.1)
46
+ rspec-mocks (2.11.2)
47
47
  sqlite3 (1.3.6)
48
48
  tzinfo (0.3.33)
49
49
 
@@ -1,28 +1,28 @@
1
1
  PATH
2
2
  remote: /Users/kostyantyn/Sites/github/gems/hydra_attribute
3
3
  specs:
4
- hydra_attribute (0.4.0.beta)
4
+ hydra_attribute (0.4.0.rc1)
5
5
  activerecord (>= 3.1.0)
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
- activemodel (3.2.7)
11
- activesupport (= 3.2.7)
10
+ activemodel (3.2.8)
11
+ activesupport (= 3.2.8)
12
12
  builder (~> 3.0.0)
13
- activerecord (3.2.7)
14
- activemodel (= 3.2.7)
15
- activesupport (= 3.2.7)
13
+ activerecord (3.2.8)
14
+ activemodel (= 3.2.8)
15
+ activesupport (= 3.2.8)
16
16
  arel (~> 3.0.2)
17
17
  tzinfo (~> 0.3.29)
18
- activesupport (3.2.7)
18
+ activesupport (3.2.8)
19
19
  i18n (~> 0.6)
20
20
  multi_json (~> 1.0)
21
21
  appraisal (0.4.1)
22
22
  bundler
23
23
  rake
24
24
  arel (3.0.2)
25
- builder (3.0.0)
25
+ builder (3.0.3)
26
26
  cucumber (1.2.1)
27
27
  builder (>= 2.1.2)
28
28
  diff-lcs (>= 1.1.3)
@@ -30,10 +30,10 @@ GEM
30
30
  json (>= 1.4.6)
31
31
  database_cleaner (0.8.0)
32
32
  diff-lcs (1.1.3)
33
- gherkin (2.11.1)
33
+ gherkin (2.11.2)
34
34
  json (>= 1.4.6)
35
- i18n (0.6.0)
36
- json (1.7.4)
35
+ i18n (0.6.1)
36
+ json (1.7.5)
37
37
  multi_json (1.3.6)
38
38
  rake (0.9.2.2)
39
39
  rspec (2.11.0)
@@ -41,9 +41,9 @@ GEM
41
41
  rspec-expectations (~> 2.11.0)
42
42
  rspec-mocks (~> 2.11.0)
43
43
  rspec-core (2.11.1)
44
- rspec-expectations (2.11.2)
44
+ rspec-expectations (2.11.3)
45
45
  diff-lcs (~> 1.1.3)
46
- rspec-mocks (2.11.1)
46
+ rspec-mocks (2.11.2)
47
47
  sqlite3 (1.3.6)
48
48
  tzinfo (0.3.33)
49
49
 
@@ -53,7 +53,7 @@ module HydraAttribute
53
53
  generated_hydra_attribute_methods.module_eval <<-EOS, __FILE__, __LINE__ + 1
54
54
  #{defn}
55
55
  if hydra_set_id? and self.class.hydra_set_attribute_ids(hydra_set_id).exclude?(#{hydra_attribute.id})
56
- raise MissingAttributeInHydraSetError, 'Attribute "#{hydra_attribute.name}" does not exist in hydra set "\#{hydra_set(hydra_set_id).name}"'
56
+ raise MissingAttributeInHydraSetError, %(Hydra attribute "#{hydra_attribute.name}" does not exist in hydra set "\#{self.class.hydra_set(hydra_set_id).name}")
57
57
  end
58
58
 
59
59
  if value_model = hydra_value_model(#{hydra_attribute.id})
@@ -99,7 +99,7 @@ module HydraAttribute
99
99
  attr_name = self.class.send(:attribute_method_matcher, name).attr_name
100
100
  end
101
101
 
102
- if hydra_attribute?(attr_name)
102
+ if self.class.hydra_attribute_names.include?(attr_name)
103
103
  self.class.hydra_set_attribute_names(hydra_set_id).include?(attr_name)
104
104
  else
105
105
  super
@@ -136,9 +136,8 @@ module HydraAttribute
136
136
  end
137
137
 
138
138
  def inspect
139
- attrs = self.class.column_names.map { |name| "#{name}: #{attribute_for_inspect(name)}" }
140
- attrs += hydra_value_models.map { |model| "#{model.hydra_attribute_name}: #{model.attribute_for_inspect('value')}" }
141
- "#<#{self.class} #{attrs.join(', ')}>"
139
+ attrs = hydra_value_models.map { |model| "#{model.hydra_attribute_name}: #{model.attribute_for_inspect('value')}" }
140
+ super.gsub(/>$/, ", #{attrs.join(', ')}>")
142
141
  end
143
142
 
144
143
  private
@@ -4,7 +4,7 @@ module HydraAttribute
4
4
  module QueryMethods
5
5
  extend ActiveSupport::Concern
6
6
 
7
- MULTI_VALUE_METHODS = [:hydra_joins_aliases, :hydra_select_values]
7
+ MULTI_VALUE_METHODS = [:hydra_joins_aliases, :hydra_select_values, :hydra_attributes]
8
8
 
9
9
  included do
10
10
  attr_writer *MULTI_VALUE_METHODS
@@ -25,6 +25,7 @@ module HydraAttribute
25
25
  opts.inject(self) do |relation, (name, value)|
26
26
  if klass.hydra_attribute_names.include?(name.to_s)
27
27
  relation, name = relation.clone, name.to_s
28
+ relation.hydra_attributes << name
28
29
  relation.hydra_joins_aliases << hydra_helper.ref_alias(name, value)
29
30
  relation.joins_values += hydra_helper.build_joins(name, value)
30
31
  relation.where_values += build_where(hydra_helper.where_options(name, value))
@@ -58,6 +59,11 @@ module HydraAttribute
58
59
  @select_values << hydra_helper.prepend_table_name('hydra_set_id')
59
60
  end
60
61
 
62
+ if hydra_attributes.any?
63
+ hydra_sets = klass.hydra_sets.select { |hydra_set| hydra_set.hydra_attributes.any? { |attr| attr.name.in?(hydra_attributes) } }
64
+ @where_values << table[:hydra_set_id].in(hydra_sets.map(&:id)).or(table[:hydra_set_id].eq(nil))
65
+ end
66
+
61
67
  super
62
68
  end
63
69
 
@@ -20,7 +20,7 @@ module HydraAttribute
20
20
 
21
21
  def build
22
22
  build_associations
23
- build_white_list
23
+ update_mass_assignment_security
24
24
  end
25
25
 
26
26
  private
@@ -30,8 +30,8 @@ module HydraAttribute
30
30
  end
31
31
  end
32
32
 
33
- def build_white_list
34
- klass.hydra_attributes.each(&:toggle_white_list!)
33
+ def update_mass_assignment_security
34
+ klass.hydra_attributes.each(&:update_mass_assignment_security)
35
35
  end
36
36
  end
37
37
  end
@@ -19,17 +19,17 @@ module HydraAttribute
19
19
 
20
20
  before_destroy :delete_dependent_values
21
21
  after_commit :clear_entity_cache
22
- after_commit :toggle_white_list!
22
+ after_commit :update_mass_assignment_security
23
23
 
24
24
  # @COMPATIBILITY with 3.1.x association module is directly added to the class instead of including module
25
25
  def hydra_sets_with_clearing_cache=(value)
26
26
  self.hydra_sets_without_clearing_cache = value
27
- clear_entity_cache
27
+ entity_type.constantize.clear_hydra_method_cache!
28
28
  value
29
29
  end
30
30
  alias_method_chain :hydra_sets=, :clearing_cache
31
31
 
32
- def toggle_white_list!
32
+ def update_mass_assignment_security
33
33
  if destroyed? or !white_list?
34
34
  remove_from_white_list
35
35
  else
@@ -44,7 +44,7 @@ module HydraAttribute
44
44
  end
45
45
 
46
46
  def clear_entity_cache
47
- entity_type.constantize.clear_hydra_method_cache!
47
+ entity_type.constantize.reset_hydra_attribute_methods!
48
48
  end
49
49
 
50
50
  def add_to_white_list