typical_situation 1.0.3 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25d81edd5ff28eb30b117722caf4e497c1c795d598d53ac92af1b007306454d9
4
- data.tar.gz: 7ebc26384625a9cc513a6c1cd0308ad9339d812694469b1a3114191ee2449bd9
3
+ metadata.gz: 48bf00bdaee8edb5e3fbf54b68ca577960068cae3dac7804ca56169d738c834c
4
+ data.tar.gz: e11a3d08dd5991937bb08b2b3a731d8bd67f91b19658c25239bef18e60e4f921
5
5
  SHA512:
6
- metadata.gz: 8ed5141d2a0ef301ef1a5b2e07df10c988584c70e9fdcb319499f655b5fba03e19dff789cafd0fb1370bcc2125d916a63711ea51df602cf8fedf2fd853b958cf
7
- data.tar.gz: f34b42196b747b3ba706d61b72afbbe6eee59d31dfab64e933836a5f9e25f9715ff129dd12aac1eccf975413ee51eb14df4f66ed368a131881d30d777c4ac2a5
6
+ metadata.gz: 584cecff5e2be5ac3201983c4a2e0fbe1ec69cf5cd7cc18c91aa2d267bb73a8680194137774889fe9cd546c3f3dc55ee35bcef53ff643e8b5ff54eb741a7e6fe
7
+ data.tar.gz: e31342f32bc78ce7aecf165ce64c51fb38f1fd3d8031ffeec891f38b972945fc0da002227a919afc7942ca61179fe3de4e4dbf4fe3f82af77cc9a014b7ed1b14
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,17 @@ 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. `prepare_resources` - search or filter transforms
121
+ 4. `apply_sorting` - default sorting from `default_sorting_attribute`
122
+ 5. `paginate_resources` - pagination adapter hook
123
+
124
+ **Scoped Collections** - Restrict the base collection based on user permissions, tenancy, or other security boundaries:
113
125
 
114
126
  ```ruby
115
127
  def scoped_resource
@@ -121,6 +133,16 @@ def scoped_resource
121
133
  end
122
134
  ```
123
135
 
136
+ **Search and Filtering** - Apply request-driven filters after scoping and before sorting/pagination:
137
+
138
+ ```ruby
139
+ def prepare_resources(resources)
140
+ resources = resources.where(status: params[:status]) if params[:status].present?
141
+ resources = resources.where("title ILIKE ?", "%#{params[:q]}%") if params[:q].present?
142
+ resources
143
+ end
144
+ ```
145
+
124
146
  **Custom Lookup** - Use different attributes for finding resources:
125
147
 
126
148
  ```ruby
@@ -439,6 +461,19 @@ Start an interactive console to experiment with the gem:
439
461
  bundle exec irb -r typical_situation
440
462
  ```
441
463
 
464
+ ### Releasing
465
+
466
+ Create a release from `main`:
467
+
468
+ ```sh
469
+ bin/release {major|minor|patch|pre}
470
+ git push --follow-tags
471
+ ```
472
+
473
+ The release script validates the repository, bumps the version, creates a git tag.
474
+
475
+ Publishing to RubyGems and creating a GitHub Release are handled automatically by GitHub Actions.
476
+
442
477
  ## Contributing
443
478
 
444
479
  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,29 @@ 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
+ # prepare_resources - standardized additional transforms (search, filter)
50
+ # apply_sorting - applies ORDER BY
51
+ # paginate_resources - applies pagination
52
+ #
53
+ # Override +prepare_resources+ in host controllers to add search/filter
54
+ # behavior without touching sorting or pagination hooks.
44
55
  def get_resources
45
- @resources = paginate_resources(apply_sorting(scoped_resource))
56
+ resources = scoped_resource
57
+ resources = prepare_resources(resources)
58
+ resources = apply_sorting(resources)
59
+ resources = paginate_resources(resources)
60
+ @resources = resources
46
61
  set_collection_instance
47
62
  @resources
48
63
  end
49
64
 
65
+ def prepare_resources(resources)
66
+ resources
67
+ end
68
+
50
69
  def new_resource
51
70
  @resource = collection.build
52
71
  end
@@ -93,20 +112,6 @@ module TypicalSituation
93
112
  resource
94
113
  end
95
114
 
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
115
  def id_param
111
116
  params[:id]
112
117
  end
@@ -117,5 +122,15 @@ module TypicalSituation
117
122
  return resources unless default_sorting_attribute
118
123
  resources.order(default_sorting_attribute => default_sorting_direction)
119
124
  end
125
+
126
+ # Sets the singular ivar named after the model (modules delimited with "__").
127
+ def set_single_instance
128
+ instance_variable_set(:"@#{model_type.to_s.gsub("/", "__")}", @resource)
129
+ end
130
+
131
+ # Sets the plural ivar named after the model (modules delimited with "__").
132
+ def set_collection_instance
133
+ instance_variable_set(:"@#{model_type.to_s.gsub("/", "__").pluralize}", @resources)
134
+ end
120
135
  end
121
136
  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.1.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.1.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
  - - ">="