ransack_ui 0.0.3 → 0.0.4

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.
@@ -17,7 +17,7 @@ Ransack.predicates =
17
17
  Ransack.type_predicates = {}
18
18
  ((o, f) -> f.call o) Ransack.type_predicates, ->
19
19
  @text = @string = ['eq', 'cont', 'matches', 'start', 'end', 'present', 'in']
20
- @boolean = ['true']
20
+ @boolean = ['true', 'null']
21
21
  @integer = @float = @decimal = ['eq', 'null', 'lt', 'gt', 'in']
22
22
  @date = @datetime = @time = ['eq', 'null', 'lt', 'gt']
23
23
 
@@ -26,37 +26,76 @@
26
26
 
27
27
  predicate_changed: (e) ->
28
28
  target = $(e.currentTarget)
29
- value_el = $('input#' + target.attr('id').slice(0, -1) + "v_0_value")
29
+ query_input = $('input#' + target.attr('id').slice(0, -1) + "v_0_value")
30
30
  if target.val() in ["true", "false", "blank", "present", "null", "not_null"]
31
- value_el.val("true")
32
- value_el.hide()
31
+ query_input.val("true")
32
+ query_input.hide()
33
33
  else
34
- unless value_el.is(":visible")
35
- value_el.val("")
36
- value_el.show()
34
+ unless query_input.is(":visible")
35
+ query_input.val("")
36
+ query_input.show()
37
37
 
38
38
  attribute_changed: (e) ->
39
39
  target = $(e.currentTarget)
40
- predicate_select = this.element.find('select#' + target.attr('id').slice(0, -8) + "p")
41
- previous_val = predicate_select.val()
42
- type = target.find('option:selected').data('type')
43
-
44
- # Build array of supported predicates
45
- available = predicate_select.data['predicates']
46
-
47
- predicates = Ransack.type_predicates[type] || []
48
- predicates = $.map predicates, (p) -> [p, Ransack.predicates[p]]
49
-
50
- # Remove all predicates, and add any supported predicates
51
- predicate_select.find('option').each (i, o) -> $(o).remove()
52
-
53
- $.each available, (i, p) ->
54
- [val, label] = [p[0], p[1]]
55
- if val in predicates
56
- predicate_select.append $('<option value='+val+'>'+label+'</option>')
57
-
58
- # Select first predicate if current selection is invalid
59
- predicate_select.select2('val', previous_val)
40
+ selected = target.find('option:selected')
41
+
42
+ base_id = target.attr('id').slice(0, -8)
43
+ predicate_select = this.element.find('select#' + base_id + 'p')
44
+ predicate_select2 = this.element.find('#s2id_' + base_id + 'p')
45
+ query_input = $('input#' + base_id + "v_0_value")
46
+
47
+ if selected.data('ajax-url') and Select2?
48
+ controller = selected.data('controller')
49
+
50
+ # Hide predicate Select2
51
+ predicate_select2.hide()
52
+ # Clear predicates, and set 'eq' predicate
53
+ predicate_select.find('option').each (i, o) -> $(o).remove()
54
+ predicate_select.append $('<option selected="selected" value="eq">is</option>')
55
+
56
+ # Set up Select2 for query input
57
+ query_input.val('')
58
+ query_input.select2
59
+ placeholder: "Search #{selected.data('ajax-entity')}"
60
+ minimumInputLength: 1
61
+ ajax:
62
+ url: selected.data('ajax-url')
63
+ dataType: 'json'
64
+ type: selected.data('ajax-type')
65
+ data: (query, page) ->
66
+ obj = {}
67
+ obj[selected.data('ajax-key')] = query
68
+ obj
69
+ results: (data, page) ->
70
+ {results: $.map(data, (text, id) -> {id: id, text: text}) }
71
+ else
72
+ predicate_select2.show()
73
+ # If Select2 is on query input, remove and set defaults
74
+ if query_select2 = this.element.find('#s2id_' + base_id + 'v_0_value')
75
+ query_input.select2('destroy')
76
+ query_input.val('')
77
+ previous_val = ''
78
+ else
79
+ previous_val = predicate_select.val()
80
+
81
+ # Build array of supported predicates
82
+ available = predicate_select.data['predicates']
83
+ predicates = Ransack.type_predicates[selected.data('type')] || []
84
+ predicates = $.map predicates, (p) -> [p, Ransack.predicates[p]]
85
+
86
+ # Remove all predicates, and add any supported predicates
87
+ predicate_select.find('option').each (i, o) -> $(o).remove()
88
+
89
+ $.each available, (i, p) ->
90
+ [val, label] = [p[0], p[1]]
91
+ if val in predicates
92
+ predicate_select.append $('<option value='+val+'>'+label+'</option>')
93
+
94
+ # Select first predicate if current selection is invalid
95
+ predicate_select.select2('val', previous_val)
96
+
97
+ # Run predicate_changed callback
98
+ predicate_select.change()
60
99
 
61
100
  return true
62
101
 
@@ -109,5 +148,10 @@
109
148
  placeholder: "Select a Field"
110
149
  allowClear: true
111
150
  formatSelection: (object, container) ->
112
- $(object.element).parent().attr('label') + ': ' + object.text
151
+ # Return model name if column is AJAX auto-completed association
152
+ if $(object.element).data('ajax-url')
153
+ object.text
154
+ # Return 'Model: field' if regular column
155
+ else
156
+ $(object.element).parent().attr('label') + ': ' + object.text
113
157
  ) jQuery
@@ -10,4 +10,4 @@
10
10
 
11
11
  = f.value_fields do |v|
12
12
  %span.fields.value{ 'data-object-name' => f.object_name }
