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.
- data/.travis.yml +11 -0
- data/CHANGELOG.rdoc +10 -0
- data/README.md +36 -2
- data/Rakefile +1 -3
- data/config/ci/before-travis.sh +28 -0
- data/lib/netzke/active_record.rb +10 -8
- data/lib/netzke/active_record/attributes.rb +28 -17
- data/lib/netzke/active_record/relation_extensions.rb +3 -1
- data/lib/netzke/basepack.rb +10 -2
- data/lib/netzke/basepack/action_column.rb +6 -8
- data/lib/netzke/basepack/data_accessor.rb +11 -174
- data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +164 -0
- data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +279 -0
- data/lib/netzke/basepack/data_adapters/data_mapper_adapter.rb +264 -0
- data/lib/netzke/basepack/data_adapters/sequel_adapter.rb +260 -0
- data/lib/netzke/basepack/form_panel.rb +3 -3
- data/lib/netzke/basepack/form_panel/fields.rb +6 -10
- data/lib/netzke/basepack/form_panel/javascripts/form_panel.js +1 -0
- data/lib/netzke/basepack/form_panel/services.rb +15 -16
- data/lib/netzke/basepack/grid_panel.rb +16 -10
- data/lib/netzke/basepack/grid_panel/columns.rb +6 -7
- data/lib/netzke/basepack/grid_panel/javascripts/event_handling.js +29 -27
- data/lib/netzke/basepack/grid_panel/services.rb +13 -90
- data/lib/netzke/basepack/paging_form_panel.rb +3 -3
- data/lib/netzke/basepack/query_builder.rb +2 -0
- data/lib/netzke/basepack/query_builder/javascripts/query_builder.js +29 -19
- data/lib/netzke/basepack/search_panel.rb +6 -3
- data/lib/netzke/basepack/search_panel/javascripts/search_panel.js +2 -1
- data/lib/netzke/basepack/search_window.rb +2 -1
- data/lib/netzke/basepack/version.rb +1 -1
- data/lib/netzke/data_mapper.rb +18 -0
- data/lib/netzke/data_mapper/attributes.rb +273 -0
- data/lib/netzke/data_mapper/combobox_options.rb +11 -0
- data/lib/netzke/data_mapper/relation_extensions.rb +38 -0
- data/lib/netzke/sequel.rb +18 -0
- data/lib/netzke/sequel/attributes.rb +274 -0
- data/lib/netzke/sequel/combobox_options.rb +10 -0
- data/lib/netzke/sequel/relation_extensions.rb +40 -0
- data/netzke-basepack.gemspec +24 -13
- data/test/basepack_test_app/Gemfile +33 -8
- data/test/basepack_test_app/Gemfile.lock +98 -79
- data/test/basepack_test_app/Guardfile +46 -0
- data/test/basepack_test_app/app/components/book_grid_with_persistence.rb +3 -0
- data/test/basepack_test_app/app/components/extras/book_presentation.rb +10 -3
- data/test/basepack_test_app/app/models/address.rb +27 -1
- data/test/basepack_test_app/app/models/author.rb +28 -0
- data/test/basepack_test_app/app/models/book.rb +43 -0
- data/test/basepack_test_app/app/models/book_with_custom_primary_key.rb +22 -0
- data/test/basepack_test_app/app/models/role.rb +21 -0
- data/test/basepack_test_app/app/models/user.rb +24 -0
- data/test/basepack_test_app/config/database.yml.sample +11 -10
- data/test/basepack_test_app/config/database.yml.travis +15 -0
- data/test/basepack_test_app/config/initializers/data_mapper_logging.rb +3 -0
- data/test/basepack_test_app/config/initializers/sequel.rb +26 -0
- data/test/basepack_test_app/db/schema.rb +0 -3
- data/test/basepack_test_app/features/grid_panel.feature +28 -8
- data/test/basepack_test_app/features/grid_sorting.feature +6 -6
- data/test/basepack_test_app/features/paging_form_panel.feature +13 -13
- data/test/basepack_test_app/features/search_in_grid.feature +31 -31
- data/test/basepack_test_app/features/step_definitions/generic_steps.rb +3 -1
- data/test/basepack_test_app/features/support/env.rb +17 -4
- data/test/basepack_test_app/lib/tasks/travis.rake +7 -0
- data/test/basepack_test_app/spec/components/form_panel_spec.rb +2 -2
- data/test/basepack_test_app/spec/data_adapter/adapter_spec.rb +68 -0
- data/test/basepack_test_app/spec/{active_record → data_adapter}/attributes_spec.rb +12 -4
- data/test/basepack_test_app/spec/data_adapter/relation_extensions_spec.rb +125 -0
- data/test/basepack_test_app/spec/spec_helper.rb +9 -0
- data/test/unit/active_record_basepack_test.rb +1 -1
- data/test/unit/grid_panel_test.rb +1 -1
- metadata +26 -31
- data/app/models/netzke_field_list.rb +0 -261
- data/app/models/netzke_model_attr_list.rb +0 -21
- data/app/models/netzke_persistent_array_auto_model.rb +0 -57
- data/test/basepack_test_app/spec/active_record/relation_extensions_spec.rb +0 -44
data/.travis.yml
ADDED
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
|
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 ../..
|
data/lib/netzke/active_record.rb
CHANGED
@@ -7,12 +7,14 @@ module Netzke
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
ActiveRecord
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =
|
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 =
|
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 =
|
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|
|
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
|
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
|
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"
|
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)
|
data/lib/netzke/basepack.rb
CHANGED
@@ -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
|
-
|
8
|
-
require '
|
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
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
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]
|
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?
|
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
|