netzke-basepack 0.7.4 → 0.7.5

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.
Files changed (74) hide show
  1. data/.travis.yml +11 -0
  2. data/CHANGELOG.rdoc +10 -0
  3. data/README.md +36 -2
  4. data/Rakefile +1 -3
  5. data/config/ci/before-travis.sh +28 -0
  6. data/lib/netzke/active_record.rb +10 -8
  7. data/lib/netzke/active_record/attributes.rb +28 -17
  8. data/lib/netzke/active_record/relation_extensions.rb +3 -1
  9. data/lib/netzke/basepack.rb +10 -2
  10. data/lib/netzke/basepack/action_column.rb +6 -8
  11. data/lib/netzke/basepack/data_accessor.rb +11 -174
  12. data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +164 -0
  13. data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +279 -0
  14. data/lib/netzke/basepack/data_adapters/data_mapper_adapter.rb +264 -0
  15. data/lib/netzke/basepack/data_adapters/sequel_adapter.rb +260 -0
  16. data/lib/netzke/basepack/form_panel.rb +3 -3
  17. data/lib/netzke/basepack/form_panel/fields.rb +6 -10
  18. data/lib/netzke/basepack/form_panel/javascripts/form_panel.js +1 -0
  19. data/lib/netzke/basepack/form_panel/services.rb +15 -16
  20. data/lib/netzke/basepack/grid_panel.rb +16 -10
  21. data/lib/netzke/basepack/grid_panel/columns.rb +6 -7
  22. data/lib/netzke/basepack/grid_panel/javascripts/event_handling.js +29 -27
  23. data/lib/netzke/basepack/grid_panel/services.rb +13 -90
  24. data/lib/netzke/basepack/paging_form_panel.rb +3 -3
  25. data/lib/netzke/basepack/query_builder.rb +2 -0
  26. data/lib/netzke/basepack/query_builder/javascripts/query_builder.js +29 -19
  27. data/lib/netzke/basepack/search_panel.rb +6 -3
  28. data/lib/netzke/basepack/search_panel/javascripts/search_panel.js +2 -1
  29. data/lib/netzke/basepack/search_window.rb +2 -1
  30. data/lib/netzke/basepack/version.rb +1 -1
  31. data/lib/netzke/data_mapper.rb +18 -0
  32. data/lib/netzke/data_mapper/attributes.rb +273 -0
  33. data/lib/netzke/data_mapper/combobox_options.rb +11 -0
  34. data/lib/netzke/data_mapper/relation_extensions.rb +38 -0
  35. data/lib/netzke/sequel.rb +18 -0
  36. data/lib/netzke/sequel/attributes.rb +274 -0
  37. data/lib/netzke/sequel/combobox_options.rb +10 -0
  38. data/lib/netzke/sequel/relation_extensions.rb +40 -0
  39. data/netzke-basepack.gemspec +24 -13
  40. data/test/basepack_test_app/Gemfile +33 -8
  41. data/test/basepack_test_app/Gemfile.lock +98 -79
  42. data/test/basepack_test_app/Guardfile +46 -0
  43. data/test/basepack_test_app/app/components/book_grid_with_persistence.rb +3 -0
  44. data/test/basepack_test_app/app/components/extras/book_presentation.rb +10 -3
  45. data/test/basepack_test_app/app/models/address.rb +27 -1
  46. data/test/basepack_test_app/app/models/author.rb +28 -0
  47. data/test/basepack_test_app/app/models/book.rb +43 -0
  48. data/test/basepack_test_app/app/models/book_with_custom_primary_key.rb +22 -0
  49. data/test/basepack_test_app/app/models/role.rb +21 -0
  50. data/test/basepack_test_app/app/models/user.rb +24 -0
  51. data/test/basepack_test_app/config/database.yml.sample +11 -10
  52. data/test/basepack_test_app/config/database.yml.travis +15 -0
  53. data/test/basepack_test_app/config/initializers/data_mapper_logging.rb +3 -0
  54. data/test/basepack_test_app/config/initializers/sequel.rb +26 -0
  55. data/test/basepack_test_app/db/schema.rb +0 -3
  56. data/test/basepack_test_app/features/grid_panel.feature +28 -8
  57. data/test/basepack_test_app/features/grid_sorting.feature +6 -6
  58. data/test/basepack_test_app/features/paging_form_panel.feature +13 -13
  59. data/test/basepack_test_app/features/search_in_grid.feature +31 -31
  60. data/test/basepack_test_app/features/step_definitions/generic_steps.rb +3 -1
  61. data/test/basepack_test_app/features/support/env.rb +17 -4
  62. data/test/basepack_test_app/lib/tasks/travis.rake +7 -0
  63. data/test/basepack_test_app/spec/components/form_panel_spec.rb +2 -2
  64. data/test/basepack_test_app/spec/data_adapter/adapter_spec.rb +68 -0
  65. data/test/basepack_test_app/spec/{active_record → data_adapter}/attributes_spec.rb +12 -4
  66. data/test/basepack_test_app/spec/data_adapter/relation_extensions_spec.rb +125 -0
  67. data/test/basepack_test_app/spec/spec_helper.rb +9 -0
  68. data/test/unit/active_record_basepack_test.rb +1 -1
  69. data/test/unit/grid_panel_test.rb +1 -1
  70. metadata +26 -31
  71. data/app/models/netzke_field_list.rb +0 -261
  72. data/app/models/netzke_model_attr_list.rb +0 -21
  73. data/app/models/netzke_persistent_array_auto_model.rb +0 -57
  74. data/test/basepack_test_app/spec/active_record/relation_extensions_spec.rb +0 -44
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ rvm:
2
+ - 1.9.2
3
+
4
+ env:
5
+ - ORM=ar
6
+ - ORM=dm
7
+ - ORM=sq
8
+
9
+ bundler_args: "--without development production profiling"
10
+ before_script: "./config/ci/before-travis.sh"
11
+ script: "cd test/basepack_test_app ; bundle exec rake travis"
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,13 @@
1
+ = 0.7.5 - ?
2
+ * improvements
3
+ * data-related operations in grids and forms are moved to data adapters; implemented (partial) support for DataMapper and Sequel (see updated README)
4
+ * afterApply event in forms and grids (pschyska)
5
+ * apply event fired before apply button is processed in FormPanel (pschyska)
6
+
7
+ * bug fix
8
+ * advanced search panel works again (pididi)
9
+ * fixed a problem with session and GridPanel
10
+
1
11
  = 0.7.4 - 2012-03-05
