ransack_ui 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  Provides HTML templates and JavaScript to build a fully functional
4
4
  advanced search form using Ransack.
5
5
 
6
+ Please note: this project is still in *alpha* and the following instructions are not yet complete/fully working.
7
+
6
8
  ## Installation
7
9
 
8
10
  Add this line to your application's Gemfile:
@@ -17,6 +19,28 @@ Or install it yourself as:
17
19
 
18
20
  $ gem install ransack_ui
19
21
 
22
+ ## Usage
23
+
24
+ Make your model ransackable (if you name associations, it will enable you to search them aswell).
25
+
26
+ ```ruby
27
+ has_ransackable_associations %w(account tags)
28
+ ransack_can_autocomplete
29
+ ```
30
+
31
+ In your controller, where you'd like to add search functionality, add the following before_filter hook. You can change the 'index' action if needed.
32
+
33
+ ```ruby
34
+ before_filter :load_ransack_search, :only => :index
35
+ ```
36
+
37
+ Insert the following helper call into your rails view code where you'd like the search form to appear.
38
+
39
+ ```ruby
40
+ = ransack_ui_search
41
+ ```
42
+
43
+ Now you can start playing with the results.
20
44
 
21
45
  ## Contributing
22
46
 
@@ -25,3 +49,9 @@ Or install it yourself as:
25
49
  3. Commit your changes (`git commit -am 'Add some feature'`)
26
50
  4. Push to the branch (`git push origin my-new-feature`)
27
51
  5. Create new Pull Request
52
+
53
+ ## Credits / Acknowledgements
54
+
55
+ * Nathan Broadbent (ndbroadbent) - creator of ransack_ui code
56
+ * Ernie Miller (ernie) for creating ransack - https://github.com/ernie/ransack
57
+ * Steve Kenworthy (steveyken) - for tiny tweaks
@@ -12,7 +12,8 @@
12
12
 
13
13
  # Store initial predicates and set up Select2 on select lists in .filters
14
14
  containers = el.find('.filters')
15
- @init_select2(containers)
15
+ if Select2?
16
+ @init_select2(containers)
16
17
  @store_initial_predicates(containers)
17
18
 
18
19
  if $.ransack.button_group_select?
@@ -31,7 +32,6 @@
31
32
 
32
33
  base_id = target.attr('id').slice(0, -8)
33
34
  predicate_select = @element.find("select##{base_id}p")
34
- predicate_select2 = @element.find("#s2id_#{base_id}p")
35
35
  query_input = $("input##{base_id}v_0_value")
36
36
 
37
37
  # Initialize datepicker if column is date/datetime/time
@@ -70,14 +70,17 @@
70
70
 
71
71
  # Handle regular columns
72
72
  else
73
- predicate_select2.select2("enable")
74
- # If Select2 is on query input, remove and set defaults
75
- if (query_select2 = @element.find("#s2id_#{base_id}v_0_value")).length > 0
76
- query_input.select2('destroy')
77
- query_input.val('')
78
- previous_val = ''
79
- else
80
- previous_val = predicate_select.val()
73
+ if Select2?
74
+ predicate_select2 = @element.find("#s2id_#{base_id}p")
75
+ predicate_select2.select2("enable")
76
+
77
+ # If Select2 is on query input, remove and set defaults
78
+ if (query_select2 = @element.find("#s2id_#{base_id}v_0_value")).length > 0
79
+ query_input.select2('destroy')
80
+ query_input.val('')
81
+ previous_val = ''
82
+ else
83
+ previous_val = predicate_select.val()
81
84
 
82
85
  # Build array of supported predicates
83
86
  available = predicate_select.data['predicates']
@@ -103,7 +106,8 @@
103
106
  predicate_select.append $("<option value=#{predicate}>#{label}</option>")
104
107
 
105
108
  # Select first predicate if current selection is invalid