13
- = v.text_field :value
13
+ = v.text_field :value, :style => "width: 200px;"
@@ -0,0 +1,3 @@
1
+ module Enumerable
2
+ alias map_to each_with_object
3
+ end
@@ -16,8 +16,10 @@ module Ransack
16
16
  base.class_eval do
17
17
  class_attribute :_ransackers
18
18
  class_attribute :_ransackable_associations
19
+ class_attribute :_ransack_can_autocomplete
19
20
  self._ransackers ||= {}
20
21
  self._ransackable_associations ||= []
22
+ self._ransack_can_autocomplete = false
21
23
  end
22
24
  end
23
25
 
@@ -25,6 +27,10 @@ module Ransack
25
27
  self._ransackable_associations = associations
26
28
  end
27
29
 
30
+ def ransack_can_autocomplete
31
+ self._ransack_can_autocomplete = true
32
+ end
33
+
28
34
  def ransackable_associations(auth_object = nil)
29
35
  all_associations = reflect_on_all_associations.map {|a| a.name.to_s}
30
36
  if self._ransackable_associations.any?
@@ -7,5 +7,9 @@ module Ransack
7
7
  def default_predicates=(options)
8
8
  self.options[:default_predicates] = options
9
9
  end
10
+
11
+ def ajax_options=(options)
12
+ self.options[:ajax_options] = options
13
+ end
10
14
  end
11
15
  end
@@ -1,4 +1,4 @@
1
- require 'ransack/helpers/form_builder'
1
+ require 'ransack/helpers/form_builder'
2
2
 
3
3
  module Ransack
4
4
  module Helpers
@@ -49,17 +49,56 @@ module Ransack
49
49
 
50
50
  def attribute_collection_for_bases(bases)
51
51
  bases.map do |base|
52
+ klass = object.context.traverse(base)
53
+ foreign_keys = klass.reflect_on_all_associations.select(&:belongs_to?).
54
+ map_to({}) {|r, h| h[r.foreign_key.to_sym] = r.class_name }
55
+ ajax_options = Ransack.options[:ajax_options] || {}
56
+
57
+ if base.present?
58
+ model = object.context.traverse(base).model_name
59
+ end
60
+
52
61
  begin
53
62
  [
54
63
  Translate.association(base, :context => object.context),
55
64
  object.context.searchable_attributes(base).map do |c, type|
65
+ # Don't show 'id' column for base model
66
+ next nil if base.blank? && c == 'id'
67
+
56
68
  attribute = attr_from_base_and_column(base, c)
69
+ attribute_label = Translate.attribute(attribute, :context => object.context)
70
+
71
+ # Set model name as label for 'id' column on that model's table.
72
+ if c == 'id'
73
+ foreign_klass = object.context.traverse(base).model_name
74
+ # Check that model can autocomplete. If not, skip this id column.
75
+ next nil unless foreign_klass.constantize._ransack_can_autocomplete
76
+ attribute_label = I18n.translate(foreign_klass, :default => foreign_klass)
77
+ else
78
+ foreign_klass = foreign_keys[c.to_sym]
79
+ end
80
+
81
+ # Add column type as data attribute
82
+ html_options = {:'data-type' => type}
83
+
84
+ if foreign_klass
85
+ # If field is a foreign key, set up 'data-ajax-*' attributes for auto-complete
86
+ controller = foreign_klass.tableize
87
+ html_options[:'data-ajax-entity'] = I18n.translate(controller, :default => controller)
88
+ if ajax_options[:url]
89
+ html_options[:'data-ajax-url'] = ajax_options[:url].sub(':controller', controller)
90
+ else
91
+ html_options[:'data-ajax-url'] = "/#{controller}.json"
92
+ end
93
+ html_options[:'data-ajax-type'] = ajax_options[:type] || 'GET'
94
+ html_options[:'data-ajax-key'] = ajax_options[:key] || 'query'
95
+ end
57
96
  [
58
- Translate.attribute(attribute, :context => object.context),
97
+ attribute_label,
59
98
  attribute,
60
- {:'data-type' => type}
99
+ html_options
61
100
  ]
62
- end
101
+ end.compact
63
102
  ]
64
103
  rescue UntraversableAssociationError => e
65
104
  nil
@@ -1,3 +1,3 @@
1
1
  module RansackUI
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/ransack_ui.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "ransack_ui/version"
2
2
  require "ransack_ui/rails/engine"
3
+ require "core_ext/enumerable"
3
4
 
4
5
  # Require ransack overrides
5
6
  Dir.glob(File.expand_path('../ransack_ui/ransack_overrides/**/*.rb', __FILE__)) {|f| require f }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ransack_ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-06 00:00:00.000000000 Z
12
+ date: 2012-11-12 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Framework for building a search UI with Ransack
15
15
  email:
@@ -33,6 +33,7 @@ files:
33
33
  - app/views/ransack/_condition_fields.html.haml
34
34
  - app/views/ransack/_grouping_fields.html.haml
35
35
  - app/views/ransack/_search.html.haml
36
+ - lib/core_ext/enumerable.rb
36
37
  - lib/ransack_ui.rb
37
38
  - lib/ransack_ui/rails/engine.rb
38
39
  - lib/ransack_ui/ransack_overrides/adapters/active_record/base.rb
@@ -57,7 +58,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
58
  version: '0'
58
59
  segments:
59
60
  - 0
60
- hash: -2955605175423395892
61
+ hash: 739364888355864408
61
62
  required_rubygems_version: !ruby/object:Gem::Requirement
62
63
  none: false
63
64
  requirements:
@@ -66,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
67
  version: '0'
67
68
  segments:
68
69
  - 0
69
- hash: -2955605175423395892
70
+ hash: 739364888355864408
70
71
  requirements: []
71
72
  rubyforge_project:
72
73
  rubygems_version: 1.8.24