2
12
  * bug fix
3
13
  * :enable_pagination is now respected in GridPanel
data/README.md CHANGED
@@ -5,7 +5,7 @@ A pack of pre-built [Netzke](http://netzke.org) components - such as grid, form,
5
5
  ## Requirements
6
6
 
7
7
  * Ruby 1.9.2 (1.8.7 may work, too)
8
- * Rails >= 3.0.0
8
+ * Rails ~> 3.1.0
9
9
  * Ext JS = 4.0.2a
10
10
 
11
11
  ## Installation
@@ -36,6 +36,40 @@ After starting up the test app, you can see the list of functional test componen
36
36
 
37
37
  http://localhost:3000/
38
38
 
39
+ ## Note on testing with DataMapper/Sequel Support
40
+ To install the test app with DataMapper or Sequel, put ORM=dm or ORM=sq
41
+ into your environment.
42
+ For example to set-up DataMapper support run
43
+
44
+ # in test/basepack_test_app
45
+ ORM=dm bundle install
46
+
47
+ To run the test app in DataMapper-Mode (will use DataMapper models instead of ActiveRecord models)
48
+
49
+ # in test/basepack_test_app
50
+ ORM=dm rails s
51
+
52
+ To run the test suite
53
+
54
+ # in test/basepack_test_app
55
+ ORM=dm bundle exec rake
56
+
57
+ etc.
58
+
59
+ NOTE: netzke-basepack is not dependant on neither DataMapper nor Sequel. It will pick the right DataAdapter for your models automatically.
60
+ ActiveRecord is still included in Gemfile of the test app, as netzke-persistance is used which uses ActiveRecord.
61
+ If you don't use netzke-persistence, then you don't need to include ActiveRecord.
62
+
63
+ ## DataMapper support
64
+ DataMapper support is *incomplete*, as I didn't find a good way to sort by an association's column when the association needs a LEFT OUTER JOIN (i.e. nullable foreign key in many_to_one).
65
+
66
+ ## Sequel support
67
+
68
+ CAVEATS:
69
+ - you can't use polymorphic associations for the time being, as the sequel_polymorphic plugin is not supported by netzke-basepack
70
+ - SearchPanel is broken atm. When it's fixed, Sequel support for
71
+ SearchPanel triggered queries should be implemented.
72
+
39
73
  ## Icons support
40
74
  Netzke Basepack can make use of FamFamFam Silk icon set (http://www.famfamfam.com/archive/silk-icons-thats-your-lot/). To enable this, download the icons and put the "icons" folder into your app's public/images folder. Then restart your application.
41
75
 
@@ -57,4 +91,4 @@ Many (if a bit outdated) tutorials: http://blog.writelesscode.com
57
91
 
58
92
  ---
59
93
  Copyright (c) 2008-2011 NomadCoder, released under the MIT license
60
- Note, that Ext JS itself is licensed [differently](http://www.sencha.com/products/extjs/license/)
94
+ Note, that Ext JS itself is licensed [differently](http://www.sencha.com/products/extjs/license/)
data/Rakefile CHANGED
@@ -10,8 +10,6 @@ begin
10
10
  gemspec.homepage = "http://netzke.org"
11
11
  gemspec.authors = ["Sergei Kozlov"]
12
12
  gemspec.add_dependency("netzke-core", "~>0.7.4")
13
- gemspec.add_dependency("will_paginate", "~>3.0.0")
14
- gemspec.add_dependency("acts_as_list", "~>0.1.4")
15
13
  gemspec.post_install_message = <<-MESSAGE
16
14
 
17
15
  ========================================================================
@@ -60,4 +58,4 @@ namespace :rdoc do
60
58
  task :publish => :rdoc do
61
59
  `scp -r rdoc/* fl:www/api.netzke.org/basepack`
62
60
  end
63
- end
61
+ end
@@ -0,0 +1,28 @@
1
+ # Start xvfb in preparation for cucumber
2
+ sh -e /etc/init.d/xvfb start
3
+
4
+ # fetch extjs
5
+ wget http://extjs.cachefly.net/ext-4.0.2a-gpl.zip
6
+ unzip -q -d test/basepack_test_app/public/ -n ext-4.0.2a-gpl.zip
7
+ mv test/basepack_test_app/public/ext-4.0.2a test/basepack_test_app/public/extjs
8
+
9
+ # cp db configuration
10
+ cp test/basepack_test_app/config/database.yml.travis test/basepack_test_app/config/database.yml
11
+
12
+ # create mysql database
13
+ mysql -e 'create database nbt_test;'
14
+
15
+ # clone netzke-core and netzke-persistence gems into test project
16
+ mkdir -p test/basepack_test_app/vendor/gems
17
+ cd test/basepack_test_app/vendor/gems
18
+ git clone git://github.com/skozlov/netzke-core.git
19
+ cd netzke-core
20
+ git checkout tags/v0.7.4
21
+ cd ..
22
+ git clone git://github.com/skozlov/netzke-persistence.git
23
+ cd netzke-persistence
24
+ git checkout tags/v0.1.0
25
+ cd ../../..
26
+ bundle install
27
+ bundle exec rake db:migrate RAILS_ENV=test
28
+ cd ../..
@@ -7,12 +7,14 @@ module Netzke
7
7
  end
8
8
  end
9
9
 
10
- # Extend ActiveRecord
11
- ActiveRecord::Base.class_eval do
12
- include ::Netzke::ActiveRecord::Attributes
13
- include ::Netzke::ActiveRecord::ComboboxOptions
14
- end
10
+ if defined? ActiveRecord
11
+ # Extend ActiveRecord
12
+ ActiveRecord::Base.class_eval do
13
+ include ::Netzke::ActiveRecord::Attributes
14
+ include ::Netzke::ActiveRecord::ComboboxOptions
15
+ end
15
16
 
16
- ActiveRecord::Relation.class_eval do
17
- include ::Netzke::ActiveRecord::RelationExtensions
18
- end
17
+ ActiveRecord::Relation.class_eval do
18
+ include ::Netzke::ActiveRecord::RelationExtensions
19
+ end
20
+ end
@@ -3,14 +3,28 @@ module Netzke
3
3
  module Attributes
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ included do
7
+ class_attribute :netzke_declared_attr
8
+ self.netzke_declared_attr = []
9
+
10
+ class_attribute :netzke_excluded_attr
11
+ self.netzke_excluded_attr = []
12
+
13
+ class_attribute :netzke_exposed_attr
14
+ end
15
+
6
16
  module ClassMethods
17
+ def data_adapter
18
+ @data_adapter = Netzke::Basepack::DataAdapters::AbstractAdapter.adapter_class(self).new(self)
19
+ end
20
+
7
21
  # Define or configure an attribute.
8
22
  # Example:
9
23
  # netzke_attribute :recent, :type => :boolean, :read_only => true
10
24
  def netzke_attribute(name, options = {})
11
25
  name = name.to_s
12
26
  options[:attr_type] = options.delete(:type) || options.delete(:attr_type) || :string
13
- declared_attrs = read_inheritable_attribute(:netzke_declared_attributes) || []
27
+ declared_attrs = self.netzke_declared_attr.dup
14
28
  # if the attr was declared already, simply merge it with the new options
15
29
  existing = declared_attrs.detect{ |va| va[:name] == name }
16
30
  if existing
@@ -24,7 +38,7 @@ module Netzke
24
38
  declared_attrs << {:name => name}.merge(options)
25
39
  end
26
40
  end
27
- write_inheritable_attribute(:netzke_declared_attributes, declared_attrs)
41
+ self.netzke_declared_attr = declared_attrs
28
42
  end
29
43
 
30
44
  # Exclude attributes from being picked up by grids and forms.
@@ -32,7 +46,7 @@ module Netzke
32
46
  # Example:
33
47
  # netzke_expose_attributes :created_at, :updated_at, :crypted_password
34
48
  def netzke_exclude_attributes(*args)
35
- write_inheritable_attribute(:netzke_excluded_attributes, args.map(&:to_s))
49
+ self.netzke_excluded_attr = args.map(&:to_s)
36
50
  end
37
51
 
38
52
  # Explicitly expose attributes that should be picked up by grids and forms.
@@ -41,7 +55,7 @@ module Netzke
41
55
  # Example:
42
56
  # netzke_expose_attributes :name, :role__name
43
57
  def netzke_expose_attributes(*args)
44
- write_inheritable_attribute(:netzke_exposed_attributes, args.map(&:to_s))
58
+ self.netzke_exposed_attr = args.map(&:to_s)
45
59
  end
46
60
 
47
61
  # Returns the attributes that will be picked up by grids and forms.
@@ -55,7 +69,7 @@ module Netzke
55
69
  end
56
70
 
57
71
  def netzke_exposed_attributes
58
- exposed = read_inheritable_attribute(:netzke_exposed_attributes)
72
+ exposed = self.netzke_exposed_attr
59
73
  if exposed && !exposed.include?(self.primary_key)
60
74
  # automatically declare primary key as a netzke attribute
61
75
  netzke_attribute(self.primary_key)
@@ -65,17 +79,10 @@ module Netzke
65
79
  end
66
80
 
67
81
  private
68
- def netzke_declared_attributes
69
- read_inheritable_attribute(:netzke_declared_attributes) || []
70
- end
71
-
72
- def netzke_excluded_attributes
73
- read_inheritable_attribute(:netzke_excluded_attributes) || []
74
- end
75
82
 
76
83
  def netzke_attrs_in_forced_order(attrs)
77
84
  attrs.collect do |attr_name|
78
- declared = netzke_declared_attributes.detect { |va| va[:name] == attr_name } || {}
85
+ declared = self.netzke_declared_attr.detect { |va| va[:name] == attr_name } || {}
79
86
  in_columns_hash = columns_hash[attr_name] && {:name => attr_name, :attr_type => columns_hash[attr_name].type, :default_value => columns_hash[attr_name].default} || {} # {:virtual => true} # if nothing found in columns, mark it as "virtual" or not?
80
87
  if in_columns_hash.empty?
81
88
  # If not among the model columns, it's either virtual, or an association
@@ -98,7 +105,7 @@ module Netzke
98
105
  # role_id => role__name
99
106
  def netzke_attrs_in_natural_order
100
107
  (
101
- declared_attrs = netzke_declared_attributes
108
+ declared_attrs = self.netzke_declared_attr
102
109
 
103
110
  column_names.map do |name|
104
111
  c = {:name => name, :attr_type => columns_hash[name].type}
@@ -124,7 +131,7 @@ module Netzke
124
131
  c
125
132
  end +
126
133
  declared_attrs
127
- ).reject { |attr| netzke_excluded_attributes.include?(attr[:name]) }
134
+ ).reject { |attr| self.netzke_excluded_attr.include?(attr[:name]) }
128
135
  end
129
136
 
130
137
  # Returns foreign key for given association (Rails >= 3.0)
@@ -139,7 +146,7 @@ module Netzke
139
146
  end
140
147
 
141
148
  # Transforms a record to array of values according to the passed attributes
142
- def to_array(attributes)
149
+ def netzke_array(attributes = self.class.netzke_attributes)
143
150
  res = []
144
151
  for a in attributes
145
152
  next if a[:included] == false
@@ -148,8 +155,12 @@ module Netzke
148
155
  res
149
156
  end
150
157
 
158
+ def netzke_json
159
+ netzke_hash.to_nifty_json
160
+ end
161
+
151
162
  # Accepts both hash and array of attributes
152
- def to_hash(attributes)
163
+ def netzke_hash(attributes = self.class.netzke_attributes)
153
164
  res = {}
154
165
  for a in (attributes.is_a?(Hash) ? attributes.values : attributes)
155
166
  next if a[:included] == false
@@ -11,7 +11,9 @@ module Netzke
11
11
  params.empty? ? self.where(scope) : self.where([scope, *params])
12
12
  when "Array"
13
13
  self.extend_with(*scope)
14
- when "Hash" # conditions hash
14
+ when "Hash" # conditions hash
15
+ self.where(scope)
16
+ when "ActiveSupport::HashWithIndifferentAccess" # conditions hash
15
17
  self.where(scope)
16
18
  when "Proc" # receives a relation, must return a relation
17
19
  scope.call(self)
@@ -3,9 +3,17 @@ require 'netzke/basepack/version'
3
3
  if defined? ActiveRecord
4
4
  require 'netzke/active_record'
5
5
  end
6
+ if defined? DataMapper
7
+ require 'netzke/data_mapper'
8
+ end
9
+ if defined? Sequel
10
+ require 'netzke/sequel'
11
+ end
6
12
 
7
- # will_paginate supports more than just ActiveRecord
8
- require 'will_paginate'
13
+ require 'netzke/basepack/data_adapters/abstract_adapter'
14
+ require 'netzke/basepack/data_adapters/active_record_adapter' if defined? ActiveRecord
15
+ require 'netzke/basepack/data_adapters/data_mapper_adapter' if defined? DataMapper
16
+ require 'netzke/basepack/data_adapters/sequel_adapter' if defined? Sequel
9
17
 
10
18
  module Netzke
11
19
  module Basepack
@@ -4,20 +4,18 @@ module Netzke
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do |base|
7
+
8
+ # Returns registered actions
9
+ class_attribute :registered_column_actions
10
+ self.registered_column_actions = []
11
+
7
12
  js_include :action_column
8
13
  end
9
14
 
10
15
  module ClassMethods
11
16
  # Register an action
12
17
  def register_column_action(name)
13
- current_column_actions = read_inheritable_attribute(:column_actions) || []
14
- current_column_actions << name
15
- write_inheritable_attribute(:column_actions, current_column_actions.uniq)
16
- end
17
-
18
- # Returns registered actions
19
- def registered_column_actions
20
- read_inheritable_attribute(:column_actions) || []
18
+ self.registered_column_actions |= [name]
21
19
  end
22
20
 
23
21
  # Use this method to define column actions in your component, e.g.:
@@ -3,48 +3,11 @@ module Netzke
3
3
  # This module is included into such data-driven components as GridPanel, FormPanel, PagingFormPanel, etc.
4
4
  module DataAccessor
5
5
 
6
- # Returns options for comboboxes in grids/forms
7
- def combobox_options_for_column(column, method_options = {})
8
- query = method_options[:query]
9
-
10
- # First, check if we have options for this column defined in persistent storage
11
- options = column[:combobox_options] && column[:combobox_options].split("\n")
12
- if options
13
- query ? options.select{ |o| o.index(/^#{query}/) }.map{ |el| [el] } : options
14
- else
15
- assoc, assoc_method = assoc_and_assoc_method_for_attr(column)
16
-
17
- if assoc
18
- # Options for an asssociation attribute
19
-
20
- relation = assoc.klass.scoped
21
6
 
22
- relation = relation.extend_with(method_options[:scope]) if method_options[:scope]
23
7
 
24
- if assoc.klass.column_names.include?(assoc_method)
25
- # apply query
26
- relation = relation.where(["#{assoc_method} like ?", "%#{query}%"]) if query.present?
27
- relation.all.map{ |r| [r.id, r.send(assoc_method)] }
28
- else
29
- relation.all.map{ |r| [r.id, r.send(assoc_method)] }.select{ |id,value| value =~ /^#{query}/ }
30
- end
31
-
32
- else
33
- # Options for a non-association attribute
34
- res=data_class.netzke_combo_options_for(column[:name], method_options)
35
-
36
- # ensure it is an array-in-array, as Ext will fail otherwise
37
- raise RuntimeError, "netzke_combo_options_for should return an Array" unless res.kind_of? Array
38
- return [[]] if res.empty?
39
-
40
- unless res.first.kind_of? Array
41
- res=res.map do |v|
42
- [v]
43
- end
44
- end
45
- return res
46
- end
47
- end
8
+ # Returns options for comboboxes in grids/forms
9
+ def combobox_options_for_column(column, method_options = {})
10
+ data_adapter.combobox_options_for_column column, method_options
48
11
  end
49
12
 
50
13
  # Normalize array of attributes
@@ -61,156 +24,30 @@ module Netzke
61
24
  a.is_a?(Symbol) || a.is_a?(String) ? {:name => a.to_s} : a.merge(:name => a[:name].to_s)
62
25
  end
63
26
 
64
- # Returns association and association method for a column
65
- def assoc_and_assoc_method_for_attr(c)
66
- assoc_name, assoc_method = c[:name].split('__')
67
- assoc = data_class.reflect_on_association(assoc_name.to_sym) if assoc_method
68
- [assoc, assoc_method]
69
- end
70
-
71
27
  def association_attr?(name)
72
28
  !!name.to_s.index("__")
73
29
  end
74
30
 
75
31
  # Model class
76
32
  def data_class
77
- @data_class ||= config[:model] && config[:model].constantize
33
+ @data_class ||= config[:model].is_a?(String) ? config[:model].constantize : config[:model]
34
+ end
35
+
36
+ # Data adapter responsible for all DB-related operations
37
+ def data_adapter
38
+ @data_adapter ||= Netzke::Basepack::DataAdapters::AbstractAdapter.adapter_class(data_class).new(data_class)
78
39
  end
79
40
 
80
41
  # whether a column is bound to the primary_key
81
42
  def primary_key_attr?(a)
82
- data_class && a[:name].to_s == data_class.primary_key
43
+ data_class && a[:name].to_s == data_class.primary_key.to_s
83
44
  end
84
45
 
85
46
  # Mark an attribute as "virtual" by default, when it doesn't reflect a model column, or a model column of an association
86
47
  def set_default_virtual(c)
87
- if c[:virtual].nil? # sometimes at maybe handy to mark a column as non-virtual forcefully
88
- assoc, assoc_method = assoc_and_assoc_method_for_attr(c)
89
- if assoc
90
- c[:virtual] = true if !assoc.klass.column_names.map(&:to_sym).include?(assoc_method.to_sym)
91
- else
92
- c[:virtual] = true if !data_class.column_names.map(&:to_sym).include?(c[:name].to_sym)
93
- end
94
- end
95
- end
96
-
97
- # An ActiveRecord::Relation instance encapsulating all the necessary conditions.
98
- def get_relation(params = {})
99
- @arel = data_class.arel_table
100
-
101
- relation = data_class.scoped
102
-
103
- relation = apply_column_filters(relation, params[:filter]) if params[:filter]
104
-
105
- if params[:extra_conditions]
106
- extra_conditions = normalize_extra_conditions(ActiveSupport::JSON.decode(params[:extra_conditions]))
107
- relation = relation.extend_with_netzke_conditions(extra_conditions) if params[:extra_conditions]
108
- end
109
-
110
- query = params[:query] && ActiveSupport::JSON.decode(params[:query])
111
-
112
- if query.present?
113
- # array of arrays of conditions that should be joined by OR
114
- and_predicates = query.map do |conditions|
115
- predicates_for_and_conditions(conditions)
116
- end
117
-
118
- # join them by OR
119
- predicates = and_predicates[1..-1].inject(and_predicates.first){ |r,c| r.or(c) }
120
- end
121
-
122
- relation = relation.where(predicates)
123
-
124
- relation = relation.extend_with(config[:scope]) if config[:scope]
125
-
126
- relation
48
+ c[:virtual] = data_adapter.column_virtual?(c) if c[:virtual].nil?
127
49
  end
128
50
 
129
- # Parses and applies grid column filters, calling consequent "where" methods on the passed relation.
130
- # Returns the updated relation.
131
- #
132
- # Example column grid data:
133
- #
134
- # {"0" => {
135
- # "data" => {
136
- # "type" => "numeric",
137
- # "comparison" => "gt",
138
- # "value" => 10 },
139
- # "field" => "id"
140
- # },
141
- # "1" => {
142
- # "data" => {
143
- # "type" => "string",
144
- # "value" => "pizza"
145
- # },
146
- # "field" => "food_name"
147
- # }}
148
- #
149
- # This will result in:
150
- #
151
- # relation.where(["id > ?", 10]).where(["food_name like ?", "%pizza%"])
152
- def apply_column_filters(relation, column_filter)
153
- res = relation
154
- operator_map = {"lt" => "<", "gt" => ">", "eq" => "="}
155
-
156
- table_name = data_class.table_name
157
-
158
- # these are still JSON-encoded due to the migration to Ext.direct
159
- column_filter=JSON.parse(column_filter)
160
- column_filter.each do |v|
161
- assoc, method = v["field"].split('__')
162
- if method
163
- assoc = data_class.reflect_on_association(assoc.to_sym)
164
- field = [assoc.klass.table_name, method].join('.')
165
- else
166
- field = [table_name, assoc].join('.')
167
- end
168
-
169
- value = v["value"]
170
-
171
- op = operator_map[v['comparison']]
172
-
173
- case v["type"]
174
- when "string"
175
- res = res.where(["#{field} like ?", "%#{value}%"])
176
- when "date"
177
- # convert value to the DB date
178
- value.match /(\d\d)\/(\d\d)\/(\d\d\d\d)/
179
- res = res.where("#{field} #{op} ?", "#{$3}-#{$1}-#{$2}")
180
- when "numeric"
181
- res = res.where(["#{field} #{op} ?", value])
182
- else
183
- res = res.where(["#{field} = ?", value])
184
- end
185
- end
186
-
187
- res
188
- end
189
-
190
-
191
- protected
192
-
193
- def predicates_for_and_conditions(conditions)
194
- return nil if conditions.empty?
195
-
196
- predicates = conditions.map do |q|
197
- value = q["value"]
198
- case q["operator"]
199
- when "contains"
200
- @arel[q["attr"]].matches "%#{value}%"
201
- else
202
- if value == false || value == true
203
- @arel[q["attr"]].eq(value ? 1 : 0)
204
- else
205
- @arel[q["attr"]].send(q["operator"], value)
206
- end
207
- end
208
- end
209
-
210
- # join them by AND
211
- predicates[1..-1].inject(predicates.first){ |r,p| r.and(p) }
212
- end
213
-
214
51
  end
215
52
  end
216
53
  end