typical_situation 1.0.3 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25d81edd5ff28eb30b117722caf4e497c1c795d598d53ac92af1b007306454d9
4
- data.tar.gz: 7ebc26384625a9cc513a6c1cd0308ad9339d812694469b1a3114191ee2449bd9
3
+ metadata.gz: 1806328a0281819fd09cedb96002dd5e038f56a2b292c608b8e1920bd3e7cf25
4
+ data.tar.gz: fb92828cdf08f013652d379c96e52177b1f6005184b24ac6ea9e9273b4d94383
5
5
  SHA512:
6
- metadata.gz: 8ed5141d2a0ef301ef1a5b2e07df10c988584c70e9fdcb319499f655b5fba03e19dff789cafd0fb1370bcc2125d916a63711ea51df602cf8fedf2fd853b958cf
7
- data.tar.gz: f34b42196b747b3ba706d61b72afbbe6eee59d31dfab64e933836a5f9e25f9715ff129dd12aac1eccf975413ee51eb14df4f66ed368a131881d30d777c4ac2a5
6
+ metadata.gz: 4d997a83448cd809e5c884c67fb55cd5be7fe1cf2869b6b177e884300c06cd63b65fce54c85f594b68f239bee417b629e9e9335480ed049c6f05d02d0ad2592f
7
+ data.tar.gz: c4b44e7839dfdcdc8d896354748e154e12c270bfc1c93be8f9167b65f774d24f970ebdc69dc493890bd0f47c582d8075a14d8622963647d69b0c0e55c7bf8c54
data/README.md CHANGED
@@ -8,15 +8,17 @@ A Ruby mixin (module) providing the seven standard resource actions & responses
8
8
 
9
9
  Tested in:
10
10
 
11
- - Rails 7.0
12
- - Rails 7.1
11
+ - Rails 7.2
13
12
  - Rails 8.0
13
+ - Rails 8.1
14
14
 
15
15
  Against Ruby versions:
16
16
 
17
+ - 3.1
17
18
  - 3.2
18
19
  - 3.3
19
20
  - 3.4
21
+ - 4.0
20
22
 
21
23
  Add to your **Gemfile**:
22
24
 
@@ -109,7 +111,18 @@ The library is split into modules:
109
111
 
110
112
  #### Common Customization Hooks
111
113
 
112
- **Scoped Collections** - Filter the collection based on user permissions or other criteria:
114
+ Most customization hooks are intended to be overridden as `private` or `protected` controller methods so they do not become public controller actions.
115
+
116
+ For index actions, resources move through this pipeline:
117
+
118
+ 1. `collection` - base relation from the host controller
119
+ 2. `scoped_resource` - visibility/tenant/security scoping
120
+ 3. `apply_filtering` - request-driven search and filter transforms
121
+ 4. `apply_sorting` - default sorting from `default_sorting_attribute`
122
+ 5. `paginate_resources` - pagination adapter hook
123
+ 6. `prepare_resources` - post-process the loaded records
124
+
125
+ **Scoped Collections** - Restrict the base collection based on user permissions, tenancy, or other security boundaries:
113
126
 
114
127
  ```ruby
115
128
  def scoped_resource
@@ -121,6 +134,24 @@ def scoped_resource
121
134
  end
122
135
  ```
123
136
 
137
+ **Search and Filtering** - Apply request-driven filters after scoping and before sorting/pagination:
138
+
139
+ ```ruby
140
+ def apply_filtering(resources)
141
+ resources = resources.where(status: params[:status]) if params[:status].present?
142
+ resources = resources.where("title ILIKE ?", "%#{params[:q]}%") if params[:q].present?
143
+ resources
144
+ end
145
+ ```
146
+
147
+ **Post-processing** - Mutate or decorate the final paginated record set (e.g. compute a derived attribute on every record):
148
+
149
+ ```ruby
150
+ def prepare_resources(resources)
151
+ resources.each { |post| post.current_user_liked = liked_post_ids.include?(post.id) }
152
+ end
153
+ ```
154
+
124
155
  **Custom Lookup** - Use different attributes for finding resources:
125
156
 
126
157
  ```ruby
@@ -439,6 +470,19 @@ Start an interactive console to experiment with the gem:
439
470
  bundle exec irb -r typical_situation
440
471
  ```
441
472
 
473
+ ### Releasing
474
+
475
+ Create a release from `main`:
476
+
477
+ ```sh
478
+ bin/release {major|minor|patch|pre}
479
+ git push --follow-tags
480
+ ```
481
+
482
+ The release script validates the repository, bumps the version, creates a git tag.
483
+
484
+ Publishing to RubyGems and creating a GitHub Release are handled automatically by GitHub Actions.
485
+
442
486
  ## Contributing
443
487
 
444
488
  Bug reports and pull requests are welcome on GitHub at https://github.com/apsislabs/typical_situation.
@@ -3,6 +3,8 @@
3
3
  module TypicalSituation
