ransack_abbreviator 0.0.2 → 0.0.3

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