106
- predicate_select.select2('val', previous_val)
109
+ if Select2?
110
+ predicate_select.select2('val', previous_val)
107
111
 
108
112
  # Run predicate_changed callback
109
113
  predicate_select.change()
@@ -149,13 +153,15 @@
149
153
  # Dsiables predicate choices and sets it to 'eq'
150
154
  force_eq_predicate: (base_id) ->
151
155
  predicate_select = @element.find("select##{base_id}p")
152
- predicate_select2 = @element.find("#s2id_#{base_id}p")
153
- # Disable predicate Select2
154
- predicate_select2.select2('disable')
155
156
  # Clear predicates, and set 'eq' predicate
156
157
  predicate_select.find('option').each (i, o) -> $(o).remove()
157
158
  predicate_select.append $('<option selected="selected" value="eq">is</option>')
158
- predicate_select2.select2('val', 'eq')
159
+
160
+ if Select2?
161
+ predicate_select2 = @element.find("#s2id_#{base_id}p")
162
+ # Disable predicate Select2
163
+ predicate_select2.select2('disable')
164
+ predicate_select2.select2('val', 'eq')
159
165
 
160
166
  # Attempts to find a predicate translation for the specific column type,
161
167
  # or returns the default label.
@@ -212,14 +218,15 @@
212
218
  # Hide all query inputs
213
219
  inputs.hide()
214
220
 
215
- # Find newly created input and setup Select2
216
- multi_query = @element.find('#' + multi_id)
217
- multi_query.select2
218
- tags: []
219
- tokenSeparators: [',']
220
- formatNoMatches: (t) ->
221
- "Add a search term"
222
- multi_query.select2('val', values)
221
+ if Select2?
222
+ # Find newly created input and setup Select2
223
+ multi_query = @element.find('#' + multi_id)
224
+ multi_query.select2
225
+ tags: []
226
+ tokenSeparators: [',']
227
+ formatNoMatches: (t) ->
228
+ "Add a search term"
229
+ multi_query.select2('val', values)
223
230
 
224
231
  add_query_input: (base_input, base_name, id, value) ->
