roda-controller 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 58cf1d688a6323bd7062c3561f6fd52a47d7fe96
4
+ data.tar.gz: cfcc8845a0a6955cded710ddb2fd6aa2625a6bcb
5
+ SHA512:
6
+ metadata.gz: 8aecd480e38e2287c1344dc84d36b11c6247ac80d02956838767e2a1f50728a7d9cbb43c70623910b695db69b426c2e12cb5dc71ba9c0ffea741333c216895db
7
+ data.tar.gz: a74e9ab398dadd0b6d6c0f1a95b85947d2ae66e4a7627258fff72075481ce22c79f9644f3c2bb42bc6516495fdb397c7e46829d2cb1d82e0463809e7ef801d7f
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Amadeus Folego
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,226 @@
1
+ # Roda Controller
2
+
3
+ Adds controller functionality to Roda
4
+
5
+ ## Configuration
6
+
7
+ Configure your Roda application to use this plugin:
8
+
9
+ ```ruby
10
+ plugin :controller
11
+ ```
12
+
13
+ You can already register your controllers:
14
+
15
+ ```ruby
16
+ plugin :controller, controllers: { users: UsersController }
17
+
18
+ # Infer controller key to 'users'
19
+ plugin :controller, controllers: [UsersController]
20
+
21
+ # Infer controller key to 'users_handler'
22
+ plugin :controller, controllers: [UsersHandler]
23
+ ```
24
+
25
+ ```ruby
26
+
27
+ You may also register controllers later, inside your application class
28
+ declaration:
29
+
30
+ ```ruby
31
+ register_controller UsersController
32
+ register_controller MoviesController
33
+
34
+ # Passing a list of controllers
35
+ register_controller [UsersController, MoviesController]
36
+
37
+ # Explicitly declaring the controller key
38
+ register_controller :users, UsersHandler
39
+ register_controller :movies, MoviesHandler
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ### Controller Naming
45
+
46
+ The controller class is not required to follow any naming convention,
47
+ specially if you specify explicitly the controller key when registered.
48
+
49
+ However if it ends with `Controller` this will be stripped from the
50
+ controller key if it is inferred. I.E. `UsersController => 'users'` and
51
+ `UsersHandler => 'users_handler'`
52
+
53
+ ### Controller Definition
54
+
55
+ You just need to implement the methods with the action names you are going to
56
+ use:
57
+
58
+ ```ruby
59
+ class UsersController
60
+ def index
61
+ "User Index"
62
+ end
63
+
64
+ def show(user_id)
65
+ "User Show ##{user_id}"
66
+ end
67
+ end
68
+ ```
69
+
70
+ ### Dispatching to controllers
71
+
72
+ Call `#dispatch` whenever you want to receive the result of the
73
+ controller action, this is a textbook RESTful routing definition:
74
+
75
+ ```ruby
76
+ r.on("users") do
77
+ r.is do
78
+ r.get do
79
+ dispatch('users#index')
80
+ end
81
+
82
+ r.post do
83
+ dispatch('users#create', args: r.params)
84
+ end
85
+ end
86
+
87
+ r.on(:id) do |user_id|
88
+ r.is do
89
+ r.get do
90
+ dispatch('users#show', args: user_id)
91
+ end
92
+
93
+ r.patch do # requires all_verbs plugin to be loaded
94
+ dispatch('users#update', args: [user_id, r.params])
95
+ end
96
+
97
+ r.delete do # requires all_verbs plugin to be loaded
98
+ dispatch('users#destroy', args: user_id)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ ```
104
+
105
+ ### Receiving dispatched responses
106
+
107
+ You may expose the controller responses using the `@responds_with` variable:
108
+
109
+ ```ruby
110
+ # users_controller.rb
111
+ class UsersController
112
+ def show(user_id)
113
+ user = user: User.find(user_id)
114
+
115
+ @responds_with = { user: user, best_movie: Movie.best_for(user) }
116
+ end
117
+ end
118
+
119
+ # app.rb
120
+ r.get do
121
+ dispatch('users#show', args: user_id)
122
+
123
+ # Do stuff with @user and @best_movie, or access @responds_with directly
124
+ # if the instance variable cannot be overwritten
125
+ end
126
+ ```
127
+
128
+ ### Rendering Views
129
+
130
+ If you are using the render plugin you can use the `#controller` method instead
131
+ of `#dispatch`. It receives the same parameters but will call the `#view`
132
+ method with the following convention:
133
+
134
+ ```ruby
135
+ controller('users#show', args: user_id) # will call view('users/show')
136
+ ```
137
+
138
+ ### Initializing Controllers
139
+
140
+ You may specify parameters for controller initialization, to provide
141
+ context to your actions without polluting the method arguments:
142
+
143
+ ```ruby
144
+ # users_controller.rb
145
+ class UsersController
146
+ attr_reader :request, :response
147
+
148
+ def initialize(request, response)
149
+ @request = request
150
+ @response = response
151
+ end
152
+
153
+ # be able to access the request and response inside actions
154
+
155
+ # app.rb
156
+ ## inside routes
157
+ dispatch('users#update', args: [user_id, r.params], inject: [request, response])
158
+ ## registering controller
159
+ register_controller(:users, -> { |req, res| UsersController.new(req, res) }
160
+ ```
161
+
162
+ ### Advanced Configuration
163
+
164
+ You can setup default arguments for the `#dispatch` and `#controller` methods:
165
+
166
+ ```ruby
167
+ # Will always initialize controllers with request and response args
168
+ plugin :controller, inject: ->{ [request, response] }
169
+ ```
170
+
171
+ ### DRYing up
172
+
173
+ By following conventions you may dry everything up.
174
+
175
+ This:
176
+
177
+ - Creates a `RodaController` class to be inherited on your controllers
178
+ - Exposes request and response variables inside actions
179
+ - Adds helper methods to your actions
180
+ - Automatically loads all controllers inside `controllers` folder
181
+
182
+ ```ruby
183
+ # roda_controller.rb
184
+ class RodaController
185
+ attr_reader :request, :response
186
+
187
+ # Access request and response methods
188
+ def initialize(request, response)
189
+ @request = request
190
+ @response = response
191
+ end
192
+
193
+ # Enables respond_with exposed_variable: local_variable
194
+ def respond_with(opts)
195
+ @responds_with ||= {}
196
+ @responds_with.merge!(opts)
197
+ end
198
+
199
+ # Get list of all controllers
200
+ def self.descendants
201
+ ObjectSpace.each_object(Class).select { |klass| klass < self }
202
+ end
203
+ end
204
+
205
+ # app.rb
206
+ ## configuring the plugin
207
+ plugin :controller, inject: ->{ [request, response] }
208
+
209
+ ## automatically registering all controllers inside controllers folder
210
+ Dir["controllers/*.rb"].each { |file| require_relative file }
211
+
212
+ RodaController.descendants.each do |controller|
213
+ controller_key = Roda::RodaPlugins::Controller.underscore(controller.name)
214
+ controller_proc = -> (req, res) { controller.new(req, res) }
215
+
216
+ register_controller(controller_key, controller_proc)
217
+ end
218
+ ```
219
+
220
+ ## Contributing
221
+
222
+ Bug reports and pull requests are welcome on GitHub at https://github.com/badosu/roda-controller
223
+
224
+ ## License
225
+
226
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task default: :spec
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "roda/plugins/controller/version"
4
+
5
+ class Roda
6
+ module RodaPlugins
7
+ module Controller
8
+ DEFAULTS = {
9
+ registered_controllers: {},
10
+ inject: nil,
11
+ args: nil
12
+ }
13
+
14
+ def self.configure(app, opts={}, &block)
15
+ plugin_opts = (app.opts[:controller] ||= DEFAULTS)
16
+
17
+ app.opts[:controller] = plugin_opts.merge(opts)
18
+
19
+ app.register_controller(opts[:controllers]) if opts[:controllers]
20
+ end
21
+
22
+ def self.underscore(name, acronym_regex: /(?=a)b/)
23
+ return name unless name =~ /[A-Z-]|::/
24
+
25
+ name.gsub!(/Controller$/, "")
26
+
27
+ word = name.to_s.gsub("::", "/")
28
+ word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_' }#{$2.downcase}" }
29
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
30
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
31
+ word.tr!("-", "_")
32
+ word.downcase!
33
+ word
34
+ end
35
+
36
+ module ClassMethods
37
+ def register_controller(*args)
38
+ controllers = opts[:controller][:registered_controllers]
39
+
40
+ if args.size == 2
41
+ controller_key, controller = args
42
+
43
+ controllers.merge! controller_key.to_sym => controller
44
+ elsif args.size == 1
45
+ controller = args[0]
46
+
47
+ if controller.kind_of? Hash
48
+ controllers.merge!(controller)
49
+ elsif controller.kind_of? Array
50
+ controller.each {|c| register_controller(c) }
51
+ elsif controller.kind_of? Class
52
+ register_controller(Controller.underscore(controller.name), controller)
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ module InstanceMethods
59
+ def dispatch(to, args: nil, inject: nil)
60
+ controller_key, action = to.to_s.split('#')
61
+ controllers = opts[:controller][:registered_controllers]
62
+ controller = controllers[controller_key.to_sym]
63
+
64
+ inject ||= opts[:controller][:inject]
65
+
66
+ if inject.respond_to?(:to_proc)
67
+ controller_args = Array(instance_exec(&inject))
68
+ else
69
+ controller_args = Array(inject)
70
+ end
71
+
72
+ if controller.respond_to?(:to_proc)
73
+ controller = controller.to_proc.call(*controller_args)
74
+ elsif controller.kind_of?(Class)
75
+ controller = controller.new(*controller_args)
76
+ end
77
+
78
+ response = controller.send(action, *Array(args))
79
+
80
+ responds_with = controller.instance_variable_get(:@responds_with)
81
+ responds_with ||= {}
82
+
83
+ responds_with.each do |var, val|
84
+ ivar = :"@#{var}"
85
+
86
+ if !instance_variable_defined?(ivar)
87
+ instance_variable_set(ivar, val)
88
+ end
89
+ end
90
+
91
+ response
92
+ end
93
+
94
+ def controller(to, args: nil, inject: nil)
95
+ controller_key, action = to.to_s.split('#')
96
+
97
+ result = dispatch(to, args: args, inject: inject)
98
+
99
+ view("#{controller_key}/#{action}")
100
+
101
+ result
102
+ end
103
+ end
104
+ end
105
+
106
+ register_plugin(:controller, Controller)
107
+ end
108
+ end
@@ -0,0 +1,7 @@
1
+ require 'roda'
2
+
3
+ module Roda::RodaPlugins
4
+ module Controller
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'roda/plugins/controller/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "roda-controller"
10
+ spec.version = Roda::RodaPlugins::Controller::VERSION
11
+ spec.authors = ["Amadeus Folego"]
12
+ spec.email = ["amadeusfolego@gmail.com"]
13
+
14
+ spec.summary = %q{Adds controller functionality to Roda}
15
+ spec.description = %q{Adds controller functionality to Roda}
16
+ spec.homepage = "https://github.com/badosu/roda-controller"
17
+ spec.license = "MIT"
18
+
19
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "roda", "~> 2.0"
25
+ spec.add_development_dependency "bundler", "~> 1.11"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roda-controller
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Amadeus Folego
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-12-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: roda
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.11'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.11'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ description: Adds controller functionality to Roda
56
+ email:
57
+ - amadeusfolego@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Gemfile
63
+ - LICENSE.txt
64
+ - README.md
65
+ - Rakefile
66
+ - lib/roda/plugins/controller.rb
67
+ - lib/roda/plugins/controller/version.rb
68
+ - roda-controller.gemspec
69
+ homepage: https://github.com/badosu/roda-controller
70
+ licenses:
71
+ - MIT
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 2.5.1
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Adds controller functionality to Roda
93
+ test_files: []