effective_resources 1.2.4 → 1.2.5
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 +5 -5
- data/README.md +92 -125
- data/app/controllers/concerns/effective/crud_controller/permitted_params.rb +3 -3
- data/app/controllers/concerns/effective/crud_controller/respond.rb +2 -2
- data/app/controllers/concerns/effective/crud_controller/save.rb +3 -0
- data/app/controllers/concerns/effective/flash_messages.rb +1 -1
- data/lib/effective_resources/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ae9635ad1328b7109aaaf6250dd6e73b1e82c94883a26128f6c175dfaa541d2d
|
4
|
+
data.tar.gz: 5921dbfd7773c0b1eb440b2864de2b1f1c95f0ec0d0de543de70433f185ed165
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 973334cca43d4337328170e7b97f95d2e97d678d24181c067d7f7e1e0c2cd81f79154a8c3c29745fbdace515cb8ea77c53dbbf313804e5331f8f36dc8270b4ab
|
7
|
+
data.tar.gz: 43e5b2f690eac1dbd8b81cb9fbf54f2f3efa95b8886c15cce725b6f6299d4acfca795ef92e4d235caf3189bb3a944beb62e5cd51a4212f6694594c02fa574ef3
|
data/README.md
CHANGED
@@ -2,31 +2,26 @@
|
|
2
2
|
|
3
3
|
The goal of this gem is to reduce the amount of code that needs to be written when developing a ruby on rails website.
|
4
4
|
|
5
|
-
It
|
5
|
+
It's ruby on rails, on effective rails.
|
6
6
|
|
7
|
-
A rails developer will always need to maintain and write:
|
7
|
+
A rails developer will **always** need to maintain and write:
|
8
8
|
|
9
9
|
- The `routes.rb` as it's the single most important file in an entire app.
|
10
10
|
- The `ability.rb` or other authorization.
|
11
|
-
- A normal
|
12
|
-
-
|
13
|
-
- Any
|
11
|
+
- A normal ApplicationRecord model file for each model, `/app/models/post.rb`.
|
12
|
+
- Its corresponding form, `/app/views/posts/_form.html.haml` and `_post.html.haml`
|
13
|
+
- Any javascript and css
|
14
14
|
|
15
|
-
However, all other
|
15
|
+
However, all other areas of code should be automated.
|
16
16
|
|
17
|
-
This gem replaces the following work a rails developer would normally do:
|
17
|
+
This gem **replaces** the following work a rails developer would normally do:
|
18
18
|
|
19
19
|
- Controllers.
|
20
|
-
-
|
20
|
+
- Any file named `index/edit/show/new.html`. We use rails application templates and powerful defaults views so these files need never be written.
|
21
|
+
- Writing `permitted params`. This gem implements a model dsl to define and blacklist params.
|
22
|
+
- Manually checking which actions are available to the `current_user` on each `resource` all the time.
|
23
|
+
- Writing submit buttons
|
21
24
|
|
22
|
-
- Any file named index/edit/show/new.html. We use rails application templates and powerful defaults views so these files need never be written.
|
23
|
-
- Figure out actions available to the `current_user` to each `resource` on the fly, based on controller namespace, the routes.rb and ability.rb
|
24
|
-
- Powerful helpers to render the correct resource action links.
|
25
|
-
- Collection of concern files.
|
26
|
-
|
27
|
-
Make your controller an effective resource controller.
|
28
|
-
Implements the 7 RESTful actions as a one-liner on any controller.
|
29
|
-
Reads the `routes.rb` and serves collection and member actions.
|
30
25
|
|
31
26
|
## Getting Started
|
32
27
|
|
@@ -48,7 +43,21 @@ rails generate effective_resources:install
|
|
48
43
|
|
49
44
|
The generator will install an initializer which describes all configuration options.
|
50
45
|
|
51
|
-
|
46
|
+
Check the `config/initializer/effective_resources.rb` and make sure it's calling your authentication library correctly.
|
47
|
+
|
48
|
+
```
|
49
|
+
config.authorization_method = Proc.new { |controller, action, resource| authorize!(action, resource) } # CanCanCan
|
50
|
+
```
|
51
|
+
|
52
|
+
# Quick Start
|
53
|
+
|
54
|
+
This gem was built to quickly build CRUD interfaces. Automate all the actions, and submit buttons.
|
55
|
+
|
56
|
+
It uses the `params[:commit]` message to call the appropriate action, or `save` on the given resource.
|
57
|
+
|
58
|
+
It reads the `routes.rb` to serve `collection` and `member` actions, and considers `current_user` and `ability.rb`
|
59
|
+
|
60
|
+
Tries to do the right thing in all situations.
|
52
61
|
|
53
62
|
Add to your `app/models/post.rb`:
|
54
63
|
|
@@ -57,7 +66,6 @@ class Post < ApplicationRecord
|
|
57
66
|
belongs_to :author, class_name: 'User'
|
58
67
|
|
59
68
|
# The only thing this block is used for - right now - is permitted_params
|
60
|
-
# So yo
|
61
69
|
effective_resource do
|
62
70
|
category :string
|
63
71
|
title :string
|
@@ -70,23 +78,16 @@ class Post < ApplicationRecord
|
|
70
78
|
|
71
79
|
# The approve! action will be called by Effective::CrudController when submitted on a create/update or member action
|
72
80
|
def approve!
|
73
|
-
raise 'already approved' if approved?
|
81
|
+
raise 'already approved' if approved?s
|
74
82
|
update!(approved: true)
|
75
83
|
end
|
76
|
-
|
77
84
|
end
|
78
85
|
```
|
79
86
|
|
80
87
|
Add to your `routes.rb`:
|
81
88
|
|
82
89
|
```ruby
|
83
|
-
resources :posts
|
84
|
-
get :approve, on: :member
|
85
|
-
post :approve, on: :member
|
86
|
-
|
87
|
-
get :approved, on: :collection
|
88
|
-
post :bulk_approve, on: :collection
|
89
|
-
end
|
90
|
+
resources :posts
|
90
91
|
```
|
91
92
|
|
92
93
|
Add to your contoller:
|
@@ -95,9 +96,58 @@ Add to your contoller:
|
|
95
96
|
class PostsController < ApplicationController
|
96
97
|
include Effective::CrudController
|
97
98
|
|
99
|
+
submit :approve, 'Approve'
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
and in your view:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
= form_with(model: post) do
|
107
|
+
= f.input :text
|
108
|
+
= effective_submit(f) # Will make a Save and an Approve. Rails 5 forms.
|
109
|
+
= simple_form_submit(f) # Ditto.
|
110
|
+
```
|
111
|
+
|
112
|
+
and in your authorization:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
can :approve, Post
|
116
|
+
# can(:approve, Post) { |post| !post.approved? }
|
117
|
+
```
|
118
|
+
|
119
|
+
## Controller
|
120
|
+
|
121
|
+
Implements the 7 RESTful actions: `index`, `new`, `create`, `show`, `edit`, `update`, `destroy`.
|
122
|
+
|
123
|
+
- Loads an appropriate `@posts` or `@post` type instance variable.
|
124
|
+
- Sets a `@page_title` (effective_pages).
|
125
|
+
- Calls authorize as per the configured `EffectiveResources.authorization_method` (flow through to CanCan or Pundit)
|
126
|
+
- Does the create/update save
|
127
|
+
- Sets a `flash[:success]` and redirects on success, or sets a `flash.now[:danger]` and renders on error.
|
128
|
+
- Does the right thing with member and collection actions
|
129
|
+
- Intelligently redirects based on commit message
|
130
|
+
|
131
|
+
You can override individual methods on the CrudController.
|
132
|
+
|
133
|
+
Here is a more advanced example:
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
class PostsController < ApplicationController
|
137
|
+
include Effective::CrudController
|
98
138
|
# Sets the @page_title in a before_filter
|
99
139
|
page_title 'My Posts', only: [:index]
|
100
140
|
|
141
|
+
# Callbacks: before_save, after_save, resource_error
|
142
|
+
before_render(only: :new) do
|
143
|
+
resource.client = current_user.clients.first
|
144
|
+
end
|
145
|
+
|
146
|
+
submit :accept, 'Accept',
|
147
|
+
if: -> { !resource.approved? }, # Imho this check should be kept in ability.rb, but you could do it here.
|
148
|
+
redirect: -> { accepted_posts_path },
|
149
|
+
success: 'The @resource has been approved' # Any @resource will be replaced with @resource.to_s
|
150
|
+
|
101
151
|
# All queries and objects will be built with this scope
|
102
152
|
resource_scope -> { current_user.posts }
|
103
153
|
|
@@ -133,122 +183,39 @@ class PostsController < ApplicationController
|
|
133
183
|
def duplicate_resource(resource)
|
134
184
|
resource_klass.new(resource.attributes.slice('job_site', 'address'))
|
135
185
|
end
|
136
|
-
|
137
186
|
end
|
138
187
|
```
|
139
188
|
|
140
|
-
##
|
141
|
-
|
142
|
-
Implements the 7 RESTful actions: `index`, `new`, `create`, `show`, `edit`, `update`, `destroy`.
|
143
|
-
|
144
|
-
- Loads an appropriate `@posts` or `@post` type instance variable.
|
145
|
-
- Sets a `@page_title` (effective_pages).
|
146
|
-
- Calls authorize as per the configured `EffectiveResources.authorization_method` (flow through to CanCan or Pundit)
|
147
|
-
- Does the create/update save
|
148
|
-
- Sets a `flash[:success]` and redirects on success, or sets a `flash.now[:danger]` and renders on error.
|
149
|
-
- Does the right thing with member and collection actions
|
150
|
-
- Intelligently redirects based on commit message
|
151
|
-
|
152
|
-
## Bootstrap3 Helpers
|
153
|
-
|
154
|
-
### nav_link_to
|
155
|
-
|
156
|
-
Use `nav_link_to` and `nav_dropdown` to create bootstrap3 menus.
|
157
|
-
|
158
|
-
The helper automatically assigns the `active` class based on the request path.
|
159
|
-
|
160
|
-
```haml
|
161
|
-
%nav.navbar.navbar-default
|
162
|
-
.container
|
163
|
-
.navbar-header
|
164
|
-
= link_to(image_tag('logo.png', alt: 'Logo'), '/', class: 'navbar-brand')
|
165
|
-
%button.navbar-toggle.collapsed{data: {toggle: 'collapse', target: '.navbar-collapse', 'aria-expanded': false}}
|
166
|
-
%span.icon-bar
|
167
|
-
%span.icon-bar
|
168
|
-
%span.icon-bar
|
169
|
-
.collapse.navbar-collapse
|
170
|
-
%ul.nav.navbar-nav.navbar-right
|
171
|
-
- if current_user.present?
|
172
|
-
- if can?(:index, Things)
|
173
|
-
= nav_link_to 'Things', things_path
|
174
|
-
|
175
|
-
= nav_dropdown 'Settings' do
|
176
|
-
= nav_link_to 'Account Settings', user_settings_path
|
177
|
-
%li.divider
|
178
|
-
= nav_link_to 'Sign Out', destroy_user_session_path, method: :delete
|
179
|
-
- else
|
180
|
-
= nav_link_to 'Sign In', new_user_session_path
|
181
|
-
```
|
182
|
-
|
183
|
-
### tabs
|
189
|
+
## Helpers
|
184
190
|
|
185
|
-
|
186
|
-
|
187
|
-
The helper inserts both the tablist and the tabpanel, and assigns the `active` class.
|
188
|
-
|
189
|
-
```haml
|
190
|
-
= tabs do
|
191
|
-
= tab 'Imports' do
|
192
|
-
%p Imports
|
193
|
-
|
194
|
-
= tab 'Exports' do
|
195
|
-
%p Exports
|
196
|
-
```
|
197
|
-
|
198
|
-
You can also call `tabs(active: 'Exports') do` to set the active tab.
|
199
|
-
|
200
|
-
## Simple Form Helpers
|
201
|
-
|
202
|
-
### simple_form_submit
|
203
|
-
|
204
|
-
Call `simple_form_submit(f)` like follows:
|
205
|
-
|
206
|
-
```haml
|
207
|
-
= simple_form_for(post) do |f|
|
208
|
-
= f.input :title
|
209
|
-
= f.input :body
|
191
|
+
### effective_submit & simple_form_submit
|
210
192
|
|
193
|
+
```rails
|
194
|
+
= form_with(model: post) do |f|
|
195
|
+
= effective_submit(f)
|
211
196
|
= simple_form_submit(f)
|
212
197
|
```
|
213
198
|
|
214
|
-
|
199
|
+
These helpers output the `= f.submit 'Save'` based on the controllers `submits`, the `current_user` and `ability.rb`.
|
215
200
|
|
216
|
-
|
201
|
+
They try to add good `data-confirm` options for `delete` buttons and sort by `btn-primary`, `btn-secondary` and `btn-danger`.
|
217
202
|
|
218
|
-
|
203
|
+
### Application Templates
|
219
204
|
|
220
|
-
|
221
|
-
= simple_form_for(post) do |f|
|
222
|
-
...
|
223
|
-
= simple_form_save(f)
|
224
|
-
```
|
205
|
+
When you installed the gem, it should make some `views/application/index.html.haml`, `new.html.haml`, etc.
|
225
206
|
|
226
|
-
|
207
|
+
If you're not using haml, you should be, go install `haml`. Or convert to slim, you sly devils.
|
227
208
|
|
228
|
-
|
209
|
+
These files, possibly customized to your app, should replace almost all resource specific views.
|
229
210
|
|
230
|
-
|
211
|
+
Just create a `_form.html.haml` and `_post.html.haml` for each resource.
|
231
212
|
|
232
|
-
|
233
|
-
= effective_submit(f)
|
234
|
-
= effective_save(f)
|
213
|
+
Just put another `app/views/posts/index.html.haml` in the posts directory to override the default template.
|
235
214
|
|
236
|
-
= effective_save(f) do
|
237
|
-
= f.save 'Save'
|
238
|
-
= f.save 'Another'
|
239
215
|
|
240
|
-
|
216
|
+
## Concerns
|
241
217
|
|
242
|
-
|
243
|
-
= f.save 'Will be appended'
|
244
|
-
```
|
245
|
-
|
246
|
-
### Remote Delete will automatically fade out the closest match
|
247
|
-
|
248
|
-
```
|
249
|
-
= link_to 'Delete', post_path(post), remote: true,
|
250
|
-
data: { confirm: "Really delete #{post}?", method: :delete, closest: '.post' }
|
251
|
-
```
|
218
|
+
Sure why not. These don't really fit into my code base anywhere else.
|
252
219
|
|
253
220
|
### acts_as_tokened
|
254
221
|
|
@@ -65,13 +65,13 @@ module Effective
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
permitted_params = permitted_params.
|
68
|
+
permitted_params = permitted_params.flat_map do |k, (datatype, v)|
|
69
69
|
if datatype == :array
|
70
|
-
{ k => [] }
|
70
|
+
[k, { k => [] }]
|
71
71
|
elsif datatype == :permitted_param && k.to_s.ends_with?('_ids')
|
72
72
|
{ k => [] }
|
73
73
|
elsif v.present? && v[:permitted] == :array
|
74
|
-
{ k => [] }
|
74
|
+
[k, { k => [] }]
|
75
75
|
elsif datatype == :permitted_param && v.present? && v.key?(:permitted_attributes)
|
76
76
|
{ k => v[:permitted_attributes] }
|
77
77
|
elsif datatype == :effective_address
|
@@ -20,7 +20,7 @@ module Effective
|
|
20
20
|
|
21
21
|
format.js do
|
22
22
|
flash.now[:success] ||= resource_flash(:success, resource, action)
|
23
|
-
reload_resource unless action == :destroy
|
23
|
+
#reload_resource unless action == :destroy # Removed.
|
24
24
|
render(action) # action.js.erb
|
25
25
|
end
|
26
26
|
else # Default
|
@@ -100,7 +100,7 @@ module Effective
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def template_present?(action)
|
103
|
-
lookup_context.template_exists?("#{action}.#{request.format.symbol || 'html'}", _prefixes)
|
103
|
+
lookup_context.template_exists?("#{action}.#{request.format.symbol.to_s.sub('json', 'js').presence || 'html'}", _prefixes)
|
104
104
|
end
|
105
105
|
|
106
106
|
end
|
@@ -52,6 +52,9 @@ module Effective
|
|
52
52
|
flash.now[:danger] = resource_flash(:danger, resource, action, e: e)
|
53
53
|
|
54
54
|
case e
|
55
|
+
when ActiveRecord::StaleObjectError
|
56
|
+
flash.now[:danger] = "#{flash.now[:danger]} <a href='#', class='alert-link' onclick='window.location.reload(true); return false;'>reload page and try again</a>"
|
57
|
+
raise(ActiveRecord::Rollback) # This is a soft error, we want to display the flash message to user
|
55
58
|
when Effective::ActionFailed, ActiveRecord::RecordInvalid, RuntimeError
|
56
59
|
raise(ActiveRecord::Rollback) # This is a soft error, we want to display the flash message to user
|
57
60
|
else
|
@@ -20,7 +20,7 @@ module Effective
|
|
20
20
|
|
21
21
|
name ||= resource.to_s.presence
|
22
22
|
|
23
|
-
["Unable to #{action}", (" #{name}" if name), (": #{messages}
|
23
|
+
["Unable to #{action}", (" #{name}" if name), (": #{messages}" if messages)].compact.join.html_safe
|
24
24
|
end
|
25
25
|
|
26
26
|
# flash.now[:danger] = "Unable to accept: #{flash_errors(@post)}"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
111
|
version: '0'
|
112
112
|
requirements: []
|
113
113
|
rubyforge_project:
|
114
|
-
rubygems_version: 2.
|
114
|
+
rubygems_version: 2.7.3
|
115
115
|
signing_key:
|
116
116
|
specification_version: 4
|
117
117
|
summary: Make any controller an effective resource controller.
|