225
232
  base_input.after $('<input name="'+base_name+'['+id+'][value]" '+
@@ -235,18 +242,18 @@
235
242
  content = target.data("content")
236
243
  new_id = new Date().getTime()
237
244
  regexp = new RegExp('new_' + type, 'g')
238
- container = target.closest('p')
239
- container.before content.replace(regexp, new_id)
240
- prev_container = container.prev()
245
+ target.before content.replace(regexp, new_id)
246
+ prev_container = target.prev()
241
247
 
242
- @init_select2(prev_container)
248
+ if Select2?
249
+ @init_select2(prev_container)
243
250
 
244
251
  if $.ransack.button_group_select?
245
252
  @init_button_group_select(prev_container)
246
253
 
247
254
  @store_initial_predicates(prev_container)
248
255
  # Fire change event on any new selects.
249
- container.prev().find("select").change()
256
+ prev_container.find("select").change()
250
257
  false
251
258
 
252
259
  remove_fields: (e) ->
@@ -269,33 +276,32 @@
269
276
  predicate_select.data['predicates'] = predicates
270
277
 
271
278
  init_select2: (container) ->
272
- if Select2?
273
- container.find('select.ransack_predicate').select2
274
- width: '160px'
275
- formatNoMatches: (term) ->
276
- "Select a field first"
277
-
278
- container.find('select.ransack_attribute').select2
279
- width: '230px'
280
- placeholder: "Select a Field"
281
- allowClear: true
282
- formatSelection: (object, container) ->
283
- # Return 'Model: field' unless column is on root model
284
- if !object.element || $(object.element).data('root-model')
279
+ container.find('select.ransack_predicate').select2
280
+ width: '160px'
281
+ formatNoMatches: (term) ->
282
+ "Select a field first"
283
+
284
+ container.find('select.ransack_attribute').select2
285
+ width: '230px'
286
+ placeholder: "Select a Field"
287
+ allowClear: true
288
+ formatSelection: (object, container) ->
289
+ # Return 'Model: field' unless column is on root model
290
+ if !object.element || $(object.element).data('root-model')
291
+ object.text
292
+ else
293
+ group_label = $(object.element).parent().attr('label')
294
+ # Avoid labels like 'Contact: Contact'
295
+ if group_label == object.text
285
296
  object.text
297
+ else if group_label?
298
+ group_label + ': ' + object.text
286
299
  else
287
- group_label = $(object.element).parent().attr('label')
288
- # Avoid labels like 'Contact: Contact'
289
- if group_label == object.text
290
- object.text
291
- else if group_label?
292
- group_label + ': ' + object.text
293
- else
294
- object.text
295
-
296
- @element.find('select.ransack_sort').select2
297
- width: '230px'
298
- placeholder: "Select a Field"
300
+ object.text
301
+
302
+ @element.find('select.ransack_sort').select2
303
+ width: '230px'
304
+ placeholder: "Select a Field"
299
305
 
300
306
  init_button_group_select: (containers) ->
301
307
  containers.find('select.ransack_combinator, select.ransack_sort_order').button_group_select()
@@ -1,4 +1,4 @@
1
- #ransack_search {
1
+ .ransack_search {
2
2
  .remove_fields, .ransack_attribute, .ransack_predicate,
3
3
  .ransack_query, .ransack_sort_order, .ransack_sort,
4
4
  .btn-group-select {
@@ -15,14 +15,19 @@
15
15
  &:hover { opacity: 0.6; }
16
16
  }
17
17
  .remove_fields.btn {
18
- padding: 0px 3px;
18
+ padding: 0px 3px 2px;
19
19
  &:hover { opacity: 1; }
20
20
  }
21
21
 
22
- a.btn {
23
- i { margin-bottom: 2px; }
22
+ .add_fields.btn {
23
+ margin-top: 20px;
24
+ }
25
+
26
+ .btn {
27
+ i { line-height: 16px; }
24
28
  span { margin-left: 5px; }
25
29
  }
30
+ .btn-small { padding-left: 6px; }
26
31
 
27
32
  .combinator { margin-bottom: 20px; }
28
33
 
@@ -30,4 +35,7 @@
30
35
  margin-top: 20px;
31
36
  }
32
37
 
38
+ .fields.sort {
39
+ margin-bottom: 20px;
40
+ }
33
41
  }
@@ -0,0 +1,15 @@
1
+ <div class="fields condition" data-object-name="<%= f.object_name %>">
2
+ <%= link_to_remove_fields t('ransack.remove_condition'), f, options %>
3
+
4
+ <%= f.attribute_fields do |a| %>
5
+ <span class="fields" data-object-name="<%= f.object_name %>">
6
+ <%= a.attribute_select({}, :class => 'ransack_attribute') %>
7
+ <% end %>
8
+
9
+ <%= f.predicate_select({}, :class => 'ransack_predicate') %>
10
+
11
+ <%= f.value_fields do |v| %>
12
+ <span class="fields value" data-object-name="<%= f.object_name %>">
13
+ <%= v.text_field :value, :style => "width: 200px;", :class => "ransack_query" %>
14
+ <% end %>
15
+ </div>
@@ -0,0 +1,16 @@
1
+ <div class="fields well" data-object-name="<%= f.object_name %>">
2
+ <div class="combinator">
3
+ <% key = (f.object_name =~ /[0]/) ? :group_first : :group_rest %>
4
+ <% combinator = f.combinator_select({}, :class => 'ransack_combinator') %>
5
+ <%= t("ransack.#{key}", :combinator => combinator).html_safe %>
6
+ </div>
7
+
8
+ <div class="filters">
9
+ <% f.object.build_condition unless f.object.conditions.any? %>
10
+ <%= f.condition_fields do |c| %>
11
+ <%= render 'ransack_ui/condition_fields', :f => c, :options => options %>
12
+ <% end %>
13
+
14
+ <%= link_to_add_fields t('ransack.add_condition'), f, :condition, options %>
15
+ </div>
16
+ </div>
@@ -0,0 +1,28 @@
1
+ <%= search_form_for @ransack_search, :url => (options[:url] || url_for(:action => :index)),
2
+ :html => {:method => :get, :class => "ransack_search"}, :remote => !!options[:remote] do |f| %>
3
+
4
+ <% javascript_tag do %>
5
+ if (window.Ransack == null) { window.Ransack = {}; }
6
+ Ransack.alt_predicates_i18n = #{I18n.translate(:"ransack.predicates.alt", :default => {}).to_json}
7
+ <% end %>
8
+
9
+ <div class="row">
10
+ <div class="span12 well">
11
+ <%= f.sort_fields do |s| %>
12
+ <%= render 'ransack_ui/sort_fields', :f => s %>
13
+ <% end %>
14
+
15
+ <%= f.grouping_fields do |g| %>
16
+ <%= render 'ransack_ui/grouping_fields', :f => g, :options => options %>
17
+ <% end %>
18
+
19
+ <%= link_to_add_fields t('ransack.add_group'), f, :grouping, options %>
20
+
21
+ <div class="pull-right">
22
+ <%= hidden_field_tag :distinct, '1' %>
23
+ <%= hidden_field_tag :page, '1' %>
24
+ <%= f.submit t('ransack.submit'), :class => 'btn btn-primary btn-large' %>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <div class="fields sort">
2
+ <span class="sort_by">Sort by:</span>
3
+ <%= f.sort_select %>
4
+ </div>
@@ -12,7 +12,7 @@ module RansackUI
12
12
  ActionController::Base.send :include, ControllerHelpers
13
13
  end
14
14
 
15
- initializer :assets do
15
+ config.before_configuration do
16
16
  # Add images to be precompiled
17
17
  ::Rails.application.config.assets.precompile += %w(ransack_ui/delete.png ransack_ui/calendar.png)
18
18
  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
@@ -35,10 +35,10 @@ module Ransack
35
35
  @template.select(
36
36
  @object_name, :name,
37
37
  @template.grouped_options_for_select(attribute_collection_for_bases(bases), object.name),
38
- objectify_options(options), @default_options.merge({class: 'ransack_sort'}).merge(html_options)
38
+ objectify_options(options), @default_options.merge({:class => 'ransack_sort'}).merge(html_options)
39
39
  ) + @template.collection_select(
40
40
  @object_name, :dir, [['asc', object.translate('asc')], ['desc', object.translate('desc')]], :first, :last,
41
- objectify_options(options.except(:include_blank)), @default_options.merge({class: 'ransack_sort_order'}).merge(html_options)
41
+ objectify_options(options.except(:include_blank)), @default_options.merge({:class => 'ransack_sort_order'}).merge(html_options)
42
42
  )
43
43
  else
44
44
  # searchable_attributes now returns [c, type]
@@ -50,14 +50,30 @@ module Ransack
50
50
  end
51
51
  @template.collection_select(
52
52
  @object_name, :name, collection, :first, :last,
53
- objectify_options(options), @default_options.merge({class: 'ransack_sort'}).merge(html_options)
53
+ objectify_options(options), @default_options.merge({:class => 'ransack_sort'}).merge(html_options)
54
54
  ) + @template.collection_select(
55
55
  @object_name, :dir, [['asc', object.translate('asc')], ['desc', object.translate('desc')]], :first, :last,
56
- objectify_options(options.except(:include_blank)), @default_options.merge({class: 'ransack_sort_order'}).merge(html_options)
56
+ objectify_options(options.except(:include_blank)), @default_options.merge({:class => 'ransack_sort_order'}).merge(html_options)
57
57
  )
58
58
  end
59
59
  end
60
60
 
61
+ def predicate_keys(options)
62
+ keys = options[:compounds] ? Predicate.names : Predicate.names.reject {|k| k.match(/_(any|all)$/)}
63
+ if only = options[:only]
64
+ if only.respond_to? :call
65
+ keys = keys.select {|k| only.call(k)}
66
+ else
67
+ only = Array.wrap(only).map(&:to_s)
68
+ # Create compounds hash, e.g. {"eq" => ["eq", "eq_any", "eq_all"], "blank" => ["blank"]}
69
+ key_groups = keys.inject(Hash.new([])){ |h,k| h[k.sub(/_(any|all)$/, '')] += [k]; h }
70
+ # Order compounds hash by 'only' keys
71
+ keys = only.map {|k| key_groups[k] }.flatten.compact
72
+ end
73
+ end
74
+ keys
75
+ end
76
+
61
77
  def predicate_select(options = {}, html_options = {})
62
78
  options = Ransack.options[:default_predicates] || {} if options.blank?
63
79
 
@@ -154,5 +170,6 @@ module Ransack
154
170
  nil
155
171
  end
156
172
  end
173
+
157
174
  end
158
- end
175
+ end
@@ -0,0 +1,13 @@
1
+ require 'ransack/nodes/condition'
2
+
3
+ module Ransack
4
+ module Nodes
5
+ Condition.class_eval do
6
+ attr_writer :is_default
7
+
8
+ def default?
9
+ @is_default
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ require 'ransack/nodes/grouping'
2
+
3
+ module Ransack
4
+ module Nodes
5
+ Grouping.class_eval do
6
+
7
+ def new_condition(opts = {})
8
+ attrs = opts[:attributes] || 1
9
+ vals = opts[:values] || 1
10
+ condition = Condition.new(@context)
11
+ condition.predicate_name = opts[:predicate] || 'eq'
12
+ condition.is_default = true
13
+ attrs.times { condition.build_attribute }
14
+ vals.times { condition.build_value }
15
+ condition
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module RansackUI
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
data/lib/ransack_ui.rb CHANGED
@@ -6,3 +6,5 @@ require "ransack_chronic"
6
6
  # Require ransack overrides
7
7
  require 'ransack_ui/adapters/active_record'
8
8
  Dir.glob(File.expand_path('../ransack_ui/ransack_overrides/**/*.rb', __FILE__)) {|f| require f }
9
+
10
+ require "ransack"
data/ransack_ui.gemspec CHANGED
@@ -18,5 +18,6 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_dependency 'ransack_chronic'
21
+ gem.add_dependency 'ransack_chronic', '>= 1.1.0'
22
+ gem.add_dependency 'ransack'
22
23
  end
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: 1.0.1
4
+ version: 1.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,26 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-19 00:00:00.000000000 Z
12
+ date: 2012-12-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ransack_chronic
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.1.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: ransack
16
32
  requirement: !ruby/object:Gem::Requirement
17
33
  none: false
18
34
  requirements:
@@ -48,10 +64,10 @@ files:
48
64
  - app/assets/javascripts/ransack_ui_jquery/search_form.js.coffee.erb
49
65
  - app/assets/stylesheets/ransack_ui_bootstrap/index.css
50
66
  - app/assets/stylesheets/ransack_ui_bootstrap/search.css.scss
51
- - app/views/ransack_ui/_condition_fields.html.haml
52
- - app/views/ransack_ui/_grouping_fields.html.haml
53
- - app/views/ransack_ui/_search.html.haml
54
- - app/views/ransack_ui/_sort_fields.html.haml
67
+ - app/views/ransack_ui/_condition_fields.html.erb
68
+ - app/views/ransack_ui/_grouping_fields.html.erb
69
+ - app/views/ransack_ui/_search.html.erb
70
+ - app/views/ransack_ui/_sort_fields.html.erb
55
71
  - config/locales/en.yml
56
72
  - lib/core_ext/enumerable.rb
57
73
  - lib/ransack_ui.rb
@@ -63,6 +79,8 @@ files:
63
79
  - lib/ransack_ui/ransack_overrides/configuration.rb
64
80
  - lib/ransack_ui/ransack_overrides/context.rb
65
81
  - lib/ransack_ui/ransack_overrides/helpers/form_builder.rb
82
+ - lib/ransack_ui/ransack_overrides/nodes/condition.rb
83
+ - lib/ransack_ui/ransack_overrides/nodes/grouping.rb
66
84
  - lib/ransack_ui/version.rb
67
85
  - lib/ransack_ui/view_helpers.rb
68
86
  - ransack_ui.gemspec
@@ -81,7 +99,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
99
  version: '0'
82
100
  segments:
83
101
  - 0
84
- hash: 3453459259470944049
102
+ hash: 1751889683287985587
85
103
  required_rubygems_version: !ruby/object:Gem::Requirement
86
104
  none: false
87
105
  requirements:
@@ -90,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
108
  version: '0'
91
109
  segments:
92
110
  - 0
93
- hash: 3453459259470944049
111
+ hash: 1751889683287985587
94
112
  requirements: []
95
113
  rubyforge_project:
96
114
  rubygems_version: 1.8.21
@@ -1,13 +0,0 @@
1
- .fields.condition{ "data-object-name" => f.object_name }
2
- %p
3
- = link_to_remove_fields t('ransack.remove_condition'), f, options
4
-
5
- = f.attribute_fields do |a|
6
- %span.fields{ "data-object-name" => f.object_name }
7
- = a.attribute_select({}, :class => 'ransack_attribute')
8
-
9
- = f.predicate_select({}, :class => 'ransack_predicate')
10
-
11
- = f.value_fields do |v|
12
- %span.fields.value{ 'data-object-name' => f.object_name }
13
- = v.text_field :value, :style => "width: 200px;", :class => "ransack_query"
@@ -1,13 +0,0 @@
1
- .fields.well{ 'data-object-name' => f.object_name }
2
- .combinator
3
- - key = (f.object_name =~ /[0]/) ? :group_first : :group_rest
4
- - combinator = f.combinator_select({}, :class => 'ransack_combinator')
5
- = t("ransack.#{key}", :combinator => combinator).html_safe
6
-
7
- .filters
8
- - f.object.build_condition unless f.object.conditions.any?
9
- = f.condition_fields do |c|
10
- = render 'ransack_ui/condition_fields', :f => c, :options => options
11
-
12
- %p
13
- = link_to_add_fields t('ransack.add_condition'), f, :condition, options
@@ -1,23 +0,0 @@
1
- = search_form_for @ransack_search, :url => (options[:url] || url_for(:action => :index)),
2
- :html => {:method => :get, :class => "ransack_search"}, :remote => !!options[:remote] do |f|
3
-
4
- :javascript
5
- if (window.Ransack == null) { window.Ransack = {}; }
6
- Ransack.alt_predicates_i18n = #{I18n.translate(:"ransack.predicates.alt", :default => {}).to_json}
7
-
8
- .row
9
- .span12.well
10
-
11
- = f.sort_fields do |s|
12
- = render 'ransack_ui/sort_fields', :f => s
13
-
14
- = f.grouping_fields do |g|
15
- = render 'ransack_ui/grouping_fields', :f => g, :options => options
16
-
17
- %p
18
- = link_to_add_fields t('ransack.add_group'), f, :grouping, options
19
-
20
- .pull-right
21
- = hidden_field_tag :distinct, '1'
22
- = hidden_field_tag :page, '1'
23
- = f.submit t('ransack.submit'), :class => 'btn btn-primary btn-large'
@@ -1,3 +0,0 @@
1
- .fields.sort
2
- %span.sort_by Sort by:
3
- = f.sort_select