activeadmin-searchable_select 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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +10 -0
  5. data/.travis.yml +16 -0
  6. data/.yardopts +2 -0
  7. data/Appraisals +15 -0
  8. data/CHANGELOG.md +7 -0
  9. data/Gemfile +3 -0
  10. data/LICENSE.txt +25 -0
  11. data/README.md +247 -0
  12. data/Rakefile +6 -0
  13. data/activeadmin-searchable_select.gemspec +37 -0
  14. data/app/assets/javascripts/active_admin/searchable_select.js.coffee +3 -0
  15. data/app/assets/javascripts/active_admin/searchable_select/init.js.coffee +29 -0
  16. data/app/assets/stylesheets/active_admin/searchable_select.scss +5 -0
  17. data/bin/rspec +17 -0
  18. data/gemfiles/rails_4.2_active_admin_1.0.0.pre4.gemfile +9 -0
  19. data/gemfiles/rails_5.1_active_admin_1.0.gemfile +8 -0
  20. data/gemfiles/rails_5.1_active_admin_1.1.gemfile +8 -0
  21. data/lib/activeadmin-searchable_select.rb +6 -0
  22. data/lib/activeadmin/inputs/filters/searchable_select_input.rb +13 -0
  23. data/lib/activeadmin/inputs/searchable_select_input.rb +11 -0
  24. data/lib/activeadmin/searchable_select.rb +20 -0
  25. data/lib/activeadmin/searchable_select/engine.rb +11 -0
  26. data/lib/activeadmin/searchable_select/option_collection.rb +103 -0
  27. data/lib/activeadmin/searchable_select/resource_dsl_extension.rb +39 -0
  28. data/lib/activeadmin/searchable_select/resource_extension.rb +10 -0
  29. data/lib/activeadmin/searchable_select/select_input_extension.rb +130 -0
  30. data/lib/activeadmin/searchable_select/version.rb +5 -0
  31. data/spec/features/ajax_params_spec.rb +53 -0
  32. data/spec/features/end_to_end_spec.rb +83 -0
  33. data/spec/features/filter_input_spec.rb +191 -0
  34. data/spec/features/form_input_spec.rb +178 -0
  35. data/spec/features/inline_ajax_setting_spec.rb +41 -0
  36. data/spec/features/input_errors_spec.rb +55 -0
  37. data/spec/features/options_dsl_spec.rb +248 -0
  38. data/spec/internal/app/assets/javascripts/active_admin.js +2 -0
  39. data/spec/internal/app/assets/stylesheets/active_admin.scss +2 -0
  40. data/spec/internal/app/controllers/application_controller.rb +5 -0
  41. data/spec/internal/config/database.yml +3 -0
  42. data/spec/internal/config/initializers/assets.rb +3 -0
  43. data/spec/internal/config/routes.rb +3 -0
  44. data/spec/internal/db/schema.rb +26 -0
  45. data/spec/internal/log/.gitignore +1 -0
  46. data/spec/internal/public/favicon.ico +0 -0
  47. data/spec/rails_helper.rb +13 -0
  48. data/spec/spec_helper.rb +96 -0
  49. data/spec/support/active_admin_helpers.rb +9 -0
  50. data/spec/support/capybara.rb +8 -0
  51. data/spec/support/models.rb +21 -0
  52. data/spec/support/pluck_polyfill.rb +12 -0
  53. data/spec/support/reset_settings.rb +5 -0
  54. metadata +311 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e45366aab36050f1bacd26cf7c7e083f73366337
4
+ data.tar.gz: 41b977d5f33c903293d2cccccfcabf2de910c71a
5
+ SHA512:
6
+ metadata.gz: 48d3f353accca041a2bc5d533cc8574d6f895f7b04fca7354b5d10e6fc73c3ae276b555ed031ea8226bcfc0a68f70c49657f737df9c51fb0f6f316700d34c2a4
7
+ data.tar.gz: 1114951d8895a4a25a1e56162d099c9fc60592241ec79b9ee8c573fed3db93e427b3137f41d555c3a658eef3f0df6cecf2a3f4034e8102a8a4280cfa97336a8e
@@ -0,0 +1,9 @@
1
+ .bundle
2
+ .ruby-version
3
+ .ruby-gemset
4
+ Gemfile.lock
5
+ /gemfiles/*.lock
6
+ /pkg/*
7
+ /spec/internal/tmp
8
+ /spec/internal/db/*.sqlite
9
+ /spec/examples.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
@@ -0,0 +1,10 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ # The default of 80 characters is a little to narrow.
5
+ Metrics/LineLength:
6
+ Max: 100
7
+
8
+ # Do not warn about missing magic comment
9
+ Style/FrozenStringLiteralComment:
10
+ Enabled: false
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.4
4
+
5
+ # Use container based travis infrastructure which allows caching
6
+ # features for open source projects.
7
+ sudo: false
8
+ cache:
9
+ bundler: true
10
+
11
+ gemfile:
12
+ - gemfiles/rails_4.2_active_admin_1.0.0.pre4.gemfile
13
+ - gemfiles/rails_5.1_active_admin_1.0.gemfile
14
+ - gemfiles/rails_5.1_active_admin_1.1.gemfile
15
+
16
+ script: bundle exec rspec
@@ -0,0 +1,2 @@
1
+ --no-private
2
+ --markup markdown
@@ -0,0 +1,15 @@
1
+ appraise 'rails-4.2-active-admin-1.0.0.pre4' do
2
+ gem 'rails', '~> 4.2'
3
+ gem 'activeadmin', '1.0.0.pre4'
4
+ gem 'jquery-ui-rails', '~> 5.0'
5
+ end
6
+
7
+ appraise 'rails-5.1-active-admin-1.0' do
8
+ gem 'rails', '~> 5.1'
9
+ gem 'activeadmin', '~> 1.0'
10
+ end
11
+
12
+ appraise 'rails-5.1-active-admin-1.1' do
13
+ gem 'rails', '~> 5.1'
14
+ gem 'activeadmin', '~> 1.1'
15
+ end
@@ -0,0 +1,7 @@
1
+ # CHANGELOG
2
+
3
+ ### Version 1.0.0
4
+
5
+ 2017-10-23
6
+
7
+ - Initial release.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,25 @@
1
+
2
+ Copyright for portions of `codevise/activeadmin-searchable_select`
3
+ held by Mark Fariburn, Praxitar Ltd, 2014 as part of
4
+ `mfairburn/activeadmin-select2` which this project is based on. All
5
+ other copyright for `codevise/activeadmin-searchable_select` held by
6
+ Codevise Solutions Ltd, 2017.
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining
9
+ a copy of this software and associated documentation files (the
10
+ "Software"), to deal in the Software without restriction, including
11
+ without limitation the rights to use, copy, modify, merge, publish,
12
+ distribute, sublicense, and/or sell copies of the Software, and to
13
+ permit persons to whom the Software is furnished to do so, subject to
14
+ the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be
17
+ included in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,247 @@
1
+ # ActiveAdmin Searchable Select
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/activeadmin-searchable_select.svg)](http://badge.fury.io/rb/activeadmin-searchable_select)
4
+ [![Build Status](https://travis-ci.org/codevise/activeadmin-searchable_select.svg?branch=master)](https://travis-ci.org/codevise/activeadmin-searchable_select)
5
+
6
+ Searchable select boxes (via [Select2](https://select2.org/)) for
7
+ ActiveAdmin forms and filters. Extends the ActiveAdmin resource DSL to
8
+ allow defining JSON endpoints to fetch options from asynchronously.
9
+
10
+ ## Installation
11
+
12
+ Add `activeadmin-searchable_select` to your Gemfile:
13
+
14
+ ```ruby
15
+ gem 'activeadmin-searchable_select
16
+ ```
17
+
18
+ Import stylesheets and require javascripts:
19
+
20
+ ```scss
21
+ // active_admin.css.scss
22
+ @import "active_admin/searchable_select";
23
+ ```
24
+
25
+ ```coffee
26
+ # active_admin.js.coffee
27
+ #= require active_admin/searchable_select
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Making Select Boxes Searchable
33
+
34
+ To add search functionality to a select box, use the
35
+ `:searchable_select` input type:
36
+
37
+ ```ruby
38
+ ActiveAdmin.register Product do
39
+ form do |f|
40
+ f.input(:category, as: :searchable_select)
41
+ end
42
+ end
43
+ ```
44
+
45
+ This also works for filters:
46
+
47
+ ```ruby
48
+ ActiveAdmin.register Product do
49
+ filter(:category, as: :searchable_select)
50
+ end
51
+ ```
52
+
53
+ ### Fetching Options via Ajax
54
+
55
+ For large collections, rendering the whole set of options can be to
56
+ expensive. Use the `ajax` option to fetch a set of matching options
57
+ once the user begins to type:
58
+
59
+ ```ruby
60
+
61
+ ActiveAdmin.register Product do
62
+ filter(:category,
63
+ as: :searchable_select,
64
+ ajax: true)
65
+ end
66
+ ```
67
+
68
+ If the input attribute corresponds to an ActiveAdmin resource, it is
69
+ expected to provide the JSON endpoint that provides the options. Use
70
+ the `searchable_select_options` method to define the required
71
+ collection action:
72
+
73
+ ```ruby
74
+ ActiveAdmin.register Category do
75
+ searchable_select_options(scope: Category.all,
76
+ text_attribute: :name)
77
+ end
78
+ ```
79
+
80
+ By default, `scope` needs to be a Ransack enabled ActiveRecord
81
+ collection proxy determining which options are available. The
82
+ attribute given by `text_attribute` will be used to get a display name
83
+ for each record. Via Ransack, it is also used to filter by search
84
+ term. Limiting result set size is handled automatically.
85
+
86
+ You can customize the display text:
87
+
88
+ ```ruby
89
+ ActiveAdmin.register Category do
90
+ searchable_select_options(scope: Category.all,
91
+ text_attribute: :name,
92
+ display_text: ->(record) { "Category: #{record.name}" } )
93
+ end
94
+ ```
95
+
96
+ Note that `text_attribute` is still required to perform filtering via
97
+ Ransack. You can pass the `filter` option, to specify your own
98
+ filtering strategy:
99
+
100
+ ```ruby
101
+ ActiveAdmin.register Category do
102
+ searchable_select_options(scope: Category.all,
103
+ text_attribute: :name,
104
+ filter: lambda |term, scope|
105
+ scope.ransack(name_cont_all: term.split(' ')).result
106
+ end)
107
+ end
108
+ ```
109
+
110
+ `scope` can also be a lambda which is evaluated in the context of the
111
+ collection action defined by the helper:
112
+
113
+ ```ruby
114
+ ActiveAdmin.register Category do
115
+ searchable_select_options(scope: -> { Category.allowed_for(current_user) },
116
+ text_attribute: :name)
117
+ end
118
+ ```
119
+
120
+ If the input attribute is set on the form's object, ajax based
121
+ searchable selects will automatically render a single option to ensure
122
+ the selected item is displayed correctly even before options have been
123
+ loaded asynchronously.
124
+
125
+ #### Specifying the Options Endpoint Resource
126
+
127
+ If the resource that provides the options endpoint cannot be guessed
128
+ based on the input attribute name, you can pass an object with a
129
+ `resource` key as `ajax` option:
130
+
131
+ ```ruby
132
+ ActiveAdmin.register Product do
133
+ form do |f|
134
+ f.input(:additional_category,
135
+ as: :searchable_select,
136
+ ajax: { resource: Category })
137
+ end
138
+ end
139
+ ```
140
+
141
+ #### Mutlple Options Endpoints per Resource
142
+
143
+ A single ActiveAdmin resource can define multiple options endpoints:
144
+
145
+ ```ruby
146
+ ActiveAdmin.register Category do
147
+ searchable_select_options(name: :favorites,
148
+ scope: Category.favorites,
149
+ text_attribute: :name)
150
+
151
+ searchable_select_options(name: :recent,
152
+ scope: Category.recent,
153
+ text_attribute: :name)
154
+ end
155
+ ```
156
+
157
+ To specify which collection to use, pass an object with a
158
+ `collection_name` key as `ajax` option:
159
+
160
+ ```ruby
161
+ ActiveAdmin.register Product do
162
+ form do |f|
163
+ f.input(:category,
164
+ as: :searchable_select,
165
+ ajax: { collection_name: :favorites })
166
+ end
167
+ end
168
+ ```
169
+
170
+ #### Passing Parameters
171
+
172
+ You can pass additional parameters to the options endpoint:
173
+
174
+ ```ruby
175
+ ActiveAdmin.register Product do
176
+ form do |f|
177
+ f.input(:category,
178
+ as: :searchable_select,
179
+ ajax: {
180
+ params: {
181
+ some: 'value'
182
+ }
183
+ })
184
+ end
185
+ end
186
+ ```
187
+
188
+ The lambda passed as `scope` can receive those parameters as first
189
+ argument:
190
+
191
+ ```ruby
192
+ ActiveAdmin.register Category do
193
+ searchable_select_options(scope: lambda do |params|
194
+ Category.find_all_by_some(params[:some])
195
+ end,
196
+ text_attribute: :name)
197
+ end
198
+ ```
199
+
200
+ #### Inlining Ajax Options in Feature Tests
201
+
202
+ When writing UI driven feature specs (i.e. with Capybara),
203
+ asynchronous loading of select options can increase test
204
+ complexity. `activeadmin-searchable_select` provides an option to
205
+ render all available options just like a normal select input while
206
+ still exercsing the same code paths including `scope` and
207
+ `text_attribute` handling.
208
+
209
+ For example with RSpec/Capybara, simply set `inline_ajax_options` true
210
+ for feature specs:
211
+
212
+ ```ruby
213
+ RSpec.configure do |config|
214
+ config.before(:each) do |example|
215
+ ActiveAdmin::Select2.inline_ajax_options = (example.metadata[:type] == :feature)
216
+ end
217
+ end
218
+
219
+ ```
220
+
221
+ ## Development
222
+
223
+ To run the tests install bundled gems and invoke RSpec:
224
+
225
+ ```
226
+ $ bundle
227
+ $ bundle exec rspec
228
+ ```
229
+
230
+ The test suite can be run against different versions of Rails and
231
+ Active Admin (see `Appraisals` file):
232
+
233
+ ```
234
+ $ appraisal install
235
+ $ appraisal rspec
236
+ ```
237
+
238
+ Please make sure changes conform with the styleguide:
239
+
240
+ ```
241
+ $ bundle exec rubocop
242
+ ```
243
+
244
+ ## Acknowledgements
245
+
246
+ Based on
247
+ [mfairburn/activeadmin-select2](https://github.com/mfairburn/activeadmin-select2).
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bundler/gem_tasks'
4
+
5
+ require 'semmy'
6
+ Semmy::Tasks.install
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'activeadmin/searchable_select/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'activeadmin-searchable_select'
9
+ spec.version = ActiveAdmin::SearchableSelect::VERSION
10
+ spec.summary = 'Use searchable selects based on Select2 in Active Admin forms and filters.'
11
+ spec.license = 'MIT'
12
+ spec.authors = ['Codevise Solutions Ltd']
13
+ spec.email = 'info@codevise.de'
14
+ spec.homepage = 'https://github.com/codevise/activeadmin-searchable_select'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.required_ruby_version = '~> 2.1'
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.5'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'appraisal', '~> 2.2'
24
+ spec.add_development_dependency 'rspec-rails', '~> 3.6'
25
+ spec.add_development_dependency 'combustion', '~> 0.7.0'
26
+ spec.add_development_dependency 'database_cleaner', '~> 1.6'
27
+ spec.add_development_dependency 'sqlite3', '~> 1.3'
28
+ spec.add_development_dependency 'capybara', '~> 2.15'
29
+ spec.add_development_dependency 'poltergeist', '~> 1.15'
30
+ spec.add_development_dependency 'rubocop', '~> 0.42.0'
31
+ spec.add_development_dependency 'semmy', '~> 1.0'
32
+ spec.add_development_dependency 'rails'
33
+
34
+ spec.add_runtime_dependency 'activeadmin', '~> 1.x'
35
+ spec.add_runtime_dependency 'jquery-rails', ['>= 3.0', '< 5']
36
+ spec.add_runtime_dependency 'select2-rails', '~> 4.0'
37
+ end
@@ -0,0 +1,3 @@
1
+ #= require select2
2
+
3
+ #= require_tree ./searchable_select
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ initSearchableSelects = (inputs, extra = {}) ->
4
+ inputs.each ->
5
+ item = $(this)
6
+ # reading from data allows <input data-searchable_select='{"tags": ['some']}'>
7
+ # to be passed to select2
8
+ options = $.extend(extra, item.data('searchableSelect'))
9
+ url = item.data('ajaxUrl');
10
+
11
+ if url
12
+ $.extend(
13
+ options,
14
+ ajax: {
15
+ url: url,
16
+ dataType: 'json'
17
+ }
18
+ )
19
+
20
+ item.select2(options)
21
+
22
+ $(document).on 'has_many_add:after', '.has_many_container', (e, fieldset) ->
23
+ initSearchableSelects(fieldset.find('.searchable-select-input'))
24
+
25
+ $(document).on 'page:load turbolinks:load', ->
26
+ initSearchableSelects($(".searchable-select-input"), placeholder: "")
27
+ return
28
+
29
+ $(-> initSearchableSelects($(".searchable-select-input")))
@@ -0,0 +1,5 @@
1
+ @import "select2";
2
+
3
+ .searchable_select.input .select2-container {
4
+ min-width: 30%;
5
+ }