tam_select 0.1.0 → 1.0.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: 6cf23ba08878f41cb17355d5ce629542fc3bab8e61756960403223d2abde898c
4
- data.tar.gz: 9257189f40b467cfdf80106c5c2c30ce3430f10395c8bb122b7c6ae09ee6a3c6
3
+ metadata.gz: e3f063f1d79268f900b10c4b86399cba1a34dac0154a90c4c12fd505771a1431
4
+ data.tar.gz: 0cf4fe7a1cf1d1dc479065318819db1ced4e71888e81e6c98a25fc6920841852
5
5
  SHA512:
6
- metadata.gz: 8c2ac3a785840329c378213fa5fdf9499756c44adc64788c6170ac5fc8f8a2de2c18eb7bd8949dbf6cd9792894ef7b5ca75e5b1135066d31052de62598e67510
7
- data.tar.gz: 326c67bbe68fc22799b6a24993bd378ebb06650772d829ffdba775fe2f119997df09a66bb63c99b1661cc85e21b3e29a3f3662b2b71fa57789fb997fc126e368
6
+ metadata.gz: 8ad40f38121d3e83e9260c825c8bbd7546c62d87073fef14ef63c70fd027a1a08bcbd18d51d60198d3a06410b2e3c3ffd325182f99b9b08c1af7b23e725a70c3
7
+ data.tar.gz: 55469f46c8348ed51dff78070efe3ddf8b95ce43cb2ae3d5b299382bf80437022fe1f91066e07c2b4d061abfba0c984d892d958616692a02415c062e4cb622db
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
- # Tam Select
1
+ the # Tam Select
2
2
 
