effective_resources 1.2.2 → 1.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75c86fb082f32358410e49243ea61b344d1e691a
4
- data.tar.gz: 5a54eba2d20082b290fdd59fb80ed54f934cca40
3
+ metadata.gz: 64dfc3d7de672e57ba2ea0238a214acc4cef4a5e
4
+ data.tar.gz: 5c6e8b73c793b0dbfb1e9b38353621bc67193324
5
5
  SHA512:
6
- metadata.gz: ae81d6db6a9a2ee2059ba36177a93d92bafbfb2a33842f28b4c718c3c478e0a454eb474459a14e072a566c09bfb436769fe7d6e7e797dce77da2ecfccf0ce9d7
7
- data.tar.gz: c17da71ef1ba9a6e64f65d7a5bc256f0b8ab7a0e4d1b3e08d10c0b486970a236e62f553e50300cdbb32cd83fd772ce779a9d1861c8b2b0e17832b33ba6476c7d
6
+ metadata.gz: 4d737b31f4efc019d091a98712d3b4d56f6cd5a82ca18b59273ea838a1d4287f855294801b16351d7de54852d28cb383f9276ce16c721c9103df07477739158a
7
+ data.tar.gz: c07020c1c837060e43dfa69682da5a9027cd33113fc19d0af71bf86e82ec8ff601507433cd99b4e12921b1c4b21f5515a10ce8ec45ac5e0b2becca6c4a871d2a
data/README.md CHANGED
@@ -1,8 +1,32 @@
1
1
  # Effective Resources
2
2
 
3
- Make your controller an effective resource controller.
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
+
5
+ It is ruby on rails, on effective rails.
6
+
7
+ A rails developer will always need to maintain and write:
8
+
9
+ - The `routes.rb` as it's the single most important file in an entire app.
10
+ - The `ability.rb` or other authorization.
11
+ - A normal active record model file for each model / form object / interaction / resource, whatever.
12
+ - A corresponding form.
13
+ - Any javascripts, etc, and unique resource actions.
14
+
15
+ However, all other patterns and a lot of code can be automated.
16
+
17
+ This gem replaces the following work a rails developer would normally do:
4
18
 
19
+ - Controllers.
20
+ - permitted params. This gem implements a model dsl to define and blacklist params. It's not the rails way.
21
+
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.
5
28
  Implements the 7 RESTful actions as a one-liner on any controller.
29
+ Reads the `routes.rb` and serves collection and member actions.
6
30
 
7
31
  ## Getting Started
8
32
 
@@ -26,6 +50,45 @@ The generator will install an initializer which describes all configuration opti
26
50
 
27
51
  ## Usage
28
52
 
53
+ Add to your `app/models/post.rb`:
54
+
55
+ ```ruby
56
+ class Post < ApplicationRecord
57
+ belongs_to :author, class_name: 'User'
58
+
59
+ # The only thing this block is used for - right now - is permitted_params
60
+ # So yo
61
+ effective_resource do
62
+ category :string
63
+ title :string
64
+ body :text
65
+
66
+ approved :boolean, permitted: false # You could write permitted: [:admin] to only permit this in the admin namespace
67
+
68
+ timestamps
69
+ end
70
+
71
+ # The approve! action will be called by Effective::CrudController when submitted on a create/update or member action
72
+ def approve!
73
+ raise 'already approved' if approved?
74
+ update!(approved: true)
75
+ end
76
+
77
+ end
78
+ ```
79
+
80
+ Add to your `routes.rb`:
81
+
82
+ ```ruby
83
+ resources :posts, only: [:index, :show] do
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
+ ```
91
+
29
92
  Add to your contoller:
30
93
 