4
4
  # These Identity methods must be defined for each implementation.
5
5
  module Identity
6
+ protected
7
+
6
8
  # Symbolized, underscored version of the model (class) to use.
7
9
  def model_type
8
10
  raise(NotImplementedError, "#model_type must be defined in the TypicalSituation implementation.")
@@ -4,6 +4,8 @@ module TypicalSituation
4
4
  # Model operations.
5
5
  # Assume that we're working w/ an ActiveRecord association collection.
6
6
  module Operations
7
+ protected
8
+
7
9
  def scoped_resource
8
10
  collection
9
11
  end
@@ -41,12 +43,35 @@ module TypicalSituation
41
43
  !@resource.errors.empty?
42
44
  end
43
45
 
46
+ # Collection pipeline lifecycle:
47
+ # collection - base relation (user-defined, required)
48
+ # scoped_resource - wraps/scopes the collection (visibility, tenancy, PHI)
49
+ # apply_filtering - applies search/filter params
50
+ # apply_sorting - applies ORDER BY
51
+ # paginate_resources - applies pagination
52
+ # prepare_resources - post-processes the loaded records (e.g. set a computed attribute)
53
+ #
54
+ # Override +apply_filtering+ to add search/filter behavior.
55
+ # Override +prepare_resources+ to mutate or decorate the final record set.
44
56
  def get_resources
45
- @resources = paginate_resources(apply_sorting(scoped_resource))
57
+ resources = scoped_resource
58
+ resources = apply_filtering(resources)
59
+ resources = apply_sorting(resources)
60
+ resources = paginate_resources(resources)
61
+ resources = prepare_resources(resources)
62
+ @resources = resources
46
63
  set_collection_instance
47
64
  @resources
48
65
  end
49
66
 
67
+ def apply_filtering(resources)
68
+ resources
69
+ end
70
+
71
+ def prepare_resources(resources)
72
+ resources
73
+ end
74
+
50
75
  def new_resource
51
76
  @resource = collection.build
52
77
  end
@@ -93,20 +118,6 @@ module TypicalSituation
93
118
  resource
94
119
  end
95
120
 
96
- # Set the singular instance variable named after the model. Modules are delimited with "_".
97
- # Example: a MockApplePie resource is set to ivar @mock_apple_pie.
98
- def set_single_instance
99
- instance_variable_set(:"@#{model_type.to_s.gsub("/", "__")}", @resource)
100
- end
101
-
102
- # Set the plural instance variable named after the model. Modules are delimited with "_".
103
- # Example: a MockApplePie resource collection is set to ivar @mock_apple_pies.
104
- def set_collection_instance
105
- instance_variable_set(:"@#{model_type.to_s.gsub("/", "__").pluralize}", @resources)
106
- end
107
-
108
- protected
109
-
110
121
  def id_param
111
122
  params[:id]
112
123
  end
@@ -117,5 +128,15 @@ module TypicalSituation
117
128
  return resources unless default_sorting_attribute
118
129
  resources.order(default_sorting_attribute => default_sorting_direction)
119
130
  end
131
+
132
+ # Sets the singular ivar named after the model (modules delimited with "__").
133
+ def set_single_instance
134
+ instance_variable_set(:"@#{model_type.to_s.gsub("/", "__")}", @resource)
135
+ end
136
+
137
+ # Sets the plural ivar named after the model (modules delimited with "__").
138
+ def set_collection_instance
139
+ instance_variable_set(:"@#{model_type.to_s.gsub("/", "__").pluralize}", @resources)
140
+ end
120
141
  end
121
142
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module TypicalSituation
4
4
  module Permissions
5
+ protected
6
+
5
7
  def authorized?(_action, _resource = nil)
6
8
  true
7
9
  end
@@ -3,6 +3,8 @@
3
3
  module TypicalSituation
4
4
  # Rails MIME responses.
5
5
  module Responses
6
+ protected
7
+
6
8
  # Return the collection as HTML or JSON
7
9
  #
8
10
  def respond_with_resources
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TypicalSituation
4
- VERSION = "1.0.3"
4
+ VERSION = "1.2.0"
5
5
  end
@@ -40,6 +40,7 @@ module TypicalSituation
40
40
  define_method :model_type do
41
41
  model_type_symbol
42
42
  end
43
+ protected :model_type
43
44
 
44
45
  if only
45
46
  only.each do |action|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typical_situation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mars Hall
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.0
19
+ version: 7.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 7.0.0
26
+ version: 7.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: appraisal
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +53,21 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: 2.2.0
55
55
  - !ruby/object:Gem::Dependency
56
- name: byebug
56
+ name: bump
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: debug
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
@@ -210,7 +224,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
210
224
  requirements:
211
225
  - - ">="
212
226
  - !ruby/object:Gem::Version
213
- version: 3.0.0
227
+ version: 3.1.0
214
228
  required_rubygems_version: !ruby/object:Gem::Requirement
215
229
  requirements:
216
230
  - - ">="