netzke-basepack 0.12.0 → 0.12.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -547
- data/Gemfile +4 -1
- data/README.md +2 -1
- data/javascripts/basepack.js +9 -2
- data/javascripts/columns.js +224 -0
- data/{lib/netzke/basepack/grid/javascripts/event_handling.js → javascripts/mixins/grid_event_handlers.js} +58 -9
- data/lib/netzke/basepack.rb +1 -3
- data/lib/netzke/basepack/columns.rb +0 -2
- data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +18 -0
- data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +26 -29
- data/lib/netzke/basepack/form.rb +1 -2
- data/lib/netzke/basepack/form/endpoints.rb +35 -0
- data/lib/netzke/basepack/form/services.rb +18 -61
- data/lib/netzke/basepack/grid.rb +6 -7
- data/lib/netzke/basepack/grid/endpoints.rb +0 -1
- data/lib/netzke/basepack/grid/javascripts/extensions.js +2 -0
- data/lib/netzke/basepack/grid/javascripts/grid.js +2 -203
- data/lib/netzke/basepack/grid/services.rb +3 -1
- data/lib/netzke/basepack/search_panel.rb +7 -5
- data/lib/netzke/basepack/search_panel/javascripts/condition_field.js +1 -2
- data/lib/netzke/basepack/tree.rb +223 -0
- data/lib/netzke/basepack/tree/javascripts/extensions.js +101 -0
- data/lib/netzke/basepack/tree/javascripts/tree.js +112 -0
- data/lib/netzke/basepack/version.rb +1 -1
- data/locales/en.yml +18 -0
- metadata +8 -3
data/Gemfile
CHANGED
@@ -7,6 +7,8 @@ gem 'sqlite3'
|
|
7
7
|
gem 'yard'
|
8
8
|
gem 'rake'
|
9
9
|
|
10
|
+
gem 'awesome_nested_set'
|
11
|
+
|
10
12
|
group :test do
|
11
13
|
gem 'rspec'
|
12
14
|
gem 'rspec-rails'
|
@@ -21,5 +23,6 @@ group :development, :test do
|
|
21
23
|
gem 'web-console', '~> 2.0'
|
22
24
|
# gem 'spring' # troubles...
|
23
25
|
gem 'pry-rails'
|
24
|
-
gem 'netzke-
|
26
|
+
gem 'netzke-core', github: 'netzke/netzke-core'
|
27
|
+
gem 'netzke-testing', github: 'netzke/netzke-testing'
|
25
28
|
end
|
data/README.md
CHANGED
@@ -14,6 +14,7 @@ A pack of pre-built [Netzke](http://netzke.org) components that can be used as b
|
|
14
14
|
Basepack includes the following components:
|
15
15
|
|
16
16
|
* [Grid](http://rdoc.info/github/netzke/netzke-basepack/Netzke/Basepack/Grid) - a grid panel with a thick bag of features
|
17
|
+
* [Tree](http://rdoc.info/github/netzke/netzke-basepack/Netzke/Basepack/Tree) - a tree panel with features similar to the Grid
|
17
18
|
* [Form](http://rdoc.info/github/netzke/netzke-basepack/Netzke/Basepack/Form) - a form panel with automatic binding of fields
|
18
19
|
* [TabPanel](http://rdoc.info/github/netzke/netzke-basepack/Netzke/Basepack/TabPanel) - a tab panel with support for lazy loading of nested components
|
19
20
|
* [Accordion](http://rdoc.info/github/netzke/netzke-basepack/Netzke/Basepack/Accordion) - an accordion panel with support for lazy loading of nested components
|
@@ -28,7 +29,7 @@ enhancing any grid with live search functionality
|
|
28
29
|
|
29
30
|
## Requirements
|
30
31
|
|
31
|
-
* Ruby >
|
32
|
+
* Ruby > 1.9.3
|
32
33
|
* Rails ~> 4.2.0
|
33
34
|
* Ext JS = 5.1.0
|
34
35
|
|
data/javascripts/basepack.js
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
Ext.ns("Netzke.
|
2
|
-
Ext.ns("Netzke.pre.Basepack");
|
1
|
+
Ext.ns("Netzke.mixins.Basepack");
|
3
2
|
Ext.ns("Ext.ux.grid");
|
4
3
|
|
5
4
|
Ext.util.Format.mask = function(v){
|
@@ -34,3 +33,11 @@ Netzke.isModelDefined = function(name) {
|
|
34
33
|
Netzke.modelName = function(name){
|
35
34
|
return "Netzke.models." + name;
|
36
35
|
};
|
36
|
+
|
37
|
+
// Fix 2-digit precision in the numeric filter
|
38
|
+
Ext.define('Ext.grid.filters.filter.Number', {
|
39
|
+
override: 'Ext.grid.filters.filter.Number',
|
40
|
+
getItemDefaults: function() {
|
41
|
+
return Ext.apply(this.itemDefaults, { decimalPrecision: 10 });
|
42
|
+
}
|
43
|
+
});
|
@@ -0,0 +1,224 @@
|
|
1
|
+
/* Shared column-related functionality, used in Tree and Grid */
|
2
|
+
Ext.define("Netzke.mixins.Basepack.Columns", {
|
3
|
+
netzkeBuildModel: function(modelClass) {
|
4
|
+
if (!Netzke.isModelDefined(this.id)) {
|
5
|
+
Ext.define(Netzke.modelName(this.id), {
|
6
|
+
extend: modelClass,
|
7
|
+
idProperty: this.pri, // Primary key
|
8
|
+
fields: this.fields
|
9
|
+
});
|
10
|
+
}
|
11
|
+
delete this.pri;
|
12
|
+
},
|
13
|
+
|
14
|
+
netzkeProcessColumns: function() {
|
15
|
+
this.fields = [];
|
16
|
+
|
17
|
+
// Run through columns and set up different configuration for each
|
18
|
+
Ext.each(this.columns, function(c, i){
|
19
|
+
|
20
|
+
this.netzkeNormalizeRenderer(c);
|
21
|
+
|
22
|
+
// Build the field configuration for this column
|
23
|
+
var fieldConfig = {name: c.name, defaultValue: c.defaultValue, allowNull: true};
|
24
|
+
|
25
|
+
if (c.name !== 'meta') fieldConfig.type = this.netzkeFieldTypeForAttrType(c.attrType); // field type (grid editors need this to function well)
|
26
|
+
|
27
|
+
if (c.attrType == 'datetime') {
|
28
|
+
fieldConfig.dateFormat = 'Y-m-d H:i:s'; // set the format in which we receive datetime from the server (so that the model can parse it)
|
29
|
+
|
30
|
+
// While for 'date' columns the renderer is set up automatically (through using column's xtype), there's no appropriate xtype for our custom datetime column.
|
31
|
+
// Thus, we need to set the renderer manually.
|
32
|
+
// NOTE: for Ext there's no distinction b/w date and datetime; date fields can include time.
|
33
|
+
if (!c.renderer) {
|
34
|
+
// format in which the data will be rendered; if c.format is nil, Ext.Date.defaultFormat extended with time will be used
|
35
|
+
c.renderer = Ext.util.Format.dateRenderer(c.format || Ext.Date.defaultFormat + " H:i:s");
|
36
|
+
}
|
37
|
+
};
|
38
|
+
|
39
|
+
if (c.attrType == 'date') {
|
40
|
+
// If no dateFormat given for date attrType, Timezone translation can subtract zone offset from 00:00:00 causing previous day.
|
41
|
+
fieldConfig.dateFormat = 'Y-m-d';
|
42
|
+
};
|
43
|
+
|
44
|
+
// because checkcolumn doesn't care about editor (not) being set, we need to explicitely set readOnly here
|
45
|
+
if (c.xtype == 'checkcolumn' && !c.editor) {
|
46
|
+
c.readOnly = true;
|
47
|
+
}
|
48
|
+
|
49
|
+
this.fields.push(fieldConfig);
|
50
|
+
|
51
|
+
// We will not use meta columns as actual columns (not even hidden) - only to create the records
|
52
|
+
if (c.meta) {
|
53
|
+
this.metaColumn = c;
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
|
57
|
+
// Set rendeder for association columns (the one displaying associations by the specified method instead of id)
|
58
|
+
if (c.assoc) {
|
59
|
+
// Editor for association column
|
60
|
+
if (c.editor) c.editor = Ext.apply({ name: c.name }, c.editor);
|
61
|
+
|
62
|
+
// Renderer for association column
|
63
|
+
this.netzkeNormalizeAssociationRenderer(c);
|
64
|
+
}
|
65
|
+
|
66
|
+
if (c.editor) {
|
67
|
+
Ext.applyIf(c.editor, {selectOnFocus: true, netzkeParent: this});
|
68
|
+
}
|
69
|
+
|
70
|
+
// Setting the default filter type
|
71
|
+
if (c.filterable != false && !c.filter) {
|
72
|
+
c.filter = {type: this.netzkeFilterTypeForAttrType(c.attrType)};
|
73
|
+
}
|
74
|
+
|
75
|
+
// setting dataIndex
|
76
|
+
c.dataIndex = c.name;
|
77
|
+
|
78
|
+
}, this);
|
79
|
+
|
80
|
+
// Now reorder columns as specified in this.columnsOrder
|
81
|
+
this.orderColumns();
|
82
|
+
},
|
83
|
+
|
84
|
+
// Build column model config with columns in the correct order; columns out of order go to the end.
|
85
|
+
orderColumns: function(){
|
86
|
+
var colModelConfig = [];
|
87
|
+
|
88
|
+
Ext.each(this.columnsOrder, function(c) {
|
89
|
+
var mainColConfig;
|
90
|
+
|
91
|
+
Ext.each(this.columns, function(oc) {
|
92
|
+
if (c.name === oc.name) {
|
93
|
+
mainColConfig = Ext.apply({}, oc);
|
94
|
+
return false;
|
95
|
+
}
|
96
|
+
});
|
97
|
+
|
98
|
+
colModelConfig.push(Ext.apply(mainColConfig, c));
|
99
|
+
}, this);
|
100
|
+
|
101
|
+
// We don't need original columns any longer
|
102
|
+
delete this.columns;
|
103
|
+
|
104
|
+
// ... instead, define own column model
|
105
|
+
this.columns = colModelConfig;
|
106
|
+
},
|
107
|
+
|
108
|
+
// Normalizes the renderer for a column.
|
109
|
+
// Renderer may be:
|
110
|
+
// 1) a string that contains the name of the function to be used as renderer.
|
111
|
+
// 2) an array, where the first element is the function name, and the rest - the arguments
|
112
|
+
// that will be passed to that function along with the value to be rendered.
|
113
|
+
// The function is searched in the following objects: 1) Ext.util.Format, 2) this.
|
114
|
+
// If not found, it is simply evaluated. Handy, when as renderer we receive an inline JS function,
|
115
|
+
// or reference to a function in some other scope.
|
116
|
+
// So, these will work:
|
117
|
+
// * "uppercase"
|
118
|
+
// * ["ellipsis", 10]
|
119
|
+
// * ["substr", 3, 5]
|
120
|
+
// * "myRenderer" (if this.myRenderer is a function)
|
121
|
+
// * ["Some.scope.Format.customRenderer", 10, 20, 30] (if Some.scope.Format.customRenderer is a function)
|
122
|
+
// * "function(v){ return 'Value: ' + v; }"
|
123
|
+
netzkeNormalizeRenderer: function(c) {
|
124
|
+
if (!c.renderer) return;
|
125
|
+
|
126
|
+
var name, args = [];
|
127
|
+
|
128
|
+
if ('string' === typeof c.renderer) {
|
129
|
+
name = c.renderer.camelize(true);
|
130
|
+
} else {
|
131
|
+
name = c.renderer[0];
|
132
|
+
args = c.renderer.slice(1);
|
133
|
+
}
|
134
|
+
|
135
|
+
// First check whether Ext.util.Format has it
|
136
|
+
if (Ext.isFunction(Ext.util.Format[name])) {
|
137
|
+
c.renderer = Ext.Function.bind(Ext.util.Format[name], this, args, 1);
|
138
|
+
} else if (Ext.isFunction(this[name])) {
|
139
|
+
// ... then if our own class has it
|
140
|
+
c.renderer = Ext.Function.bind(this[name], this, args, 1);
|
141
|
+
} else {
|
142
|
+
// ... and, as last resort, evaluate it (allows passing inline javascript function as renderer)
|
143
|
+
eval("c.renderer = " + c.renderer + ";");
|
144
|
+
}
|
145
|
+
},
|
146
|
+
|
147
|
+
/*
|
148
|
+
Set a renderer that displayes association values instead of association record ID.
|
149
|
+
The association values are passed in the meta-column under associationValues hash.
|
150
|
+
*/
|
151
|
+
netzkeNormalizeAssociationRenderer: function(c) {
|
152
|
+
var passedRenderer = c.renderer, // renderer we got from netzkeNormalizeRenderer
|
153
|
+
metaData, assocValue;
|
154
|
+
c.scope = this;
|
155
|
+
c.renderer = function(value, a, r, ri, ci, store, view){
|
156
|
+
var column = view.headerCt.items.getAt(ci),
|
157
|
+
editor = column.getEditor && column.getEditor(),
|
158
|
+
recordFromStore = editor && editor.isXType('combobox') && editor.getStore().findRecord('value', value),
|
159
|
+
renderedValue;
|
160
|
+
|
161
|
+
if (recordFromStore) {
|
162
|
+
renderedValue = recordFromStore.get('text');
|
163
|
+
} else if (metaData = r.get('meta')) {
|
164
|
+
assocValue = metaData.associationValues[c.name];
|
165
|
+
renderedValue = (assocValue == undefined) ? c.emptyText : assocValue;
|
166
|
+
} else {
|
167
|
+
renderedValue = value;
|
168
|
+
}
|
169
|
+
|
170
|
+
return passedRenderer ? passedRenderer.call(this, renderedValue) : renderedValue;
|
171
|
+
};
|
172
|
+
},
|
173
|
+
|
174
|
+
netzkeSaveColumns: function(){
|
175
|
+
var cols = [];
|
176
|
+
this.getView().getHeaderCt().items.each(function(c){
|
177
|
+
cols.push({name: c.name, width: c.width, hidden: c.hidden});
|
178
|
+
});
|
179
|
+
|
180
|
+
this.serverSaveColumns(cols);
|
181
|
+
},
|
182
|
+
|
183
|
+
// Tries editing the first editable (i.e. not hidden, not read-only) sell
|
184
|
+
netzkeTryStartEditing: function(r){
|
185
|
+
var editableIndex = 0;
|
186
|
+
Ext.each(this.initialConfig.columns, function(c){
|
187
|
+
// skip columns that cannot be edited
|
188
|
+
if (!(c.hidden == true || !c.editor || c.attrType == 'boolean')) {
|
189
|
+
return false;
|
190
|
+
}
|
191
|
+
editableIndex++;
|
192
|
+
});
|
193
|
+
|
194
|
+
if (editableIndex < this.initialConfig.columns.length) {this.getPlugin('celleditor').startEdit(r, this.columns[editableIndex]);}
|
195
|
+
},
|
196
|
+
|
197
|
+
netzkeFilterTypeForAttrType: function(attrType){
|
198
|
+
var map = {
|
199
|
+
integer : 'number',
|
200
|
+
decimal : 'number',
|
201
|
+
float : 'number',
|
202
|
+
datetime : 'date',
|
203
|
+
date : 'date',
|
204
|
+
string : 'string',
|
205
|
+
text : 'string',
|
206
|
+
'boolean' : 'boolean'
|
207
|
+
};
|
208
|
+
return map[attrType] || 'string';
|
209
|
+
},
|
210
|
+
|
211
|
+
netzkeFieldTypeForAttrType: function(attrType){
|
212
|
+
var map = {
|
213
|
+
integer : 'int',
|
214
|
+
decimal : 'float',
|
215
|
+
float : 'float',
|
216
|
+
datetime : 'date',
|
217
|
+
date : 'date',
|
218
|
+
string : 'string',
|
219
|
+
text : 'string',
|
220
|
+
'boolean' : 'boolean'
|
221
|
+
};
|
222
|
+
return map[attrType] || 'string';
|
223
|
+
}
|
224
|
+
});
|
@@ -1,6 +1,6 @@
|
|
1
|
-
{
|
1
|
+
Ext.define("Netzke.mixins.Basepack.GridEventHandlers", {
|
2
2
|
// Handler for the 'add' button
|
3
|
-
|
3
|
+
onAddRecord: function(){
|
4
4
|
if (this.enableEditInForm && !this.enableEditInline) {
|
5
5
|
this.onAddInForm();
|
6
6
|
} else {
|
@@ -18,12 +18,11 @@
|
|
18
18
|
onDel: function() {
|
19
19
|
Ext.Msg.confirm(this.i18n.confirmation, this.i18n.areYouSure, function(btn){
|
20
20
|
if (btn == 'yes') {
|
21
|
-
var
|
22
|
-
this.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
this.store.sync();
|
21
|
+
var toDelete = this.getSelectionModel().getSelection();
|
22
|
+
store = this.getStore();
|
23
|
+
store.remove(toDelete);
|
24
|
+
store.removedNodes = toDelete; // HACK
|
25
|
+
store.sync();
|
27
26
|
}
|
28
27
|
}, this);
|
29
28
|
},
|
@@ -86,5 +85,55 @@
|
|
86
85
|
if (this.searchWindow) {
|
87
86
|
this.searchWindow.destroy();
|
88
87
|
}
|
88
|
+
},
|
89
|
+
|
90
|
+
onEditInForm: function(){
|
91
|
+
var selModel = this.getSelectionModel();
|
92
|
+
if (selModel.getCount() > 1) {
|
93
|
+
var recordId = selModel.selected.first().getId();
|
94
|
+
this.netzkeLoadComponent("multi_edit_window", {
|
95
|
+
params: {record_id: recordId},
|
96
|
+
callback: function(w){
|
97
|
+
w.show();
|
98
|
+
var form = w.items.first();
|
99
|
+
form.on('apply', function(){
|
100
|
+
var ids = [];
|
101
|
+
selModel.selected.each(function(r){
|
102
|
+
ids.push(r.getId());
|
103
|
+
});
|
104
|
+
if (!form.baseParams) form.baseParams = {};
|
105
|
+
form.baseParams.ids = Ext.encode(ids);
|
106
|
+
}, this);
|
107
|
+
|
108
|
+
w.on('close', function(){
|
109
|
+
if (w.closeRes === "ok") {
|
110
|
+
this.store.load();
|
111
|
+
}
|
112
|
+
}, this);
|
113
|
+
}, scope: this});
|
114
|
+
} else {
|
115
|
+
var recordId = selModel.selected.first().getId();
|
116
|
+
this.netzkeLoadComponent("edit_window", {
|
117
|
+
clientConfig: {record_id: recordId},
|
118
|
+
callback: function(w){
|
119
|
+
w.show();
|
120
|
+
w.on('close', function(){
|
121
|
+
if (w.closeRes === "ok") {
|
122
|
+
this.store.load();
|
123
|
+
}
|
124
|
+
}, this);
|
125
|
+
}, scope: this});
|
126
|
+
}
|
127
|
+
},
|
128
|
+
|
129
|
+
onAddInForm: function(){
|
130
|
+
this.netzkeLoadComponent("add_window", {callback: function(w){
|
131
|
+
w.show();
|
132
|
+
w.on('close', function(){
|
133
|
+
if (w.closeRes === "ok") {
|
134
|
+
this.store.load();
|
135
|
+
}
|
136
|
+
}, this);
|
137
|
+
}, scope: this});
|
89
138
|
}
|
90
|
-
}
|
139
|
+
});
|
data/lib/netzke/basepack.rb
CHANGED
@@ -16,10 +16,9 @@ module Netzke
|
|
16
16
|
mattr_accessor :icons_uri
|
17
17
|
|
18
18
|
class << self
|
19
|
-
|
20
19
|
# Called from netzke-basepack.rb
|
21
20
|
def init
|
22
|
-
%w[netzkeremotecombo xdatetime basepack].each do |name|
|
21
|
+
%w[netzkeremotecombo xdatetime basepack columns mixins/grid_event_handlers].each do |name|
|
23
22
|
Netzke::Core.ext_javascripts << "#{File.dirname(__FILE__)}/../../javascripts/#{name}.js"
|
24
23
|
end
|
25
24
|
|
@@ -35,6 +34,5 @@ module Netzke
|
|
35
34
|
yield self
|
36
35
|
end
|
37
36
|
end
|
38
|
-
|
39
37
|
end
|
40
38
|
end
|
@@ -225,6 +225,24 @@ module Netzke::Basepack::DataAdapters
|
|
225
225
|
name.to_s.humanize
|
226
226
|
end
|
227
227
|
|
228
|
+
# Return root record for tree-like data
|
229
|
+
def root
|
230
|
+
model_class.root
|
231
|
+
end
|
232
|
+
|
233
|
+
def find_record_children(r)
|
234
|
+
r.children
|
235
|
+
end
|
236
|
+
|
237
|
+
def find_root_records
|
238
|
+
model_class.where(parent_id: nil)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Does record respond to given method?
|
242
|
+
def model_respond_to?(method)
|
243
|
+
@model_class.instance_methods.include?(method)
|
244
|
+
end
|
245
|
+
|
228
246
|
# -- End of overridable methods
|
229
247
|
|
230
248
|
# Abstract-adapter specifics
|
@@ -39,7 +39,9 @@ module Netzke::Basepack::DataAdapters
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def attr_type(attr_name)
|
42
|
-
|
42
|
+
method, assoc = method_and_assoc(attr_name)
|
43
|
+
klass = assoc.nil? ? @model_class : assoc.klass
|
44
|
+
klass.columns_hash[method].try(:type) || :string
|
43
45
|
end
|
44
46
|
|
45
47
|
# Implementation for {AbstractAdapter#get_records}
|
@@ -113,17 +115,17 @@ module Netzke::Basepack::DataAdapters
|
|
113
115
|
|
114
116
|
def virtual_attribute?(c)
|
115
117
|
assoc_name, asso = c[:name].split('__')
|
116
|
-
|
118
|
+
method, assoc = method_and_assoc(c[:name])
|
117
119
|
|
118
120
|
if assoc
|
119
|
-
return !assoc.klass.column_names.include?(
|
121
|
+
return !assoc.klass.column_names.include?(method)
|
120
122
|
else
|
121
123
|
return !@model_class.column_names.include?(c[:name])
|
122
124
|
end
|
123
125
|
end
|
124
126
|
|
125
127
|
def combo_data(attr, query = "")
|
126
|
-
|
128
|
+
method, assoc = method_and_assoc(attr[:name])
|
127
129
|
|
128
130
|
if assoc
|
129
131
|
# Options for an asssociation attribute
|
@@ -131,16 +133,16 @@ module Netzke::Basepack::DataAdapters
|
|
131
133
|
relation = assoc.klass.all
|
132
134
|
relation = relation.extend_with(attr[:scope]) if attr[:scope]
|
133
135
|
|
134
|
-
if assoc.klass.column_names.include?(
|
136
|
+
if assoc.klass.column_names.include?(method)
|
135
137
|
# apply query
|
136
138
|
assoc_arel_table = assoc.klass.arel_table
|
137
139
|
|
138
|
-
relation = relation.where(assoc_arel_table[
|
139
|
-
relation.to_a.map{ |r| [r.id, r.send(
|
140
|
+
relation = relation.where(assoc_arel_table[method].matches("%#{query}%")) if query.present?
|
141
|
+
relation.to_a.map{ |r| [r.id, r.send(method)] }
|
140
142
|
else
|
141
143
|
query.downcase!
|
142
144
|
# an expensive search!
|
143
|
-
relation.to_a.map{ |r| [r.id, r.send(
|
145
|
+
relation.to_a.map{ |r| [r.id, r.send(method)] }.select{ |id,value| value.to_s.downcase.include?(query) }
|
144
146
|
end
|
145
147
|
|
146
148
|
else
|
@@ -240,7 +242,7 @@ module Netzke::Basepack::DataAdapters
|
|
240
242
|
end
|
241
243
|
# the composite_primary_keys gem produces [Key1,Key2...] and [Value1,Value2...]
|
242
244
|
# on primary_key and id requests. Basepack::AttrConfig converts the keys-array to an String.
|
243
|
-
elsif
|
245
|
+
elsif primary_key.try(:to_s) == a[:name]
|
244
246
|
r.id # return 'val1,val2...' on 'key1,key2...' composite_primary_keys
|
245
247
|
end
|
246
248
|
|
@@ -296,11 +298,12 @@ module Netzke::Basepack::DataAdapters
|
|
296
298
|
end
|
297
299
|
end
|
298
300
|
|
299
|
-
#
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
301
|
+
# If association attribute is given, returns [method, association]
|
302
|
+
# Else returns [attr_name]
|
303
|
+
def method_and_assoc(attr_name)
|
304
|
+
assoc_name, method = attr_name.to_s.split('__')
|
305
|
+
assoc = @model_class.reflect_on_association(assoc_name.to_sym) if method
|
306
|
+
assoc.nil? ? [attr_name] : [method, assoc]
|
304
307
|
end
|
305
308
|
|
306
309
|
# An ActiveRecord::Relation instance encapsulating all the necessary conditions.
|
@@ -353,16 +356,10 @@ module Netzke::Basepack::DataAdapters
|
|
353
356
|
predicates = conditions.map do |q|
|
354
357
|
q = HashWithIndifferentAccess.new(q)
|
355
358
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
attr = method
|
361
|
-
arel_table = Arel::Table.new(assoc.klass.table_name.to_sym)
|
362
|
-
else
|
363
|
-
attr = assoc
|
364
|
-
arel_table = @model_class.arel_table
|
365
|
-
end
|
359
|
+
attr = q[:attr]
|
360
|
+
method, assoc = method_and_assoc(attr)
|
361
|
+
|
362
|
+
arel_table = assoc ? Arel::Table.new(assoc.klass.table_name.to_sym) : @model_class.arel_table
|
366
363
|
|
367
364
|
value = q["value"]
|
368
365
|
op = q["operator"]
|
@@ -371,15 +368,15 @@ module Netzke::Basepack::DataAdapters
|
|
371
368
|
|
372
369
|
case attr_type
|
373
370
|
when :datetime
|
374
|
-
update_predecate_for_datetime(arel_table[
|
371
|
+
update_predecate_for_datetime(arel_table[method], op, value.to_date)
|
375
372
|
when :string, :text
|
376
|
-
update_predecate_for_string(arel_table[
|
373
|
+
update_predecate_for_string(arel_table[method], op, value)
|
377
374
|
when :boolean
|
378
|
-
update_predecate_for_boolean(arel_table[
|
375
|
+
update_predecate_for_boolean(arel_table[method], op, value)
|
379
376
|
when :date
|
380
|
-
update_predecate_for_rest(arel_table[
|
377
|
+
update_predecate_for_rest(arel_table[method], op, value.to_date)
|
381
378
|
else
|
382
|
-
update_predecate_for_rest(arel_table[
|
379
|
+
update_predecate_for_rest(arel_table[method], op, value)
|
383
380
|
end
|
384
381
|
end
|
385
382
|
|