31
94
  ```ruby
@@ -43,6 +106,9 @@ class PostsController < ApplicationController
43
106
  Post.active.where(user: current_user)
44
107
  end
45
108
 
109
+ # The following methods are discovered from the routes.rb and defined automatically.
110
+ # But you could also define them like this if you wanted.
111
+
46
112
  # When GET request, will render the approve page
47
113
  # When POST|PATCH|PUT request, will call @post.approve! and do the right thing
48
114
  member_action :approve
@@ -56,7 +122,9 @@ class PostsController < ApplicationController
56
122
 
57
123
  protected
58
124
 
59
- # The permitted parameters for this post. Other recognized method names are posts_params and permitted_params
125
+ # The post_params are discovered from the model effective_resource do ... end block.
126
+ # But you could also define them like this if you wanted.
127
+ # Other recognized method names are posts_params and permitted_params
60
128
  def post_params
61
129
  params.require(:post).permit(:id, :author_id, :category, :title, :body)
62
130
  end
@@ -190,6 +258,40 @@ This prevents enumeration of this resource.
190
258
 
191
259
  Make sure to create a string `token` field on your model, then just declare `acts_as_tokened`. There are no options.
192
260
 
261
+ ### acts_as_archived
262
+
263
+ Create an 'archived' boolean filed in your model, then declare `acts_as_archived`.
264
+
265
+ Implements the dumb archived pattern.
266
+
267
+ An archived object should not be displayed on index screens, or any related resource's #new pages
268
+
269
+ effective_select (from the effective_bootstrap gem) is aware of this concern, and calls `.unarchived` and `.archived` appropriately when passed an ActiveRecord relation.
270
+
271
+ Use the cascade argument to cascade archived changes to any has_manys
272
+
273
+ ```ruby
274
+ class Thing < ApplicationRecord
275
+ has_many :comments
276
+ acts_as_archivable cascade: :comments
277
+ end
278
+ ```
279
+
280
+ Each controller needs its own archive and unarchive action.
281
+ To simplify this, use the following route concern.
282
+
283
+ In your routes.rb:
284
+
285
+ ```ruby
286
+ Rails.application.routes.draw do
287
+ acts_as_archived
288
+
289
+ resource :things, concern: :acts_as_archived
290
+ resource :comments, concern: :acts_as_archived
291
+ end
292
+ ```
293
+
294
+ and include Effective::CrudController in your resource controller.
193
295
 
194
296
  ## License
195
297
 
@@ -53,7 +53,7 @@ module Effective
53
53
  elsif atts.blank? || !atts.key?(:permitted)
54
54
  true # Default is true
55
55
  else
56
- permitted = (atts[:permitted].respond_to?(:call) ? instance_exec(&atts[:permitted]) : atts[:permitted])
56
+ permitted = (atts[:permitted].respond_to?(:call) ? Effective::ResourceExec.new(self, resource).instance_exec(&atts[:permitted]) : atts[:permitted])
57
57
 
58
58
  if permitted == true || permitted == false
59
59
  permitted
@@ -36,11 +36,11 @@ module Effective
36
36
  end
37
37
 
38
38
  if args.key?(:if) && args[:if].respond_to?(:call) == false
39
- raise "expected if: to be callable. Try submit :approve, 'Save and Approve', if: -> (resource) { resource.finished? }"
39
+ raise "expected if: to be callable. Try submit :approve, 'Save and Approve', if: -> { resource.finished? }"
40
40
  end
41
41
 
42
42
  if args.key?(:unless) && args[:unless].respond_to?(:call) == false
43
- raise "expected unless: to be callable. Try submit :approve, 'Save and Approve', unless: -> (resource) { resource.declined? }"
43
+ raise "expected unless: to be callable. Try submit :approve, 'Save and Approve', unless: -> { resource.declined? }"
44
44
  end
45
45
 
46
46
  if args.key?(:only)
@@ -78,11 +78,11 @@ module Effective
78
78
  end
79
79
 
80
80
  if args.key?(:if) && args[:if].respond_to?(:call) == false
81
- raise "expected if: to be callable. Try button :approve, 'Approve', if: -> (resource) { resource.finished? }"
81
+ raise "expected if: to be callable. Try button :approve, 'Approve', if: -> { resource.finished? }"
82
82
  end
83
83
 
84
84
  if args.key?(:unless) && args[:unless].respond_to?(:call) == false
85
- raise "expected unless: to be callable. Try button :approve, 'Approve', unless: -> (resource) { resource.declined? }"
85
+ raise "expected unless: to be callable. Try button :approve, 'Approve', unless: -> { resource.declined? }"
86
86
  end
87
87
 
88
88
  if args.key?(:only)
@@ -77,7 +77,7 @@ module EffectiveResourcesHelper
77
77
  end
78
78
 
79
79
  # Filter out false and proc false
80
- actions = actions.select { |_, v| atts[v[:action]].respond_to?(:call) ? instance_exec(&atts[v[:action]]) : (atts[v[:action]] != false) }
80
+ actions = actions.select { |_, v| atts[v[:action]].respond_to?(:call) ? Effective::ResourceExec.new(self, resource).instance_exec(&atts[v[:action]]) : (atts[v[:action]] != false) }
81
81
 
82
82
  # Select Partial
83
83
  partial = ['effective/resource/actions', partial.to_s].join('_') if partial.kind_of?(Symbol)
@@ -5,14 +5,15 @@ module EffectiveResourcesPrivateHelper
5
5
 
6
6
  def permitted_resource_actions(resource, actions)
7
7
  page_action = REPLACE_PAGE_ACTIONS[params[:action]] || params[:action]&.to_sym || :save
8
+ executor = Effective::ResourceExec.new(self, resource)
8
9
 
9
10
  actions.select do |commit, args|
10
11
  action = (args[:action] == :save ? (resource.new_record? ? :create : :update) : args[:action])
11
12
 
12
13
  (args.key?(:only) ? args[:only].include?(page_action) : true) &&
13
14
  (args.key?(:except) ? !args[:except].include?(page_action) : true) &&
14
- (args.key?(:if) ? controller.instance_exec(resource, &args[:if]) : true) &&
15
- (args.key?(:unless) ? !controller.instance_exec(resource, &args[:unless]) : true) &&
15
+ (args.key?(:if) ? executor.instance_exec(&args[:if]) : true) &&
16
+ (args.key?(:unless) ? !executor.instance_exec(&args[:unless]) : true) &&
16
17
  EffectiveResources.authorized?(controller, action, resource)
17
18
  end.inject({}) do |h, (commit, args)|
18
19
  opts = args.except(:default, :only, :except, :if, :unless, :redirect, :success, :danger)
@@ -44,7 +44,7 @@ module ActsAsArchived
44
44
 
45
45
  module CanCan
46
46
  def acts_as_archived(klass)
47
- raise "klass does not implement acts_as_archived" unless klass.acts_as_archived?
47
+ raise "klass does not implement acts_as_archived" unless klass.respond_to?(:acts_as_archived?)
48
48
 
49
49
  can(:archive, klass) { |obj| !obj.archived? }
50
50
  can(:unarchive, klass) { |obj| obj.archived? }
@@ -0,0 +1,19 @@
1
+ # Makes sure resource in any instance_execs is the correct resource
2
+ module Effective
3
+ class ResourceExec
4
+
5
+ def initialize(instance, resource)
6
+ @instance = instance
7
+ @resource = resource
8
+ end
9
+
10
+ def resource
11
+ @resource
12
+ end
13
+
14
+ def method_missing(method, *args, &block)
15
+ @instance.send(method, *args)
16
+ end
17
+
18
+ end
19
+ end
@@ -13,11 +13,11 @@ module Effective
13
13
  end
14
14
 
15
15
  if actions.find { |a| a == :index }
16
- submits['Continue'] = { action: :save, redirect: :index, default: true, unless: -> (resource) { params[:_datatable_id] } }
16
+ submits['Continue'] = { action: :save, redirect: :index, default: true, unless: -> { params[:_datatable_id].present? } }
17
17
  end
18
18
 
19
19
  if actions.find { |a| a == :new }
20
- submits['Add New'] = { action: :save, redirect: :new, default: true, unless: -> (resource) { params[:_datatable_id] } }
20
+ submits['Add New'] = { action: :save, redirect: :new, default: true, unless: -> { params[:_datatable_id].present? } }
21
21
  end
22
22
  end
23
23
  end
@@ -31,9 +31,9 @@ module Effective
31
31
  (member_post_actions - crud_actions).each do |action| # default true means it will be overwritten by dsl methods
32
32
  buttons[action.to_s.titleize] = case action
33
33
  when :archive
34
- { action: action, default: true, if: -> (resource) { !resource.archived? }, class: 'btn btn-danger', 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?"}
34
+ { action: action, default: true, if: -> { !resource.archived? }, class: 'btn btn-danger', 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?"}
35
35
  when :unarchive
36
- { action: action, default: true, if: -> (resource) { resource.archived? }, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?" }
36
+ { action: action, default: true, if: -> { resource.archived? }, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?" }
37
37
  else
38
38
  { action: action, default: true, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?"}
39
39
  end
@@ -79,9 +79,9 @@ module Effective
79
79
 
80
80
  actions[action.to_s.titleize] = case action
81
81
  when :archive
82
- { action: action, default: true, if: -> (resource) { !resource.archived? }, class: 'btn btn-danger', 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?"}
82
+ { action: action, default: true, if: -> { resource.archived? }, class: 'btn btn-danger', 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?"}
83
83
  when :unarchive
84
- { action: action, default: true, if: -> (resource) { resource.archived? }, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?" }
84
+ { action: action, default: true, if: -> { resource.archived? }, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?" }
85
85
  else
86
86
  { action: action, default: true, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?" }
87
87
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveResources
2
- VERSION = '1.2.2'.freeze
2
+ VERSION = '1.2.3'.freeze
3
3
  end
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.2
4
+ version: 1.2.3
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-02-07 00:00:00.000000000 Z
11
+ date: 2019-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -57,6 +57,7 @@ files:
57
57
  - app/models/effective/code_reader.rb
58
58
  - app/models/effective/model_reader.rb
59
59
  - app/models/effective/resource.rb
60
+ - app/models/effective/resource_exec.rb
60
61
  - app/models/effective/resources/actions.rb
61
62
  - app/models/effective/resources/associations.rb
62
63
  - app/models/effective/resources/attributes.rb