ransack_ui 0.0.3 → 0.0.4

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