ddc 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +122 -0
- data/Rakefile +2 -0
- data/ddc.gemspec +27 -0
- data/lib/ddc.rb +6 -0
- data/lib/ddc/controller_builder.rb +98 -0
- data/lib/ddc/response_builder.rb +11 -0
- data/lib/ddc/service_builder.rb +54 -0
- data/lib/ddc/version.rb +3 -0
- data/spec/controller_builder_spec.rb +181 -0
- data/spec/spec_helper.rb +8 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f3a6ee066211a5a1664cda8df754f8dd14d6bc07
|
4
|
+
data.tar.gz: 23a9ecdcb2c841d6b78e51e1dce499f90197e2ea
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dffde5c7259d6cc663a5efcb354b4a4549009a6ea360fedeaf58ff48f4e7a0dd17700deb71fa124e5770bd9e9550cb925c575329d111407abc9501cfce4db85a
|
7
|
+
data.tar.gz: fb195d4f69292e9481af00a52d03fe8e2cb8c56cfd4f9fdc713397512448b154e80b6fbea2af0704fdef5a2c803af96760fb900cfa26c7a03751730823888826
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Shawn Anderson
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# DDC
|
2
|
+
|
3
|
+
DDC (Data Driven Controllers) let's you declare how to wire Rails into your app without the need for code. A Rails controller's job is parsing/interpreting parameters to send to your application domain and taking those results and translating them back out to an HTTP result (html/status/headers). DDC removes the need for all the boiler plate controller code and tests.
|
4
|
+
|
5
|
+
By adhering to a couple of interfaces, you can avoid writing most controller code and tests. See this [blog post]( http://spin.atomicobject.com/2015/01/26/data-driven-rails-controllers) for more information.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'ddc'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install ddc
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### Controllers
|
26
|
+
|
27
|
+
`controllers/monkeys_controller.rb`
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
DDC::ControllerBuilder.build :monkeys
|
31
|
+
before_actions: [:authenticate_user!],
|
32
|
+
actions: {
|
33
|
+
show: {
|
34
|
+
context: 'context_builder#user_and_id',
|
35
|
+
service: 'monkey_service#find'
|
36
|
+
},
|
37
|
+
index: {
|
38
|
+
context: 'context_builder#user',
|
39
|
+
service: 'monkey_service#find_all'
|
40
|
+
},
|
41
|
+
update: {
|
42
|
+
context: 'context_builder#monkey',
|
43
|
+
service: 'monkey_service#update'
|
44
|
+
},
|
45
|
+
create: {
|
46
|
+
context: 'context_builder#monkey',
|
47
|
+
service: 'monkey_service#create'
|
48
|
+
}
|
49
|
+
}
|
50
|
+
```
|
51
|
+
|
52
|
+
### Context Builders
|
53
|
+
`lib/context_builder.rb`
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
class ContextBuilder
|
57
|
+
def user(context_params)
|
58
|
+
HashWithIndifferentAccess.new current_user: context_params[:current_user]
|
59
|
+
end
|
60
|
+
|
61
|
+
def user_and_id(context_params)
|
62
|
+
user(context_params).merge(id: context_params[:params][:id])
|
63
|
+
end
|
64
|
+
|
65
|
+
def monkey(context_params)
|
66
|
+
info = context_params[:params].permit(monkey: [:color, :poo])
|
67
|
+
user_and_id(context_params).merge(info)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
|
73
|
+
### Services
|
74
|
+
|
75
|
+
`lib/monkeys_service.rb`
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
class MonkeyService
|
79
|
+
def find(context)
|
80
|
+
id, user = context.values_at :id, :current_user
|
81
|
+
me = find_for_user user, id
|
82
|
+
if me.present?
|
83
|
+
ok(me)
|
84
|
+
else
|
85
|
+
not_found
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def update(context)
|
90
|
+
id, user, updates = context.values_at :id, :current_user, @model_type
|
91
|
+
me = find_for_user user, id
|
92
|
+
|
93
|
+
translated_updates = translated_cid_to_id(updates)
|
94
|
+
|
95
|
+
if me.present?
|
96
|
+
me.update_attributes translated_updates
|
97
|
+
ok(me)
|
98
|
+
else
|
99
|
+
not_found
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
def not_found
|
105
|
+
{status: :not_found}.freeze
|
106
|
+
end
|
107
|
+
def ok(obj)
|
108
|
+
{status: :ok, object: obj}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# shortcut for default CRUD service
|
113
|
+
MonkeyService = DDC::ServiceBuilder.build(:monkey)
|
114
|
+
```
|
115
|
+
|
116
|
+
## Contributing
|
117
|
+
|
118
|
+
1. Fork it ( https://github.com/[my-github-username]/ddc/fork )
|
119
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
120
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
121
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
122
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/ddc.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ddc/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ddc"
|
8
|
+
spec.version = Ddc::VERSION
|
9
|
+
spec.authors = ["Shawn Anderson"]
|
10
|
+
spec.email = ["shawn42@gmail.com"]
|
11
|
+
spec.summary = %q{Data Driven Controllers for Rails}
|
12
|
+
spec.description = %q{Use data to tell Rails how to interact with your domain.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
+
spec.add_dependency "actionpack", "~> 4.1"
|
25
|
+
spec.add_dependency "activesupport", "~> 4.1"
|
26
|
+
|
27
|
+
end
|
data/lib/ddc.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
module DDC
|
2
|
+
class ControllerBuilder
|
3
|
+
DEFAULT_CONTEXT_PARAMS = [:params]
|
4
|
+
DEFAULT_STATUSES = {
|
5
|
+
ok: 200,
|
6
|
+
created: 201,
|
7
|
+
not_found: 404,
|
8
|
+
not_allowed: 401,
|
9
|
+
error: 500
|
10
|
+
}
|
11
|
+
class << self
|
12
|
+
def build_controller(controller_name, config)
|
13
|
+
klass = find_or_create_class(controller_name)
|
14
|
+
setup_before_actions!(klass, config)
|
15
|
+
setup_actions!(controller_name, klass, config)
|
16
|
+
klass
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def find_or_create_class(controller_name)
|
21
|
+
controller_klass_name = controller_name.to_s.camelize+'Controller'
|
22
|
+
klass = nil
|
23
|
+
if Object.constants.include?(controller_klass_name.to_sym)
|
24
|
+
klass = Object.const_get(controller_klass_name)
|
25
|
+
else
|
26
|
+
klass = Class.new(ApplicationController)
|
27
|
+
Object.const_set(controller_klass_name, klass)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup_before_actions!(klass, config)
|
32
|
+
(config[:before_actions] || []).each do |ba|
|
33
|
+
klass.before_action ba
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def setup_actions!(controller_name, klass, config)
|
38
|
+
actions = config[:actions]
|
39
|
+
raise "Must specify actions" if actions.blank?
|
40
|
+
|
41
|
+
actions.each do |action, action_desc|
|
42
|
+
setup_action! controller_name, klass, action, action_desc
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def setup_action!(controller_name, klass, action, action_desc)
|
47
|
+
raise "Must specify a service for each action" unless action_desc[:service].present?
|
48
|
+
raise "Must specify a context for each action" unless action_desc[:context].present?
|
49
|
+
proc_klass, proc_method = parse_class_and_method(action_desc[:service])
|
50
|
+
context_klass, context_method = parse_class_and_method(action_desc[:context])
|
51
|
+
|
52
|
+
klass.send :define_method, action do
|
53
|
+
context_params = (action_desc[:params] || DEFAULT_CONTEXT_PARAMS).inject({}) do |h, param|
|
54
|
+
h[param] = send param
|
55
|
+
h
|
56
|
+
end
|
57
|
+
context = context_klass.new.send(context_method, context_params)
|
58
|
+
|
59
|
+
result = proc_klass.new.send(proc_method, context)
|
60
|
+
obj = result[:object]
|
61
|
+
errors = result[:errors] || []
|
62
|
+
plural_model_name = controller_name.to_s
|
63
|
+
model_name = plural_model_name.singularize
|
64
|
+
|
65
|
+
# alias in object as model name
|
66
|
+
if obj.is_a? Enumerable
|
67
|
+
result[plural_model_name] ||= obj
|
68
|
+
else
|
69
|
+
result[model_name] ||= obj
|
70
|
+
end
|
71
|
+
|
72
|
+
status = DEFAULT_STATUSES.merge(action_desc[:status]||{})[result[:status]]
|
73
|
+
|
74
|
+
respond_to do |format|
|
75
|
+
format.json do
|
76
|
+
if obj.nil?
|
77
|
+
render json: {errors: errors}, status: status
|
78
|
+
else
|
79
|
+
render json: obj, status: status
|
80
|
+
end
|
81
|
+
end
|
82
|
+
format.html do
|
83
|
+
result.each do |k,v|
|
84
|
+
instance_variable_set("@#{k}", v)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse_class_and_method(str)
|
92
|
+
under_klass, method = str.split('#')
|
93
|
+
[Object.const_get(under_klass.camelize), method]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module DDC
|
2
|
+
class ServiceBuilder
|
3
|
+
def self.build(model_type)
|
4
|
+
Class.new do
|
5
|
+
include ResponseBuilder
|
6
|
+
class << self
|
7
|
+
attr_accessor :model_type, :ar_model
|
8
|
+
end
|
9
|
+
|
10
|
+
@model_type = model_type
|
11
|
+
ar_class_name = model_type.to_s.camelize
|
12
|
+
@ar_model = Object.const_get(ar_class_name)
|
13
|
+
|
14
|
+
def find(context)
|
15
|
+
id = context.values_at :id
|
16
|
+
me = self.class.ar_model.where id: id
|
17
|
+
if me.present?
|
18
|
+
ok(me)
|
19
|
+
else
|
20
|
+
not_found
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_all(context)
|
25
|
+
mes = self.class.ar_model.all
|
26
|
+
ok(mes)
|
27
|
+
end
|
28
|
+
|
29
|
+
def update(context)
|
30
|
+
id, updates = context.values_at :id, self.class.model_type
|
31
|
+
me = self.class.ar_model.where id: id
|
32
|
+
|
33
|
+
if me.present?
|
34
|
+
me.update_attributes translated_updates
|
35
|
+
ok(me)
|
36
|
+
else
|
37
|
+
not_found
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def create(context)
|
42
|
+
attributes = context.values_at self.class.model_type
|
43
|
+
me = self.class.ar_model.create attributes
|
44
|
+
created(me)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def find_for_user(user, id)
|
49
|
+
return nil if id.nil? || !UUIDUtil.valid?(id)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/ddc/version.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DDC::ControllerBuilder do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
describe '.build_controller' do
|
7
|
+
let(:json_format) {
|
8
|
+
format = double('json format')
|
9
|
+
expect(format).to receive(:json).and_yield
|
10
|
+
expect(format).to receive(:html)
|
11
|
+
format }
|
12
|
+
let(:html_format) {
|
13
|
+
format = double('html format')
|
14
|
+
expect(format).to receive(:html).and_yield
|
15
|
+
expect(format).to receive(:json)
|
16
|
+
format }
|
17
|
+
after do
|
18
|
+
klass_to_cleanup = :FooController
|
19
|
+
Object.send :remove_const, klass_to_cleanup if Object.constants.include?(klass_to_cleanup)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'defines the controller class' do
|
23
|
+
subject.build_controller :foo, actions: {
|
24
|
+
index: {
|
25
|
+
params: [:current_user, :params],
|
26
|
+
context: 'foo_context_builder#bar',
|
27
|
+
service: 'baz_service#qux'
|
28
|
+
}
|
29
|
+
}
|
30
|
+
expect(Object.const_get("FooController")).not_to be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'raises if there are no actions defined' do
|
34
|
+
expect(->{subject.build_controller :foo, actions: {}}).to raise_exception
|
35
|
+
expect(->{subject.build_controller :foop, {}}).to raise_exception
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'raises if an action is missing context' do
|
39
|
+
expect(->{subject.build_controller :foo, actions: {foo: {
|
40
|
+
params: [:current_user, :params],
|
41
|
+
service: 'baz_service#qux'
|
42
|
+
}}}).to raise_exception
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'raises if an action is missing service' do
|
46
|
+
expect(->{subject.build_controller :foo, actions: {foo: {
|
47
|
+
context: 'foo_context_builder#bar',
|
48
|
+
}}}).to raise_exception
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'adds the before actions' do
|
52
|
+
class FooController
|
53
|
+
def self.before_action(*args);end
|
54
|
+
end
|
55
|
+
|
56
|
+
expect(FooController).to receive(:before_action).with(:my_before_action)
|
57
|
+
subject.build_controller :foo,
|
58
|
+
before_actions: [:my_before_action],
|
59
|
+
actions: {
|
60
|
+
index: {
|
61
|
+
context: 'foo_context_builder#bar',
|
62
|
+
service: 'baz_service#qux'
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'sunny day get params, process, return object and status, render' do
|
69
|
+
class FooController
|
70
|
+
def current_user; end
|
71
|
+
def some_user; end
|
72
|
+
def render(args); end
|
73
|
+
def respond_to; end
|
74
|
+
end
|
75
|
+
controller = FooController.new
|
76
|
+
|
77
|
+
expect(controller).to receive_messages(
|
78
|
+
current_user: :some_user,
|
79
|
+
params: {a: :b})
|
80
|
+
|
81
|
+
render_args = nil
|
82
|
+
expect(controller).to receive(:render) do |args|
|
83
|
+
render_args = args
|
84
|
+
end
|
85
|
+
expect(controller).to receive(:respond_to) do |&block|
|
86
|
+
block.call(json_format)
|
87
|
+
end
|
88
|
+
expect_any_instance_of(FooContextBuilder).to receive(:bar).with(hash_including(
|
89
|
+
current_user: :some_user,
|
90
|
+
params: {a: :b})) { :context }
|
91
|
+
|
92
|
+
expect_any_instance_of(BazService).to receive(:qux).with(:context) do
|
93
|
+
{ object: :some_obj, status: :ok }
|
94
|
+
end
|
95
|
+
|
96
|
+
subject.build_controller :foo, actions: {
|
97
|
+
index: {
|
98
|
+
params: [:current_user, :params],
|
99
|
+
context: 'foo_context_builder#bar',
|
100
|
+
service: 'baz_service#qux'
|
101
|
+
}
|
102
|
+
}
|
103
|
+
controller.index
|
104
|
+
|
105
|
+
expect(render_args).to eq(json: :some_obj, status: 200)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'renders error if service returns nil object' do
|
109
|
+
class FooController
|
110
|
+
def current_user; end
|
111
|
+
def some_user; end
|
112
|
+
def render(args); end
|
113
|
+
def respond_to; end
|
114
|
+
end
|
115
|
+
|
116
|
+
subject.build_controller :foo, actions: {
|
117
|
+
index: {
|
118
|
+
params: [:current_user, :params],
|
119
|
+
context: 'foo_context_builder#bar',
|
120
|
+
service: 'baz_service#qux'
|
121
|
+
}
|
122
|
+
}
|
123
|
+
controller = FooController.new
|
124
|
+
expect(controller).to receive_messages(
|
125
|
+
current_user: :some_user,
|
126
|
+
params: {a: :b})
|
127
|
+
|
128
|
+
render_args = nil
|
129
|
+
expect(controller).to receive(:render) do |args|
|
130
|
+
render_args = args
|
131
|
+
end
|
132
|
+
expect(controller).to receive(:respond_to) do |&block|
|
133
|
+
block.call(json_format)
|
134
|
+
end
|
135
|
+
|
136
|
+
expect_any_instance_of(FooContextBuilder).to receive(:bar).with(hash_including(
|
137
|
+
current_user: :some_user,
|
138
|
+
params: {a: :b})) { :context }
|
139
|
+
|
140
|
+
expect_any_instance_of(BazService).to receive(:qux).with(:context) do
|
141
|
+
{ status: :error, errors: ["BOOM"] }
|
142
|
+
end
|
143
|
+
|
144
|
+
controller.index
|
145
|
+
expect(render_args).to eq(json: {errors: ["BOOM"]}, status: 500)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'defines all the action methods' do
|
149
|
+
class FooController
|
150
|
+
def current_user; end
|
151
|
+
def some_user; end
|
152
|
+
def render(args); end
|
153
|
+
end
|
154
|
+
subject.build_controller :foo,
|
155
|
+
params: [:current_user, :params],
|
156
|
+
actions: {
|
157
|
+
index: {
|
158
|
+
context: 'foo_context_builder#bar',
|
159
|
+
service: 'baz_service#qux'
|
160
|
+
},
|
161
|
+
other: {
|
162
|
+
context: 'foo_context_builder#bar',
|
163
|
+
service: 'baz_service#qux'
|
164
|
+
}
|
165
|
+
}
|
166
|
+
controller = FooController.new
|
167
|
+
expect(controller).to respond_to(:index)
|
168
|
+
expect(controller).to respond_to(:other)
|
169
|
+
end
|
170
|
+
|
171
|
+
class FooContextBuilder
|
172
|
+
def bar(opts) {} end
|
173
|
+
end
|
174
|
+
|
175
|
+
class BazService
|
176
|
+
def qux(context) {} end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ddc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Shawn Anderson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: actionpack
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.1'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activesupport
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.1'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.1'
|
83
|
+
description: Use data to tell Rails how to interact with your domain.
|
84
|
+
email:
|
85
|
+
- shawn42@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- Gemfile
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- ddc.gemspec
|
96
|
+
- lib/ddc.rb
|
97
|
+
- lib/ddc/controller_builder.rb
|
98
|
+
- lib/ddc/response_builder.rb
|
99
|
+
- lib/ddc/service_builder.rb
|
100
|
+
- lib/ddc/version.rb
|
101
|
+
- spec/controller_builder_spec.rb
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
homepage: ''
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata: {}
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
requirements: []
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 2.2.2
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
126
|
+
summary: Data Driven Controllers for Rails
|
127
|
+
test_files:
|
128
|
+
- spec/controller_builder_spec.rb
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
has_rdoc:
|