ransack_abbreviator 0.0.2 → 0.0.3

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.
@@ -1,9 +1,36 @@
1
1
  module RansackAbbreviator
2
2
  module Abbreviators
3
- module Decoder
3
+ class Decoder
4
+ attr_reader :context
5
+
6
+ def initialize(context)
7
+ @context = context
8
+ end
9
+
10
+ def decode_parameter(param)
11
+ str = param.dup
12
+ pred = Ransack::Predicate.detect_and_strip_from_string!(str)
13
+ decoded_param = nil
14
+ case str
15
+ when /^(g|c|m|groupings|conditions|combinator)=?$/
16
+ decoded_param = param
17
+ else
18
+ conjunctions = str.split("_").select{|s| s == "and" || s == "or" }
19
+ decoded_param = ""
20
+ str.split(/_and_|_or_/).each do |possible_abbr|
21
+ decoded_str = self.context.decode_possible_abbr(possible_abbr)
22
+ decoded_param << (!decoded_str.blank? ? decoded_str : possible_abbr)
23
+ decoded_param << "_#{conjunctions.shift}_" if !conjunctions.blank?
24
+ end
25
+ end
26
+
27
+ decoded_param << "_#{pred}" if pred
28
+ decoded_param
29
+ end
30
+
4
31
  def decode_possible_abbr(possible_abbr)
5
32
  possible_assoc_abbr, possible_attr_abbr = extract_possible_assoc_and_attribute_abbr(possible_abbr)
6
- parent_of_attribute = self.klass
33
+ parent_of_attribute = @context.klass
7
34
  decoded_str = ""
8
35
  if possible_assoc_abbr
9
36
  decoded_str, parent_of_attribute = decode_assoc_abbr(possible_assoc_abbr)
@@ -24,11 +51,11 @@ module RansackAbbreviator
24
51
  decoded_str = ""
25
52
  segments = possible_assoc_abbr.split(/_/)
26
53
  association_parts = []
27
- klass = self.klass
54
+ klass = @context.klass
28
55
 
29
56
  while segments.size > 0 && association_parts << segments.shift
30
57
  assoc_to_test = association_parts.join('_')
31
- if polymorphic_association_specified?(assoc_to_test)
58
+ if Ransack::Context.polymorphic_association_specified?(assoc_to_test)
32
59
  assoc_name, class_type = get_polymorphic_assoc_and_class_type(assoc_to_test)
33
60
  klass = Kernel.const_get(class_type)
34
61
  decoded_str << "of_#{class_type}_type_"
@@ -48,7 +75,7 @@ module RansackAbbreviator
48
75
  [decoded_str, klass]
49
76
  end
50
77
 
51
- def decode_column_abbr(possible_attr_abbr, klass=@klass)
78
+ def decode_column_abbr(possible_attr_abbr, klass=@context.klass)
52
79
  klass.ransackable_column_name_for(possible_attr_abbr)
53
80
  end
54
81
 
@@ -57,7 +84,7 @@ module RansackAbbreviator
57
84
  def get_polymorphic_assoc_and_class_type(possible_assoc_abbr)
58
85
  assoc_name = class_type = nil
59
86
  if (match = possible_assoc_abbr.match(/_of_([^_]+?)_type$/))
60
- assoc_name = self.klass.ransackable_assoc_name_for(match.pre_match)
87
+ assoc_name = @context.klass.ransackable_assoc_name_for(match.pre_match)
61
88
  class_type = RansackAbbreviator.assoc_name_for(match.captures.first).camelize
62
89
  end
63
90
  [assoc_name, class_type]
@@ -1,17 +1,23 @@
1
1
  module RansackAbbreviator
2
2
  module Abbreviators
3
- module Encoder
3
+ class Encoder
4
+ attr_reader :context
5
+
6
+ def initialize(context)
7
+ @context = context
8
+ end
9
+
4
10
  def encode_ransack_str(str)
5
11
  encoded_str = ""
6
- associations, attr_name = self.get_associations_and_attribute(str)
7
- parent_of_attribute = self.klass
12
+ associations, attr_name = @context.get_associations_and_attribute(str)
13
+ parent_of_attribute = @context.klass
8
14
 
9
15
  if attr_name
10
16
  unless associations.blank?
11
- encoded_associations, parent_of_attribute = self.encode_associations(associations, str)
17
+ encoded_associations, parent_of_attribute = encode_associations(associations, str)
12
18
  encoded_str = "#{encoded_associations}."
13
19
  end
14
- encoded_str << self.encode_attribute(attr_name, parent_of_attribute)
20
+ encoded_str << encode_attribute(attr_name, parent_of_attribute)
15
21
  else
