restomatic 0.1.0
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/MIT-LICENSE +20 -0
- data/README.md +228 -0
- data/Rakefile +2 -0
- data/lib/restomatic/routing_mapper.rb +97 -0
- data/lib/restomatic/version.rb +3 -0
- data/lib/restomatic.rb +6 -0
- metadata +65 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 5e40b314565dc501d5da5f6b97f108c41c4700a940208b056af5205fa681cb4d
|
|
4
|
+
data.tar.gz: c93b2fc63f639ef8a899e29934b20c7a0492869acdd195a9758c17c4a143ecb2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7e895db99eb254ea860f56e46d371b327576d0403c72520f1f2a7578b7f245b23a1268e79c9ff4a7476e8bdd5e00d1331d38b4df5b634176245c4161c4165e61
|
|
7
|
+
data.tar.gz: 560e927399392480f81eeffaeb45653b4f9a0d4aed1838f5f914bbc2389442f19f23b1b1aea919758adc27b77195ad2437ff2db6b93e50879ec0b0f11f387912
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2022 Brad Gessler
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# RESTomatic
|
|
2
|
+
|
|
3
|
+
RESTomatic helps Rails developers organize nested resources with automatic namespacing. Each nested resource gets its own controller module, making your app cleaner and easier to maintain.
|
|
4
|
+
|
|
5
|
+
Unlike Rails shallow routes that send everything to one controller, RESTomatic enforces proper separation: `Blogs::PostsController`, `Users::PostsController`, etc. keeping your controllers organized and your codebase more maintainable.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add to your Rails application Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
bundle add "restomatic"
|
|
13
|
+
```
|
|
14
|
+
That's it! The routing helpers are automatically available in your `config/routes.rb` file.
|
|
15
|
+
|
|
16
|
+
Then start using more RESTful routes in `config/routes.rb`:
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
resources :blogs do
|
|
20
|
+
nest :posts do # Blogs::PostsController
|
|
21
|
+
collection do
|
|
22
|
+
get :search # Blogs::PostsController#search
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
resources :posts do
|
|
28
|
+
create :comments # Posts::CommentsController#new, #create
|
|
29
|
+
end
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## The Problem
|
|
33
|
+
|
|
34
|
+
Rails provides shallow routes and nested resources, but the syntax becomes verbose and repetitive, especially when you want to properly namespace controllers.
|
|
35
|
+
|
|
36
|
+
### Before RESTomatic
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
resources :blogs do
|
|
40
|
+
scope module: :blogs do
|
|
41
|
+
resources :posts, only: %i[index new create] do
|
|
42
|
+
collection do
|
|
43
|
+
get :search
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
resources :posts do
|
|
50
|
+
scope module: :posts do
|
|
51
|
+
resources :comments, only: %i[new create]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### With RESTomatic
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
resources :blogs do
|
|
60
|
+
nest :posts do # Blogs::PostsController
|
|
61
|
+
collection do
|
|
62
|
+
get :search # Blogs::PostsController#search
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
resources :posts do
|
|
68
|
+
create :comments # Posts::CommentsController#new, #create
|
|
69
|
+
end
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Much cleaner! The `nest` helper automatically:
|
|
73
|
+
- Scopes to the parent resource's module (e.g., `Blogs::PostsController`)
|
|
74
|
+
- Sets sensible defaults for which actions are included
|
|
75
|
+
- Reduces boilerplate while maintaining Rails conventions
|
|
76
|
+
|
|
77
|
+
## Route Helpers
|
|
78
|
+
|
|
79
|
+
### `nest`
|
|
80
|
+
|
|
81
|
+
Nest resources under a parent with automatic module scoping and sensible action defaults.
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
resources :blogs do
|
|
85
|
+
nest :posts # Creates index, new, create actions under Blogs::PostsController
|
|
86
|
+
nest :post # Singular: creates new, create actions (no edit/update/destroy)
|
|
87
|
+
end
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Options:**
|
|
91
|
+
- `except:` - Exclude specific actions (overrides defaults)
|
|
92
|
+
- Singular resources default to excluding: `[:edit, :update, :destroy]`
|
|
93
|
+
- Plural resources default to excluding: `[:show, :edit, :update, :destroy]`
|
|
94
|
+
|
|
95
|
+
**Module-only nesting:**
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
resources :posts do
|
|
99
|
+
nest do
|
|
100
|
+
# Routes defined here will be scoped to Posts module
|
|
101
|
+
# without creating a nested resource
|
|
102
|
+
get :analytics
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### `create`
|
|
108
|
+
|
|
109
|
+
Define routes for creating a resource (new + create actions only).
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
resources :posts do
|
|
113
|
+
create :comments # Only new and create actions
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
create :session # Works with both singular and plural forms
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `edit`
|
|
120
|
+
|
|
121
|
+
Define routes for editing a resource (edit + update actions only).
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
resources :posts do
|
|
125
|
+
edit :metadata # Only edit and update actions
|
|
126
|
+
end
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### `show`
|
|
130
|
+
|
|
131
|
+
Define routes for showing a resource (show action only).
|
|
132
|
+
|
|
133
|
+
```ruby
|
|
134
|
+
resources :posts do
|
|
135
|
+
show :preview # Only show action
|
|
136
|
+
end
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `destroy`
|
|
140
|
+
|
|
141
|
+
Define routes for destroying a resource (destroy action only).
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
resources :posts do
|
|
145
|
+
destroy :attachment # Only destroy action
|
|
146
|
+
end
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `list`
|
|
150
|
+
|
|
151
|
+
Define routes for listing resources (index action only).
|
|
152
|
+
|
|
153
|
+
```ruby
|
|
154
|
+
resources :users do
|
|
155
|
+
list :posts # Only index action
|
|
156
|
+
end
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Real-World Example
|
|
160
|
+
|
|
161
|
+
```ruby
|
|
162
|
+
Rails.application.routes.draw do
|
|
163
|
+
root "home#index"
|
|
164
|
+
|
|
165
|
+
# Public blog routes
|
|
166
|
+
resources :blogs, only: [:index, :show] do
|
|
167
|
+
list :posts # Blogs::PostsController#index
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Admin area with nested resources
|
|
171
|
+
namespace :admin do
|
|
172
|
+
resources :blogs do
|
|
173
|
+
nest :posts do # Admin::Blogs::PostsController
|
|
174
|
+
create :comments # Admin::Blogs::Posts::CommentsController#new, #create
|
|
175
|
+
collection do
|
|
176
|
+
get :scheduled # Admin::Blogs::PostsController#scheduled
|
|
177
|
+
post :bulk_publish # Admin::Blogs::PostsController#bulk_publish
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
resources :posts do
|
|
183
|
+
edit :seo # Admin::Posts::SeosController#edit, #update
|
|
184
|
+
show :preview # Admin::Posts::PreviewsController#show
|
|
185
|
+
destroy :featured_image # Admin::Posts::FeaturedImagesController#destroy
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# User account management
|
|
190
|
+
resource :account do
|
|
191
|
+
nest do
|
|
192
|
+
edit :profile # Accounts::ProfilesController#edit, #update
|
|
193
|
+
edit :password # Accounts::PasswordsController#edit, #update
|
|
194
|
+
show :billing # Accounts::BillingsController#show
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## How It Works
|
|
201
|
+
|
|
202
|
+
RESTomatic extends `ActionDispatch::Routing::Mapper` to add these helper methods. The helpers automatically:
|
|
203
|
+
|
|
204
|
+
1. Detect singular vs. plural resource names
|
|
205
|
+
2. Apply appropriate module scoping
|
|
206
|
+
3. Set sensible action defaults based on the helper used
|
|
207
|
+
4. Work seamlessly with existing Rails routing features
|
|
208
|
+
|
|
209
|
+
## Philosophy
|
|
210
|
+
|
|
211
|
+
Rails routing is powerful but can become verbose when building properly organized applications with shallow routes and namespaced controllers. RESTomatic embraces Rails conventions while reducing boilerplate, making your routes file more readable and maintainable.
|
|
212
|
+
|
|
213
|
+
## Requirements
|
|
214
|
+
|
|
215
|
+
- Rails 7.0+
|
|
216
|
+
- Ruby 3.0+
|
|
217
|
+
|
|
218
|
+
## Contributing
|
|
219
|
+
|
|
220
|
+
1. Fork the repository
|
|
221
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
222
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
223
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
224
|
+
5. Create a new Pull Request
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
module ActionDispatch::Routing
|
|
2
|
+
# I have no idea how or why this works this way, I lifted the pattern from Devise, which came with even
|
|
3
|
+
# more weird stuff. Rails could use an API for adding route helpers to decrease the brittleness of this
|
|
4
|
+
# approach. For now, deal with this helper.
|
|
5
|
+
class Mapper
|
|
6
|
+
def nest(name = nil, *args, except: nil, **kwargs, &block)
|
|
7
|
+
unless resource_scope?
|
|
8
|
+
raise ArgumentError, "can't use nest outside resource(s) scope"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
if name.nil?
|
|
12
|
+
scope module: parent_module_name, &block
|
|
13
|
+
elsif is_singular_resource_name? name
|
|
14
|
+
scope module: parent_module_name do
|
|
15
|
+
except ||= %i[edit update destroy]
|
|
16
|
+
resource name, *args, except: except, **kwargs, &block
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
scope module: parent_module_name do
|
|
20
|
+
except ||= %i[show edit update destroy]
|
|
21
|
+
resources name, *args, except: except, **kwargs, &block
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create(name, *args, **kwargs, &block)
|
|
27
|
+
if resource_scope? && !@scope[:module]
|
|
28
|
+
scope module: parent_module_name do
|
|
29
|
+
resource name, *args, only: %i[new create], **kwargs, &block
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
resource name, *args, only: %i[new create], **kwargs, &block
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def edit(name, *args, **kwargs, &block)
|
|
37
|
+
if resource_scope? && !@scope[:module]
|
|
38
|
+
scope module: parent_module_name do
|
|
39
|
+
resource name, *args, only: %i[edit update], **kwargs, &block
|
|
40
|
+
end
|
|
41
|
+
else
|
|
42
|
+
resource name, *args, only: %i[edit update], **kwargs, &block
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def show(name, *args, **kwargs, &block)
|
|
47
|
+
if resource_scope? && !@scope[:module]
|
|
48
|
+
scope module: parent_module_name do
|
|
49
|
+
resource name, *args, only: :show, **kwargs, &block
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
resource name, *args, only: :show, **kwargs, &block
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def destroy(name, *args, **kwargs, &block)
|
|
57
|
+
if resource_scope? && !@scope[:module]
|
|
58
|
+
scope module: parent_module_name do
|
|
59
|
+
resource name, *args, only: :destroy, **kwargs, &block
|
|
60
|
+
end
|
|
61
|
+
else
|
|
62
|
+
resource name, *args, only: :destroy, **kwargs, &block
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def index(name, *args, **kwargs, &block)
|
|
67
|
+
if resource_scope? && !@scope[:module]
|
|
68
|
+
scope module: parent_module_name do
|
|
69
|
+
resources name, *args, only: :index, **kwargs, &block
|
|
70
|
+
end
|
|
71
|
+
else
|
|
72
|
+
resources name, *args, only: :index, **kwargs, &block
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def parent_module_name
|
|
79
|
+
# For singular resources (resource :account), Rails uses plural controller names (AccountsController)
|
|
80
|
+
# So we need to pluralize the parent resource name for the module scope
|
|
81
|
+
parent_resource.singular ? parent_resource.name.to_s.pluralize : parent_resource.name
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def is_singular_resource_name?(name)
|
|
85
|
+
name_string = name.to_s
|
|
86
|
+
name_string.singularize == name_string
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def resource_plurality(name)
|
|
90
|
+
is_singular_resource_name?(name) ? :resource : :resources
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def inflect_resource_plurality(name, *args, **kwargs, &)
|
|
94
|
+
self.method(resource_plurality(name)).call(name, *args, **kwargs, &)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
data/lib/restomatic.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: restomatic
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Brad Gessler
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2025-11-18 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.0'
|
|
26
|
+
description: Provides cleaner, more intuitive helpers for defining RESTful routes
|
|
27
|
+
with proper scoping and namespacing in Rails
|
|
28
|
+
email:
|
|
29
|
+
- bradgessler@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- MIT-LICENSE
|
|
35
|
+
- README.md
|
|
36
|
+
- Rakefile
|
|
37
|
+
- lib/restomatic.rb
|
|
38
|
+
- lib/restomatic/routing_mapper.rb
|
|
39
|
+
- lib/restomatic/version.rb
|
|
40
|
+
homepage: https://github.com/rocketshipio/restomatic
|
|
41
|
+
licenses:
|
|
42
|
+
- MIT
|
|
43
|
+
metadata:
|
|
44
|
+
allowed_push_host: https://rubygems.org
|
|
45
|
+
homepage_uri: https://github.com/rocketshipio/restomatic
|
|
46
|
+
source_code_uri: https://github.com/rocketshipio/restomatic
|
|
47
|
+
changelog_uri: https://github.com/rocketshipio/restomatic
|
|
48
|
+
rdoc_options: []
|
|
49
|
+
require_paths:
|
|
50
|
+
- lib
|
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '3.0'
|
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
requirements: []
|
|
62
|
+
rubygems_version: 3.6.2
|
|
63
|
+
specification_version: 4
|
|
64
|
+
summary: Better route mappers for Rails applications
|
|
65
|
+
test_files: []
|