3
3
  [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
4
+ [![Gem Version](https://img.shields.io/badge/version-0.1.1-blue.svg)](https://github.com/tamiru/tam_select)
4
5
 
5
6
  **Tam Select** is an accessible, searchable select component for Ruby on Rails, built for Simple Form, Stimulus, Turbo, and Tailwind CSS. It keeps the native `<select>` as the source of truth, so Rails form submission, validation, selected values, and browser autofill continue to work.
6
7
 
@@ -35,6 +36,7 @@ app/javascript/tam_select/tam_select.js
35
36
  app/javascript/controllers/tam_select_controller.js
36
37
  app/inputs/tam_select_input.rb
37
38
  app/controllers/concerns/tam_select_paginatable.rb
39
+ app/controllers/tam_select_remote_controller.rb
38
40
  app/helpers/tam_select_helper.rb
39
41
  ```
40
42
 
@@ -47,6 +49,23 @@ Add the generated JavaScript to Tailwind's source detection in `app/assets/tailw
47
49
  @source "../../javascript/tam_select/**/*.js";
48
50
  ```
49
51
 
52
+ ### Updating
53
+
54
+ The Rails integration files are copied into your application, so updating the gem does not update them automatically. Commit local customizations first, then run:
55
+
56
+ ```bash
57
+ bundle update tam_select
58
+ bin/rails generate tam_select:install
59
+ ```
60
+
61
+ Rails prompts before replacing changed files. To replace every generated file without prompting, use:
62
+
63
+ ```bash
64
+ bin/rails generate tam_select:install --force
65
+ ```
66
+
67
+ Review `git diff` afterward because `--force` overwrites application-specific customizations.
68
+
50
69
  ## Features
51
70
 
52
71
  - Single and multiple selection
@@ -123,7 +142,7 @@ The install generator creates `app/inputs/tam_select_input.rb`. Use it like any
123
142
  prompt: "Select region",
124
143
  input_html: {
125
144
  tam_options: {
126
- remoteUrl: regions_path,
145
+ remoteUrl: region_options_path(format: :json),
127
146
  minQueryLength: 1
128
147
  }
129
148
  } %>
@@ -153,6 +172,63 @@ The generator installs `TamSelectPaginatable` as a Rails response helper. A comp
153
172
 
154
173
  Secure remote endpoints exactly like other Rails JSON endpoints. Scope records by the current user's permissions and never trust a submitted value merely because it appeared in the dropdown.
155
174
 
175
+ ### Generic remote controller
176
+
177
+ The installer generates `TamSelectRemoteController`. Create a small subclass for each allowed remote source:
178
+
179
+ ```ruby
180
+ # app/controllers/region_options_controller.rb
181
+ class RegionOptionsController < TamSelectRemoteController
182
+ tam_select model: Region, label: :name, search_by: %i[name code]
183
+
184
+ private
185
+
186
+ # Override this method when records require authorization or tenant scoping.
187
+ def tam_select_scope(config)
188
+ current_account.regions.order(:name)
189
+ end
190
+ end
191
+ ```
192
+
193
+ Expose the JSON endpoint and pass it to the input:
194
+
195
+ ```ruby
196
+ # config/routes.rb
197
+ get "region_options", to: "region_options#index", defaults: { format: :json }
198
+ ```
199
+
200
+ ```erb
201
+ <%= form.input :region_id,
202
+ as: :tam_select,
203
+ collection: [form.object.region].compact,
204
+ label_method: :name,
205
+ value_method: :id,
206
+ input_html: {
207
+ tam_options: {
208
+ remoteUrl: region_options_path(format: :json),
209
+ minQueryLength: 1
210
+ }
211
+ } %>
212
+ ```
213
+
214
+ Do not accept a model name from request parameters. Declaring each source in a controller subclass prevents clients from querying arbitrary application models.
215
+
216
+ The browser sends requests such as:
217
+
218
+ ```text
219
+ GET /region_options.json?q=addis&page=1
220
+ Accept: application/json
221
+ ```
222
+
223
+ Test an endpoint independently with:
224
+
225
+ ```bash
226
+ curl -H "Accept: application/json" \
227
+ "http://localhost:3000/region_options.json?q=addis&page=1"
228
+ ```
229
+
230
+ A `406 Not Acceptable` response means the route or controller rejected JSON. Keep `defaults: { format: :json }` on the route, use a `.json` URL, and ensure the controller does not restrict responses to HTML only.
231
+
156
232
  ## Core JavaScript
157
233
 
158
234
  ```js
@@ -20,6 +20,10 @@ module TamSelect
20
20
  copy_file "lib/generators/tam_select/templates/tam_select_paginatable.rb", "app/controllers/concerns/tam_select_paginatable.rb"
21
21
  end
22
22
 
23
+ def copy_remote_controller
24
+ copy_file "lib/generators/tam_select/templates/tam_select_remote_controller.rb", "app/controllers/tam_select_remote_controller.rb"
25
+ end
26
+
23
27
  def copy_helper
24
28
  copy_file "lib/generators/tam_select/templates/tam_select_helper.rb", "app/helpers/tam_select_helper.rb"
25
29
  end
@@ -0,0 +1,44 @@
1
+ class TamSelectRemoteController < ApplicationController
2
+ include TamSelectPaginatable
3
+
4
+ class_attribute :tam_select_config, instance_writer: false
5
+
6
+ def self.tam_select(model:, label:, value: :id, search_by: nil, per_page: 20)
7
+ self.tam_select_config = {
8
+ model: model,
9
+ label: label,
10
+ value: value,
11
+ search_by: Array(search_by || label),
12
+ per_page: per_page
13
+ }.freeze
14
+ end
15
+
16
+ def index
17
+ config = self.class.tam_select_config
18
+ raise "Configure #{self.class.name} with tam_select(...)" unless config
19
+
20
+ records = search(tam_select_scope(config), config)
21
+ render json: tam_select_payload(
22
+ records,
23
+ label: config[:label],
24
+ value: config[:value],
25
+ per_page: config[:per_page]
26
+ )
27
+ end
28
+
29
+ private
30
+
31
+ def tam_select_scope(config)
32
+ config[:model].all
33
+ end
34
+
35
+ def search(records, config)
36
+ query = params[:q].to_s.strip
37
+ return records if query.blank?
38
+
39
+ model = config[:model]
40
+ pattern = "%#{model.sanitize_sql_like(query)}%"
41
+ predicates = config[:search_by].map { |field| model.arel_table[field].matches(pattern) }
42
+ records.where(predicates.reduce(&:or))
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  module TamSelect
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tam_select
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tamiru Hailu
@@ -62,6 +62,7 @@ files:
62
62
  - lib/generators/tam_select/templates/tam_select_helper.rb
63
63
  - lib/generators/tam_select/templates/tam_select_input.rb
64
64
  - lib/generators/tam_select/templates/tam_select_paginatable.rb
65
+ - lib/generators/tam_select/templates/tam_select_remote_controller.rb
65
66
  - lib/tam_select.rb
66
67
  - lib/tam_select/engine.rb
67
68
  - lib/tam_select/version.rb