16
22
  encoded_str = str
17
23
  end
@@ -20,7 +26,7 @@ module RansackAbbreviator
20
26
  end
21
27
 
22
28
  def encode_associations(associations, ransack_name)
23
- klass = self.klass
29
+ klass = @context.klass
24
30
  encoded_str = ""
25
31
 
26
32
  associations.each_with_index do |assoc, i|
@@ -41,7 +47,7 @@ module RansackAbbreviator
41
47
  [encoded_str, klass]
42
48
  end
43
49
 
44
- def encode_attribute(attr_name, parent=@klass)
50
+ def encode_attribute(attr_name, parent=@context.klass)
45
51
  parent.ransackable_column_abbr_for(attr_name)
46
52
  end
47
53
  end
@@ -34,8 +34,10 @@ module RansackAbbreviator
34
34
  end
35
35
 
36
36
  def ransackable_assoc_abbreviations
37
- associations = reflect_on_all_associations.map{|a| a.name.to_s}
38
- self._ransack_assoc_abbreviations ||= RansackAbbreviator.assoc_abbreviations.select{ |key, val| associations.include?(key) }
37
+ self._ransack_assoc_abbreviations ||= begin
38
+ associations = reflect_on_all_associations.map{|a| a.name.to_s}
39
+ RansackAbbreviator.assoc_abbreviations.select{ |key, val| associations.include?(key) }
40
+ end
39
41
  end
40
42
 
41
43
  def ransackable_column_name_for(possible_abbr)
@@ -3,8 +3,12 @@ require 'ransack_abbreviator/abbreviators/encoder'
3
3
 
4
4
  module Ransack
5
5
  class Context
6
- include RansackAbbreviator::Abbreviators::Decoder
7
- include RansackAbbreviator::Abbreviators::Encoder
6
+ attr_reader :decoder, :encoder
7
+ alias_method :full_ransackable_attribute?, :ransackable_attribute?
8
+ alias_method :full_ransackable_association?, :ransackable_association?
9
+
10
+ delegate :encode_ransack_str, to: :encoder
11
+ delegate :decode_parameter, :decode_possible_abbr, to: :decoder
8
12
 
9
13
  def get_associations_and_attribute(str, klass = @klass, associations = [])
10
14
  attr_name = nil
@@ -25,9 +29,31 @@ module Ransack
25
29
  [associations, attr_name]
26
30
  end
27
31
 
28
- private
32
+ def decoder
33
+ @decoder ||= RansackAbbreviator::Abbreviators::Decoder.new(self)
34
+ end
35
+
36
+ def encoder
37
+ @encoder ||= RansackAbbreviator::Abbreviators::Encoder.new(self)
38
+ end
39
+
40
+ def ransackable_attribute?(str, klass)
41
+ full_ransackable_attribute?(str, klass) || ransackable_attribute_abbreviation?(str, klass)
42
+ end
43
+
44
+ def ransackable_association?(str, klass)
45
+ full_ransackable_association?(str, klass) || ransackable_assoc_abbreviation?(str, klass)
46
+ end
47
+
48
+ def ransackable_attribute_abbreviation?(str, klass)
49
+ klass.ransackable_column_abbreviations.has_value?(str)
50
+ end
51
+
52
+ def ransackable_assoc_abbreviation?(str, klass)
53
+ klass.ransackable_assoc_abbreviations.has_value?(str)
54
+ end
29
55
 
30
- def polymorphic_association_specified?(str)
56
+ def self.polymorphic_association_specified?(str)
31
57
  str && str.match(/_of_([^_]+?)_type$/)
32
58
  end
33
59
  end
@@ -6,8 +6,7 @@ module Ransack
6
6
  def build(params)
7
7
  decoded_attr_names = []
8
8
  params[:a].each do |possible_abbr|
9
- decoded_str = @context.decode_possible_abbr(possible_abbr)
10
- decoded_attr_names << (!decoded_str.blank? ? decoded_str : possible_abbr)
9
+ decoded_attr_names << @context.decode_parameter(possible_abbr)
11
10
  end
12
11
  params[:a] = decoded_attr_names
13
12
  ransack_condition_build(params)
@@ -1,27 +1,23 @@
1
1
  module Ransack
2
2
  class Search
3
3
  alias_method :ransack_search_build, :build
4
+ alias_method :ransack_method_missing, :method_missing
5
+
6
+ def method_missing(method_id, *args)
7
+ method_name = method_id.to_s
8
+ writer = method_name.sub!(/\=$/, '')
9
+ # Decode abbreviation (if it is indeed an abbreviation) so Ransack is happy
10
+ decoded_param = self.context.decode_parameter(method_name)
11
+ decoded_str = writer ? "#{decoded_param}=" : decoded_param
12
+ ransack_method_missing(decoded_str.to_sym, *args)
13
+ end
4
14
 
