dynamic_controller 0.0.8 → 0.0.9
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 +80 -80
- data/dynamic_controller.gemspec +27 -27
- data/lib/dynamic_controller/action_controller_extension.rb +18 -16
- data/lib/dynamic_controller/class_methods.rb +41 -41
- data/lib/dynamic_controller/helper_methods.rb +103 -91
- data/lib/dynamic_controller/instance_methods.rb +139 -139
- data/lib/dynamic_controller/resource.rb +21 -21
- data/lib/dynamic_controller/responder.rb +70 -70
- data/lib/dynamic_controller/version.rb +3 -3
- data/lib/dynamic_controller.rb +18 -18
- data/spec/controller_factory.rb +22 -22
- data/spec/controllers/crud_actions_html_spec.rb +111 -111
- data/spec/controllers/crud_actions_json_spec.rb +91 -91
- data/spec/controllers/nested_crud_actions_html_spec.rb +125 -125
- data/spec/controllers/nested_crud_actions_json_spec.rb +97 -97
- data/spec/controllers/ransack_spec.rb +57 -57
- data/spec/controllers/redefined_responders_html_spec.rb +111 -111
- data/spec/controllers/redefined_responders_json_spec.rb +94 -94
- data/spec/controllers/two_level_nested_crud_actions_html_spec.rb +133 -133
- data/spec/controllers/two_level_nested_crud_actions_json_spec.rb +97 -97
- data/spec/custom_responder_format_spec.rb +12 -12
- data/spec/dummy/Gemfile +13 -13
- data/spec/dummy/app/controllers/cities_controller.rb +95 -95
- data/spec/dummy/app/controllers/languages_controller.rb +95 -95
- data/spec/dummy/app/controllers/streets_controller.rb +97 -97
- data/spec/dummy/app/models/city.rb +6 -6
- data/spec/dummy/app/models/language.rb +4 -4
- data/spec/dummy/app/models/street.rb +5 -5
- data/spec/dummy/app/views/cities/_form.html.erb +25 -25
- data/spec/dummy/app/views/cities/index.html.erb +29 -29
- data/spec/dummy/app/views/countries/index.html.erb +25 -25
- data/spec/dummy/app/views/languages/_form.html.erb +21 -21
- data/spec/dummy/app/views/languages/edit.html.erb +6 -6
- data/spec/dummy/app/views/languages/index.html.erb +23 -23
- data/spec/dummy/app/views/languages/new.html.erb +5 -5
- data/spec/dummy/app/views/languages/show.html.erb +10 -10
- data/spec/dummy/app/views/streets/_form.html.erb +25 -25
- data/spec/dummy/app/views/streets/edit.html.erb +6 -6
- data/spec/dummy/app/views/streets/index.html.erb +27 -27
- data/spec/dummy/app/views/streets/new.html.erb +5 -5
- data/spec/dummy/app/views/streets/show.html.erb +15 -15
- data/spec/dummy/config/routes.rb +8 -8
- data/spec/dummy/db/migrate/20120922010743_create_languages.rb +9 -9
- data/spec/dummy/db/migrate/20120929185302_create_streets.rb +11 -11
- data/spec/dummy/db/schema.rb +46 -46
- data/spec/factories.rb +21 -21
- data/spec/has_crud_actions_options_spec.rb +48 -48
- data/spec/spec_helper.rb +35 -35
- metadata +58 -17
data/README.md
CHANGED
@@ -1,80 +1,80 @@
|
|
1
|
-
# DynamicController
|
2
|
-
|
3
|
-
Simple way to add CRUD actions into Rails controllers.
|
4
|
-
|
5
|
-
Suppoted formats HTML and JSON.
|
6
|
-
|
7
|
-
Tested with Ruby 1.9.3 and Rails 3.2.8.
|
8
|
-
|
9
|
-
## Installation
|
10
|
-
|
11
|
-
Add this line to your application's Gemfile:
|
12
|
-
|
13
|
-
gem 'dynamic_controller'
|
14
|
-
|
15
|
-
And then execute:
|
16
|
-
|
17
|
-
$ bundle
|
18
|
-
|
19
|
-
Or install it yourself as:
|
20
|
-
|
21
|
-
$ gem install dynamic_controller
|
22
|
-
|
23
|
-
## Adding CRUD actions to resource controller
|
24
|
-
|
25
|
-
class UsersController < ApplicationController
|
26
|
-
has_crud_actions
|
27
|
-
end
|
28
|
-
|
29
|
-
has_crud_actions adds index, show, new, edit, create, update and destroy actions to controller
|
30
|
-
|
31
|
-
## Explicit action specification
|
32
|
-
|
33
|
-
class UsersController < ApplicationController
|
34
|
-
has_crud_actions only: [:index, :new, :create]
|
35
|
-
end
|
36
|
-
|
37
|
-
or
|
38
|
-
|
39
|
-
class UsersController < ApplicationController
|
40
|
-
has_crud_actions except: :destroy
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
## Nested resources support
|
45
|
-
|
46
|
-
class ProfilesController < ApplicationController
|
47
|
-
has_crud_actions
|
48
|
-
nested_of User
|
49
|
-
end
|
50
|
-
|
51
|
-
If has more than one nested level should use
|
52
|
-
|
53
|
-
class StreetsController < ApplicationController
|
54
|
-
has_crud_actions
|
55
|
-
nested_of Country
|
56
|
-
nested_of City
|
57
|
-
end
|
58
|
-
|
59
|
-
## Redefining responder
|
60
|
-
|
61
|
-
class LanguagesController < ApplicationController
|
62
|
-
has_crud_actions
|
63
|
-
|
64
|
-
respond_to_create :html do
|
65
|
-
redirect_to action: :index
|
66
|
-
end
|
67
|
-
|
68
|
-
respond_to_update do |format|
|
69
|
-
format.html { redirect_to action: :index }
|
70
|
-
format.json { render json: @language }
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
## Contributing
|
75
|
-
|
76
|
-
1. Fork it
|
77
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
78
|
-
3. Commit your changes (`git commit -am 'Added some feature'`)
|
79
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
80
|
-
5. Create new Pull Request
|
1
|
+
# DynamicController
|
2
|
+
|
3
|
+
Simple way to add CRUD actions into Rails controllers.
|
4
|
+
|
5
|
+
Suppoted formats HTML and JSON.
|
6
|
+
|
7
|
+
Tested with Ruby 1.9.3 and Rails 3.2.8.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'dynamic_controller'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install dynamic_controller
|
22
|
+
|
23
|
+
## Adding CRUD actions to resource controller
|
24
|
+
|
25
|
+
class UsersController < ApplicationController
|
26
|
+
has_crud_actions
|
27
|
+
end
|
28
|
+
|
29
|
+
has_crud_actions adds index, show, new, edit, create, update and destroy actions to controller
|
30
|
+
|
31
|
+
## Explicit action specification
|
32
|
+
|
33
|
+
class UsersController < ApplicationController
|
34
|
+
has_crud_actions only: [:index, :new, :create]
|
35
|
+
end
|
36
|
+
|
37
|
+
or
|
38
|
+
|
39
|
+
class UsersController < ApplicationController
|
40
|
+
has_crud_actions except: :destroy
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
## Nested resources support
|
45
|
+
|
46
|
+
class ProfilesController < ApplicationController
|
47
|
+
has_crud_actions
|
48
|
+
nested_of User
|
49
|
+
end
|
50
|
+
|
51
|
+
If has more than one nested level should use
|
52
|
+
|
53
|
+
class StreetsController < ApplicationController
|
54
|
+
has_crud_actions
|
55
|
+
nested_of Country
|
56
|
+
nested_of City
|
57
|
+
end
|
58
|
+
|
59
|
+
## Redefining responder
|
60
|
+
|
61
|
+
class LanguagesController < ApplicationController
|
62
|
+
has_crud_actions
|
63
|
+
|
64
|
+
respond_to_create :html do
|
65
|
+
redirect_to action: :index
|
66
|
+
end
|
67
|
+
|
68
|
+
respond_to_update do |format|
|
69
|
+
format.html { redirect_to action: :index }
|
70
|
+
format.json { render json: @language }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
## Contributing
|
75
|
+
|
76
|
+
1. Fork it
|
77
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
78
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
79
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
80
|
+
5. Create new Pull Request
|
data/dynamic_controller.gemspec
CHANGED
@@ -1,27 +1,27 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "dynamic_controller/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = 'dynamic_controller'
|
7
|
-
s.version = DynamicController::VERSION
|
8
|
-
s.authors = ['Gabriel Naiman']
|
9
|
-
s.email = ['gabynaiman@gmail.com']
|
10
|
-
s.homepage = 'https://github.com/gabynaiman/dynamic_controller'
|
11
|
-
s.summary = 'Simple way to add CRUD actions into Rails controllers'
|
12
|
-
s.description = 'Simple way to add CRUD actions into Rails controllers'
|
13
|
-
|
14
|
-
s.files = `git ls-files`.split("\n")
|
15
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
-
s.require_paths = ["lib"]
|
18
|
-
|
19
|
-
s.add_dependency 'ransack'
|
20
|
-
s.add_dependency 'kaminari'
|
21
|
-
s.add_dependency 'nql', '0.0.4'
|
22
|
-
|
23
|
-
s.add_development_dependency 'rails'
|
24
|
-
s.add_development_dependency 'sqlite3'
|
25
|
-
s.add_development_dependency 'rspec-rails'
|
26
|
-
s.add_development_dependency 'factory_girl_rails'
|
27
|
-
end
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dynamic_controller/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'dynamic_controller'
|
7
|
+
s.version = DynamicController::VERSION
|
8
|
+
s.authors = ['Gabriel Naiman']
|
9
|
+
s.email = ['gabynaiman@gmail.com']
|
10
|
+
s.homepage = 'https://github.com/gabynaiman/dynamic_controller'
|
11
|
+
s.summary = 'Simple way to add CRUD actions into Rails controllers'
|
12
|
+
s.description = 'Simple way to add CRUD actions into Rails controllers'
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency 'ransack'
|
20
|
+
s.add_dependency 'kaminari'
|
21
|
+
s.add_dependency 'nql', '0.0.4'
|
22
|
+
|
23
|
+
s.add_development_dependency 'rails'
|
24
|
+
s.add_development_dependency 'sqlite3'
|
25
|
+
s.add_development_dependency 'rspec-rails'
|
26
|
+
s.add_development_dependency 'factory_girl_rails'
|
27
|
+
end
|
@@ -1,17 +1,19 @@
|
|
1
|
-
module DynamicController
|
2
|
-
module ActionControllerExtension
|
3
|
-
|
4
|
-
def has_crud_actions(options={})
|
5
|
-
@resource_options = Hash[options.map { |k, v| [:only, :except].include?(k.to_sym) ? [k, [v].flatten.map(&:to_sym)] : [k, v] }].reverse_merge(only: DynamicController::ACTIONS, except: [])
|
6
|
-
send :extend, ClassMethods
|
7
|
-
send :include, InstanceMethods
|
8
|
-
send :include, HelperMethods
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
1
|
+
module DynamicController
|
2
|
+
module ActionControllerExtension
|
3
|
+
|
4
|
+
def has_crud_actions(options={})
|
5
|
+
@resource_options = Hash[options.map { |k, v| [:only, :except].include?(k.to_sym) ? [k, [v].flatten.map(&:to_sym)] : [k, v] }].reverse_merge(only: DynamicController::ACTIONS, except: [])
|
6
|
+
send :extend, ClassMethods
|
7
|
+
send :include, InstanceMethods
|
8
|
+
send :include, HelperMethods
|
9
|
+
|
10
|
+
helper_method :search_query
|
11
|
+
end
|
12
|
+
|
13
|
+
def nested_of(resource_class)
|
14
|
+
before_filter :load_parent_models if parent_resources.empty?
|
15
|
+
parent_resources << Resource.new(resource_class: resource_class)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
17
19
|
end
|
@@ -1,42 +1,42 @@
|
|
1
|
-
module DynamicController
|
2
|
-
module ClassMethods
|
3
|
-
|
4
|
-
def parent_resources
|
5
|
-
@parent_resources ||= []
|
6
|
-
end
|
7
|
-
|
8
|
-
def include_action?(action_name)
|
9
|
-
(@resource_options[:only] - @resource_options[:except]).include?(action_name)
|
10
|
-
end
|
11
|
-
|
12
|
-
def redefined_responders
|
13
|
-
@redefined_responders ||= {}
|
14
|
-
end
|
15
|
-
|
16
|
-
def redefined_responder_to(action, format=nil)
|
17
|
-
redefined_responders[redefined_responder_key(action, format)]
|
18
|
-
end
|
19
|
-
|
20
|
-
def redefined_responder_to?(action, format=nil)
|
21
|
-
redefined_responders.has_key? redefined_responder_key(action, format)
|
22
|
-
end
|
23
|
-
|
24
|
-
def responder_formats
|
25
|
-
@responder_formats ||= [:html, :json]
|
26
|
-
end
|
27
|
-
|
28
|
-
DynamicController::ACTIONS.each do |action|
|
29
|
-
define_method "respond_to_#{action}" do |format=nil, &block|
|
30
|
-
responder_formats << format if format and !responder_formats.include?(format)
|
31
|
-
redefined_responders[redefined_responder_key(action, format)] = block
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def redefined_responder_key(action, format=nil)
|
38
|
-
[action, format].compact.join('_').to_sym
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
1
|
+
module DynamicController
|
2
|
+
module ClassMethods
|
3
|
+
|
4
|
+
def parent_resources
|
5
|
+
@parent_resources ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
def include_action?(action_name)
|
9
|
+
(@resource_options[:only] - @resource_options[:except]).include?(action_name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def redefined_responders
|
13
|
+
@redefined_responders ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def redefined_responder_to(action, format=nil)
|
17
|
+
redefined_responders[redefined_responder_key(action, format)]
|
18
|
+
end
|
19
|
+
|
20
|
+
def redefined_responder_to?(action, format=nil)
|
21
|
+
redefined_responders.has_key? redefined_responder_key(action, format)
|
22
|
+
end
|
23
|
+
|
24
|
+
def responder_formats
|
25
|
+
@responder_formats ||= [:html, :json]
|
26
|
+
end
|
27
|
+
|
28
|
+
DynamicController::ACTIONS.each do |action|
|
29
|
+
define_method "respond_to_#{action}" do |format=nil, &block|
|
30
|
+
responder_formats << format if format and !responder_formats.include?(format)
|
31
|
+
redefined_responders[redefined_responder_key(action, format)] = block
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def redefined_responder_key(action, format=nil)
|
38
|
+
[action, format].compact.join('_').to_sym
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
42
|
end
|
@@ -1,92 +1,104 @@
|
|
1
|
-
module DynamicController
|
2
|
-
module HelperMethods
|
3
|
-
|
4
|
-
def resource_class
|
5
|
-
@resource_class ||= (resource_namespace.to_s.split('::') << controller_name.classify).join('::').constantize
|
6
|
-
end
|
7
|
-
|
8
|
-
def resource_namespace
|
9
|
-
self.class.to_s.deconstantize.constantize
|
10
|
-
end
|
11
|
-
|
12
|
-
def collection=(value)
|
13
|
-
instance_variable_set("@#{controller_name}", value)
|
14
|
-
end
|
15
|
-
|
16
|
-
def collection
|
17
|
-
instance_variable_get("@#{controller_name}")
|
18
|
-
end
|
19
|
-
|
20
|
-
def model=(value)
|
21
|
-
instance_variable_set("@#{controller_name.singularize}", value)
|
22
|
-
end
|
23
|
-
|
24
|
-
def model
|
25
|
-
instance_variable_get("@#{controller_name.singularize}")
|
26
|
-
end
|
27
|
-
|
28
|
-
def load_parent_models
|
29
|
-
parent = nil
|
30
|
-
self.class.parent_resources.each do |resource|
|
31
|
-
if parent
|
32
|
-
parent = parent.send(resource.children_name).find(params[resource.param_name])
|
33
|
-
else
|
34
|
-
parent = resource.find params[resource.param_name]
|
35
|
-
end
|
36
|
-
instance_variable_set resource.instance_variable_name, parent
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def parent_models
|
41
|
-
return nil if self.class.parent_resources.empty?
|
42
|
-
self.class.parent_resources.map do |resource|
|
43
|
-
instance_variable_get resource.instance_variable_name
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def parent_model
|
48
|
-
(parent_models || []).last
|
49
|
-
end
|
50
|
-
|
51
|
-
def handle_error(error)
|
52
|
-
respond_to do |format|
|
53
|
-
format.html { raise error }
|
54
|
-
format.json { render json: error.message, status: :internal_server_error }
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def model_extended_attributes
|
59
|
-
resource_class.column_names | resource_class.reflections.map { |k, v| v.klass.column_names.map { |c| "#{k}_#{c}" } }.flatten
|
60
|
-
end
|
61
|
-
|
62
|
-
def search_query
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
true
|
89
|
-
|
90
|
-
|
91
|
-
|
1
|
+
module DynamicController
|
2
|
+
module HelperMethods
|
3
|
+
|
4
|
+
def resource_class
|
5
|
+
@resource_class ||= (resource_namespace.to_s.split('::') << controller_name.classify).join('::').constantize
|
6
|
+
end
|
7
|
+
|
8
|
+
def resource_namespace
|
9
|
+
self.class.to_s.deconstantize.constantize
|
10
|
+
end
|
11
|
+
|
12
|
+
def collection=(value)
|
13
|
+
instance_variable_set("@#{controller_name}", value)
|
14
|
+
end
|
15
|
+
|
16
|
+
def collection
|
17
|
+
instance_variable_get("@#{controller_name}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def model=(value)
|
21
|
+
instance_variable_set("@#{controller_name.singularize}", value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def model
|
25
|
+
instance_variable_get("@#{controller_name.singularize}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_parent_models
|
29
|
+
parent = nil
|
30
|
+
self.class.parent_resources.each do |resource|
|
31
|
+
if parent
|
32
|
+
parent = parent.send(resource.children_name).find(params[resource.param_name])
|
33
|
+
else
|
34
|
+
parent = resource.find params[resource.param_name]
|
35
|
+
end
|
36
|
+
instance_variable_set resource.instance_variable_name, parent
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def parent_models
|
41
|
+
return nil if self.class.parent_resources.empty?
|
42
|
+
self.class.parent_resources.map do |resource|
|
43
|
+
instance_variable_get resource.instance_variable_name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def parent_model
|
48
|
+
(parent_models || []).last
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle_error(error)
|
52
|
+
respond_to do |format|
|
53
|
+
format.html { raise error }
|
54
|
+
format.json { render json: error.message, status: :internal_server_error }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def model_extended_attributes
|
59
|
+
resource_class.column_names | resource_class.reflections.map { |k, v| v.klass.column_names.map { |c| "#{k}_#{c}" } }.flatten
|
60
|
+
end
|
61
|
+
|
62
|
+
def search_query
|
63
|
+
return @search_query if @search_query
|
64
|
+
|
65
|
+
query_key = "query_#{params[:controller]}_#{params[:action]}"
|
66
|
+
|
67
|
+
@search_query = if params.has_key?(:q)
|
68
|
+
session[query_key] = params[:q]
|
69
|
+
else
|
70
|
+
session[query_key]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def ransack_query
|
75
|
+
search_query.is_a?(String) ? NQL.to_ransack(search_query) : search_query
|
76
|
+
end
|
77
|
+
|
78
|
+
def search_query_valid?
|
79
|
+
begin
|
80
|
+
search_node_valid? ransack_query, model_extended_attributes
|
81
|
+
rescue NQL::InvalidExpressionError => ex
|
82
|
+
Rails.logger.debug "Invalid search query: #{params[:q]} | Error: #{ex.message}"
|
83
|
+
false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def search_node_valid?(node, valid_attributes)
|
88
|
+
return true unless node
|
89
|
+
node.deep_symbolize_keys.each do |k, v|
|
90
|
+
if k == :a
|
91
|
+
return false unless valid_attributes.include?(v['0'.to_sym][:name])
|
92
|
+
else
|
93
|
+
if v.is_a?(Hash)
|
94
|
+
return false unless search_node_valid?(v, valid_attributes)
|
95
|
+
elsif v.is_a?(Array)
|
96
|
+
v.select { |e| e.is_a?(Hash) }.each { |e| return false unless search_node_valid?(e, valid_attributes) }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
92
104
|
end
|