ransack_abbreviator 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -1
- data/README.md +11 -8
- data/lib/ransack_abbreviator.rb +2 -1
- data/lib/ransack_abbreviator/adapters/active_record/base.rb +24 -6
- data/lib/ransack_abbreviator/configuration.rb +4 -2
- data/lib/ransack_abbreviator/ransack_extensions/helpers/form_builder.rb +65 -0
- data/lib/ransack_abbreviator/ransack_extensions/nodes/condition.rb +12 -4
- data/lib/ransack_abbreviator/version.rb +1 -1
- data/spec/ransack_abbreviator/helpers/form_builder_spec.rb +78 -0
- data/spec/ransack_abbreviator/search_spec.rb +1 -0
- metadata +5 -2
data/CHANGELOG.md
CHANGED
@@ -8,4 +8,9 @@
|
|
8
8
|
|
9
9
|
## v0.0.6
|
10
10
|
|
11
|
-
* First stable release
|
11
|
+
* First stable release
|
12
|
+
|
13
|
+
## v0.0.7
|
14
|
+
|
15
|
+
* Added ability to reference abbreviations in a form by adding a 'abbr_' prefix on each form element.
|
16
|
+
* Created an 'abbr_attribute_select' form helper that does the same as Ransack's attribute_select, but with abbreviations.
|
data/README.md
CHANGED
@@ -16,7 +16,7 @@ gem 'ransack_abbreviator'
|
|
16
16
|
The abbreviator should cause absolutely no problems if you decide to not use abbreviations. It only kicks in when an abbreviation is detected in the params. That said, here's how to use it:
|
17
17
|
|
18
18
|
#### Define Abbreviations
|
19
|
-
First, define some abbreviations for columns and associations
|
19
|
+
First, define some abbreviations for columns and associations. One way to do that is to create a ransack_abbreviator.yml file in your config directory in a structure like this:
|
20
20
|
|
21
21
|
ransack_abbreviations:
|
22
22
|
columns:
|
@@ -36,27 +36,30 @@ RansackAbbreviator.configure do |config|
|
|
36
36
|
end
|
37
37
|
```
|
38
38
|
#### Use the Abbreviated Attribute in your Form
|
39
|
-
In your form,
|
39
|
+
In your form, simply add an 'abbr_' prefix to each form element:
|
40
40
|
|
41
41
|
<%= search_form_for @q do |f| %>
|
42
|
-
<%= f.
|
43
|
-
<%= f.
|
42
|
+
<%= f.abbr_label :name_cont, "Name Contains" %>
|
43
|
+
<%= f.abbr_text_field :name_cont %>
|
44
|
+
<%= f.abbr_label :articles_title_start, "Title of article starts with" %>
|
45
|
+
<%= f.abbr_text_field :articles_title_start %>
|
44
46
|
<%= f.submit %>
|
45
47
|
<% end %>
|
46
48
|
|
47
|
-
When the above form is submitted, what would have normally been a URL param of 'name_cont' is now 'nm_cont'. 'articles_title_start' is now 'ars.tl_start'.
|
49
|
+
When the above form is submitted, what would have normally been a URL param of 'name_cont' is now 'nm_cont'. 'articles_title_start' is now 'ars.tl_start'. View the source of the generated form to see for yourself!
|
48
50
|
|
49
|
-
|
51
|
+
If you're using Ransack's 'attribute_select', simply change it to 'abbr_attribute_select' to utilize abbreviations over the full attribute name.
|
52
|
+
|
53
|
+
See the [Ransack](https://github.com/ernie/ransack) documentation for more info on the language Ransack uses and how to reference associations, columns, and predicates.
|
50
54
|
|
51
55
|
#### Remove those POST hacks!
|
52
56
|
Hopefully, the URL is now at least half the size it could have been before and you can remove all the POST hacks you did to get pagination and whatnot to work correctly!
|
53
57
|
|
54
58
|
### Some Notes
|
55
|
-
*
|
59
|
+
* The code works by abbreviating what it can and leaving what it cannot alone. For example, if you forgot to abbreviate 'articles', then <%= f.abbr_text_field :articles_title_start %> would return 'articles.tl_start' as the ID and param of the text field.
|
56
60
|
|
57
61
|
### To Do
|
58
62
|
* Support abbreviation of 'ransacker' attributes
|
59
|
-
* Extend the 'attribute_select' form helper to support returning attributes as their abbreviations
|
60
63
|
|
61
64
|
### License and Copyright
|
62
65
|
MIT License. Copyright © 2013 [Jamie Davidson](http://jamie-davidson.com)
|
data/lib/ransack_abbreviator.rb
CHANGED
@@ -23,4 +23,5 @@ require "ransack_abbreviator/ransack_extensions/nodes/condition"
|
|
23
23
|
require "ransack_abbreviator/ransack_extensions/context"
|
24
24
|
require "ransack_abbreviator/ransack_extensions/search"
|
25
25
|
require 'ransack_abbreviator/adapters/active_record'
|
26
|
-
require "ransack_abbreviator/view_helpers"
|
26
|
+
require "ransack_abbreviator/view_helpers"
|
27
|
+
require "ransack_abbreviator/ransack_extensions/helpers/form_builder"
|
@@ -14,8 +14,12 @@ module RansackAbbreviator
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def ransack_abbreviate_column!(column_name, column_abbr)
|
17
|
-
|
18
|
-
|
17
|
+
unless column_names.include?(column_name)
|
18
|
+
raise ActiveModel::MissingAttributeError, "missing attribute: #{column_name}"
|
19
|
+
end
|
20
|
+
if self.ransackable_column_abbreviations.has_value?(column_abbr)
|
21
|
+
raise "Column #{self.ransackable_column_abbreviations.key(column_abbr)} already has abbreviaiton #{column_abbr}. Column abbreviations need to be unique"
|
22
|
+
end
|
19
23
|
self._ransack_column_abbreviations[column_name] = column_abbr
|
20
24
|
end
|
21
25
|
|
@@ -24,19 +28,33 @@ module RansackAbbreviator
|
|
24
28
|
end
|
25
29
|
|
26
30
|
def ransack_abbreviate_assoc!(assoc_name, assoc_abbr)
|
27
|
-
|
28
|
-
|
31
|
+
unless reflect_on_all_associations.map{|a| a.name.to_s}.include?(assoc_name)
|
32
|
+
raise ActiveModel::MissingAttributeError, "missing association: #{assoc_name}"
|
33
|
+
end
|
34
|
+
if self.ransackable_assoc_abbreviations.has_value?(assoc_abbr)
|
35
|
+
raise "Association #{self.ransackable_assoc_abbreviations.key(assoc_abbr)} already has abbreviaiton #{assoc_abbr} Association abbreviations need to be unique"
|
36
|
+
end
|
29
37
|
self._ransack_assoc_abbreviations[assoc_name] = assoc_abbr
|
30
38
|
end
|
31
39
|
|
32
40
|
def ransackable_column_abbreviations
|
33
|
-
self._ransack_column_abbreviations ||=
|
41
|
+
self._ransack_column_abbreviations ||= begin
|
42
|
+
self._ransack_column_abbreviations = {}
|
43
|
+
RansackAbbreviator.column_abbreviations.select{ |key, val| column_names.include?(key) }.each do |col, abbr|
|
44
|
+
raise "Column #{self._ransack_column_abbreviations.key(abbr)} already has abbreviaiton #{abbr}" if self._ransack_column_abbreviations.has_value?(abbr)
|
45
|
+
self._ransack_column_abbreviations[col] = abbr
|
46
|
+
end
|
47
|
+
end
|
34
48
|
end
|
35
49
|
|
36
50
|
def ransackable_assoc_abbreviations
|
37
51
|
self._ransack_assoc_abbreviations ||= begin
|
52
|
+
self._ransack_assoc_abbreviations = {}
|
38
53
|
associations = reflect_on_all_associations.map{|a| a.name.to_s}
|
39
|
-
RansackAbbreviator.assoc_abbreviations.select{ |key, val| associations.include?(key) }
|
54
|
+
RansackAbbreviator.assoc_abbreviations.select{ |key, val| associations.include?(key) }.each do |assoc, abbr|
|
55
|
+
raise "Association #{self._ransack_assoc_abbreviations.key(abbr)} already has abbreviaiton #{abbr}" if self._ransack_assoc_abbreviations.has_value?(abbr)
|
56
|
+
self._ransack_assoc_abbreviations[assoc] = abbr
|
57
|
+
end
|
40
58
|
end
|
41
59
|
end
|
42
60
|
|
@@ -11,8 +11,9 @@ module RansackAbbreviator
|
|
11
11
|
|
12
12
|
def column_abbreviations=(abbreviations)
|
13
13
|
if abbreviations
|
14
|
+
raise ArgumentError, "abbreviates must be a Hash" unless abbreviations.is_a?(Hash)
|
14
15
|
if !(abbreviations.values & RansackAbbreviator::Constants::RESERVED_KEYWORDS).blank?
|
15
|
-
|
16
|
+
raise ArgumentError, "You used a reserved keyword as a column abbreviation. Reserverd keywords: #{RansackAbbreviator::Constants::RESERVED_KEYWORDS.join(", ")}"
|
16
17
|
end
|
17
18
|
|
18
19
|
@@column_abbreviations = abbreviations
|
@@ -21,8 +22,9 @@ module RansackAbbreviator
|
|
21
22
|
|
22
23
|
def assoc_abbreviations=(abbreviations)
|
23
24
|
if abbreviations
|
25
|
+
raise ArgumentError, "abbreviates must be a Hash" unless abbreviations.is_a?(Hash)
|
24
26
|
if !(abbreviations.values & RansackAbbreviator::Constants::RESERVED_KEYWORDS).blank?
|
25
|
-
|
27
|
+
raise ArgumentError, "You used a reserved keyword as an association abbreviation. Reserverd keywords: #{RansackAbbreviator::Constants::RESERVED_KEYWORDS.join(", ")}"
|
26
28
|
end
|
27
29
|
|
28
30
|
@@assoc_abbreviations = abbreviations
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
module Ransack
|
4
|
+
module Helpers
|
5
|
+
class FormBuilder < ::ActionView::Helpers::FormBuilder
|
6
|
+
def method_missing(method_id, *args, &block)
|
7
|
+
method_name = method_id.to_s
|
8
|
+
if method_name.starts_with?('abbr_')
|
9
|
+
raise ArgumentError, "abbreviated form helpers must be called inside a search FormBuilder!" unless object.respond_to?(:context)
|
10
|
+
ransack_name = args.shift
|
11
|
+
actual_method = method_name.sub('abbr_', '')
|
12
|
+
abbreviated_ransack_name = object.context.encode_parameter(ransack_name)
|
13
|
+
self.send(actual_method, abbreviated_ransack_name, *args, &block)
|
14
|
+
else
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def abbr_attribute_select(options = {}, html_options = {})
|
20
|
+
raise ArgumentError, "abbr_attribute_select must be called inside a search FormBuilder!" unless object.respond_to?(:context)
|
21
|
+
options[:include_blank] = true unless options.has_key?(:include_blank)
|
22
|
+
associations = association_array(options[:associations])
|
23
|
+
if associations.size > 0
|
24
|
+
bases = [''] + associations
|
25
|
+
grouped_collection = encoded_attribute_collection_for_bases(bases)
|
26
|
+
@template.grouped_collection_select(
|
27
|
+
@object_name, :name, grouped_collection, :last, :first, :first, :last,
|
28
|
+
objectify_options(options), @default_options.merge(html_options)
|
29
|
+
)
|
30
|
+
else
|
31
|
+
collection = encoded_attribute_collection_for_base
|
32
|
+
@template.collection_select(
|
33
|
+
@object_name, :name, collection, :first, :last,
|
34
|
+
objectify_options(options), @default_options.merge(html_options)
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def encoded_attribute_collection_for_base(base=nil)
|
42
|
+
prefix = base.blank? ? "" : "#{base}_"
|
43
|
+
object.context.searchable_attributes(base).map do |attr|
|
44
|
+
[
|
45
|
+
object.context.encode_parameter(prefix + attr),
|
46
|
+
Translate.attribute(prefix + attr, :context => object.context)
|
47
|
+
]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def encoded_attribute_collection_for_bases(bases)
|
52
|
+
bases.map do |base|
|
53
|
+
begin
|
54
|
+
[
|
55
|
+
Translate.association(base, :context => object.context),
|
56
|
+
encoded_attribute_collection_for_base(base)
|
57
|
+
]
|
58
|
+
rescue UntraversableAssociationError => e
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
end.compact
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -4,11 +4,19 @@ module Ransack
|
|
4
4
|
alias_method :ransack_condition_build, :build
|
5
5
|
|
6
6
|
def build(params)
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
attrs = params[:a]
|
8
|
+
unless attrs.blank?
|
9
|
+
case attrs
|
10
|
+
when Array
|
11
|
+
attrs.each_with_index do |attr, i|
|
12
|
+
params[:a][i] = @context.decode_parameter(attr)
|
13
|
+
end
|
14
|
+
when Hash
|
15
|
+
attrs.each do |index, attr|
|
16
|
+
params[:a][index][:name] = @context.decode_parameter(attr[:name])
|
17
|
+
end
|
18
|
+
end
|
10
19
|
end
|
11
|
-
params[:a] = decoded_attr_names
|
12
20
|
ransack_condition_build(params)
|
13
21
|
end
|
14
22
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Ransack
|
4
|
+
module Helpers
|
5
|
+
describe FormBuilder do
|
6
|
+
# Below setup copied from Ransack 0.7.2 form_builder_spec
|
7
|
+
router = ActionDispatch::Routing::RouteSet.new
|
8
|
+
router.draw do
|
9
|
+
resources :people
|
10
|
+
match ':controller(/:action(/:id(.:format)))'
|
11
|
+
end
|
12
|
+
|
13
|
+
include router.url_helpers
|
14
|
+
|
15
|
+
# FIXME: figure out a cleaner way to get this behavior
|
16
|
+
before do
|
17
|
+
@controller = ActionView::TestCase::TestController.new
|
18
|
+
@controller.instance_variable_set(:@_routes, router)
|
19
|
+
@controller.class_eval do
|
20
|
+
include router.url_helpers
|
21
|
+
end
|
22
|
+
|
23
|
+
@controller.view_context_class.class_eval do
|
24
|
+
include router.url_helpers
|
25
|
+
end
|
26
|
+
|
27
|
+
@s = Person.search
|
28
|
+
@controller.view_context.search_form_for @s do |f|
|
29
|
+
@f = f
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'form helpers with abbreviations' do
|
34
|
+
it 'shortens the method to defined Ransack abbreviations' do
|
35
|
+
html = @f.abbr_label :name_eq
|
36
|
+
html.should match /for="q_nm_eq"/
|
37
|
+
|
38
|
+
html = @f.abbr_select :children_name_eq, "<option value=\"Ernie\">Ernie</option><option value=\"Bob\">Bob</option>"
|
39
|
+
html.should match /id="q_ch.nm_eq"/
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'uses the full name for undefined abbreviations' do
|
43
|
+
html = @f.abbr_text_area :articles_body_cont
|
44
|
+
html.should match /id="q_articles.body_cont"/
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'selects previously-entered values' do
|
48
|
+
@s.name_eq = 'Ernie'
|
49
|
+
html = @f.abbr_text_field :name_eq
|
50
|
+
html.should match /value="Ernie"/
|
51
|
+
|
52
|
+
@s.children_name_eq = 'Ernie'
|
53
|
+
html = @f.abbr_text_field :children_name_eq
|
54
|
+
html.should match /value="Ernie"/
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#abbr_attribute_select' do
|
59
|
+
it 'returns ransackable attributes as abbreviations' do
|
60
|
+
html = @f.abbr_attribute_select
|
61
|
+
html.split(/\n/).should have(Person.ransackable_attributes.size + 1).lines
|
62
|
+
Person.ransackable_attributes.each do |attribute|
|
63
|
+
html.should match /<option value="#{@s.context.encode_parameter(attribute)}">/
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns ransackable attributes as abbreviations for associations' do
|
68
|
+
attributes = Person.ransackable_attributes + Comment.ransackable_attributes.map {|a| "authored_article_comments_#{a}"}
|
69
|
+
html = @f.abbr_attribute_select :associations => ['authored_article_comments']
|
70
|
+
html.split(/\n/).should have(attributes.size).lines
|
71
|
+
attributes.each do |attribute|
|
72
|
+
html.should match /<option value="#{@s.context.encode_parameter(attribute)}">/
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -123,6 +123,7 @@ module Ransack # We're testing Ransack's Search wih abbreviations
|
|
123
123
|
end
|
124
124
|
|
125
125
|
context "without abbreviations" do
|
126
|
+
# Below specs copied from Ransack 0.7.2 search_spec. I'm ensuring I didn't break any existing Ransack functionality
|
126
127
|
it 'creates Conditions for top-level attributes' do
|
127
128
|
search = Search.new(Person, :name_eq => 'Ernie')
|
128
129
|
condition = search.base[:name_eq]
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ransack_abbreviator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.7
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jamie Davidson
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2013-02-
|
13
|
+
date: 2013-02-08 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: ransack
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/ransack_abbreviator/constants.rb
|
105
105
|
- lib/ransack_abbreviator/engine.rb
|
106
106
|
- lib/ransack_abbreviator/ransack_extensions/context.rb
|
107
|
+
- lib/ransack_abbreviator/ransack_extensions/helpers/form_builder.rb
|
107
108
|
- lib/ransack_abbreviator/ransack_extensions/nodes/condition.rb
|
108
109
|
- lib/ransack_abbreviator/ransack_extensions/search.rb
|
109
110
|
- lib/ransack_abbreviator/version.rb
|
@@ -117,6 +118,7 @@ files:
|
|
117
118
|
- spec/ransack_abbreviator/adapters/active_record/base_spec.rb
|
118
119
|
- spec/ransack_abbreviator/configuration_spec.rb
|
119
120
|
- spec/ransack_abbreviator/helper_spec.rb
|
121
|
+
- spec/ransack_abbreviator/helpers/form_builder_spec.rb
|
120
122
|
- spec/ransack_abbreviator/search_spec.rb
|
121
123
|
- spec/spec_helper.rb
|
122
124
|
- spec/support/schema.rb
|
@@ -156,6 +158,7 @@ test_files:
|
|
156
158
|
- spec/ransack_abbreviator/adapters/active_record/base_spec.rb
|
157
159
|
- spec/ransack_abbreviator/configuration_spec.rb
|
158
160
|
- spec/ransack_abbreviator/helper_spec.rb
|
161
|
+
- spec/ransack_abbreviator/helpers/form_builder_spec.rb
|
159
162
|
- spec/ransack_abbreviator/search_spec.rb
|
160
163
|
- spec/spec_helper.rb
|
161
164
|
- spec/support/schema.rb
|