5
15
  def build(params)
6
16
  # Loop through each of the params and test if any contain abbreviations. If so, convert them to the normal Ransack language
7
17
  new_params = {}
8
18
  collapse_multiparameter_attributes!(params.with_indifferent_access).each do |key, value|
9
- pred = Predicate.detect_from_string(key)
10
- str = base.strip_predicate_and_index_from_param_string(key)
11
- if base.special_condition?(str)
12
- # Maintain the param as-is
13
- new_params[key] = value
14
- else
15
- conjunctions = str.split("_").select{|s| s == "and" || s == "or" }
16
- full_str = ""
17
- str.split(/_and_|_or_/).each do |possible_abbr|
18
- decoded_str = self.context.decode_possible_abbr(possible_abbr)
19
- full_str << (!decoded_str.blank? ? decoded_str : possible_abbr)
20
- full_str << "_#{conjunctions.shift}_" if !conjunctions.blank?
21
- end
22
- full_str << "_#{pred}" if pred
23
- new_params[full_str] = value
24
- end
19
+ decoded_param = self.context.decode_parameter(key)
20
+ new_params[decoded_param] = value
25
21
  end
26
22
 
27
23
  ransack_search_build(new_params)
@@ -1,3 +1,3 @@
1
1
  module RansackAbbreviator
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -21,7 +21,6 @@ RansackAbbreviator.configure do |config|
21
21
  end
22
22
 
23
23
  require "ransack_abbreviator/ransack_extensions/nodes/condition"
24
- require "ransack_abbreviator/ransack_extensions/nodes/grouping"
25
24
  require "ransack_abbreviator/ransack_extensions/context"
26
25
  require "ransack_abbreviator/ransack_extensions/search"
27
26
  require 'ransack_abbreviator/adapters/active_record'
@@ -375,5 +375,30 @@ module Ransack # We're testing Ransack's Search wih abbreviations
375
375
  search.result.where_values.first.to_sql.should eq abbr_search.result.where_values.first.to_sql
376
376
  end
377
377
  end
378
+
379
+ describe '#method_missing' do
380
+ before do
381
+ @search = Search.new(Person)
382
+ end
383
+
384
+ it 'support abbreviations' do
385
+ abbr_search = ransack_abbreviation_for(@search, :middle_name_eq)
386
+ @search.send "#{abbr_search}=", 'Ernie'
387
+ @search.middle_name_eq.should eq 'Ernie'
388
+
389
+ abbr_search = ransack_abbreviation_for(@search, :authored_article_comments_vote_count_lteq)
390
+ @search.send "#{abbr_search}=", 10
391
+ @search.authored_article_comments_vote_count_lteq.should eq 10
392
+
393
+ note_search = Search.new(Note)
394
+ abbr_search = ransack_abbreviation_for(note_search, :notable_of_Person_type_name_eq)
395
+ note_search.send "#{abbr_search}=", 'Ernie'
396
+ note_search.notable_of_Person_type_name_eq.should eq 'Ernie'
397
+ end
398
+
399
+ it 'raises NoMethodError when sent an invalid attribute/abreviation' do
400
+ expect {@search.i_am_garbage}.to raise_error NoMethodError
401
+ end
402
+ end
378
403
  end
379
404
  end
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.2
5
+ version: 0.0.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jamie Davidson
@@ -104,7 +104,6 @@ files:
104
104
  - lib/ransack_abbreviator/constants.rb
105
105
  - lib/ransack_abbreviator/ransack_extensions/context.rb
106
106
  - lib/ransack_abbreviator/ransack_extensions/nodes/condition.rb
107
- - lib/ransack_abbreviator/ransack_extensions/nodes/grouping.rb
108
107
  - lib/ransack_abbreviator/ransack_extensions/search.rb
109
108
  - lib/ransack_abbreviator/version.rb
110
109
  - lib/ransack_abbreviator/view_helpers.rb
@@ -1,18 +0,0 @@
1
- module Ransack
2
- module Nodes
3
- class Grouping < Node
4
- def strip_predicate_and_index_from_param_string(param_string)
5
- strip_predicate_and_index(param_string)
6
- end
7
-
8
- def special_condition?(str)
9
- case str
10
- when /^(g|c|m|groupings|conditions|combinator)=?$/
11
- true
12
- else
13
- false
14
- end
15
- end
16
- end
17
- end
18
- end