activeadmin-searchable_select 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }