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
@@ -0,0 +1,260 @@
|
|
1
|
+
module Netzke::Basepack::DataAdapters
|
2
|
+
class SequelAdapter < AbstractAdapter
|
3
|
+
def self.for_class?(model_class)
|
4
|
+
model_class <= Sequel::Model
|
5
|
+
end
|
6
|
+
|
7
|
+
def get_records(params, columns=[])
|
8
|
+
get_dataset(params, columns).all
|
9
|
+
end
|
10
|
+
|
11
|
+
def count_records(params, columns=[])
|
12
|
+
# dont pass columns, JOINs will be done as necessary for filters
|
13
|
+
get_dataset(params, [], true).count
|
14
|
+
end
|
15
|
+
|
16
|
+
def map_type type
|
17
|
+
type
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_assoc_property_type assoc_name, prop_name
|
21
|
+
db_schema=class_for(assoc_name.to_sym).db_schema
|
22
|
+
# return nil if prop_name not present in db schema (virtual column)
|
23
|
+
db_schema[prop_name.to_sym] ? db_schema[prop_name.to_sym][:type] : nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# like get_assoc_property_type but for non-association columns
|
27
|
+
def get_property_type column
|
28
|
+
column[:type]
|
29
|
+
end
|
30
|
+
|
31
|
+
def column_virtual? c
|
32
|
+
assoc, method = c[:name].split '__'
|
33
|
+
if method
|
34
|
+
!class_for(assoc.to_sym).columns.include? method.to_sym
|
35
|
+
else
|
36
|
+
!@model_class.columns.include? assoc.to_sym
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns options for comboboxes in grids/forms
|
41
|
+
def combobox_options_for_column(column, method_options = {})
|
42
|
+
query = method_options[:query]
|
43
|
+
|
44
|
+
# First, check if we have options for this column defined in persistent storage
|
45
|
+
options = column[:combobox_options] && column[:combobox_options].split("\n")
|
46
|
+
if options
|
47
|
+
query ? options.select{ |o| o.index(/^#{query}/) }.map{ |el| [el] } : options
|
48
|
+
else
|
49
|
+
assoc_name, assoc_method = column[:name].split '__'
|
50
|
+
|
51
|
+
if assoc_name
|
52
|
+
# Options for an asssociation attribute
|
53
|
+
dataset = class_for(assoc_name)
|
54
|
+
|
55
|
+
dataset = dataset.extend_with(method_options[:scope]) if method_options[:scope]
|
56
|
+
|
57
|
+
if class_for(assoc_name).column_names.include?(assoc_method)
|
58
|
+
# apply query
|
59
|
+
dataset = dataset.where(assoc_method.to_sym.like("%#{query}%")) if query.present?
|
60
|
+
dataset.all.map{ |r| [r.id, r.send(assoc_method)] }
|
61
|
+
else
|
62
|
+
dataset.all.map{ |r| [r.id, r.send(assoc_method)] }.select{ |id,value| value =~ /^#{query}/ }
|
63
|
+
end
|
64
|
+
else
|
65
|
+
# Options for a non-association attribute
|
66
|
+
res=@model_class.netzke_combo_options_for(column[:name], method_options)
|
67
|
+
|
68
|
+
# ensure it is an array-in-array, as Ext will fail otherwise
|
69
|
+
raise RuntimeError, "netzke_combo_options_for should return an Array" unless res.kind_of? Array
|
70
|
+
return [[]] if res.empty?
|
71
|
+
|
72
|
+
unless res.first.kind_of? Array
|
73
|
+
res=res.map do |v|
|
74
|
+
[v]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
return res
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def foreign_key_for assoc_name
|
83
|
+
@model_class.association_reflection(assoc_name.to_sym)[:key].to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns the model class for an association
|
87
|
+
def class_for assoc_name
|
88
|
+
@model_class.association_reflection(assoc_name.to_sym)[:class_name].constantize
|
89
|
+
end
|
90
|
+
|
91
|
+
def destroy(ids)
|
92
|
+
@model_class.where(:id => ids).destroy
|
93
|
+
end
|
94
|
+
|
95
|
+
def find_record(id)
|
96
|
+
@model_class[id]
|
97
|
+
end
|
98
|
+
|
99
|
+
# Build a hash of foreign keys and the associated model
|
100
|
+
def hash_fk_model
|
101
|
+
@model_class.all_association_reflections.inject({}) do |res, assoc|
|
102
|
+
res[assoc[:key]] = assoc[:class_name].constantize.model_name.underscore.to_sym
|
103
|
+
res
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# TODO: is this possible with Sequel?
|
108
|
+
def move_records(params)
|
109
|
+
end
|
110
|
+
|
111
|
+
# give the data adapter the opportunity the set special options for
|
112
|
+
# saving
|
113
|
+
def save_record(record)
|
114
|
+
# don't raise an error on saving. basepack will evaluate record.errors
|
115
|
+
# to get validation errors
|
116
|
+
record.raise_on_save_failure = false
|
117
|
+
record.save
|
118
|
+
end
|
119
|
+
|
120
|
+
# give the data adapter the opporunity to process error messages
|
121
|
+
# must return an raay of the form ["Title can't be blank", "Foo can't be blank"]
|
122
|
+
def errors_array(record)
|
123
|
+
record.errors.to_a.inject([]) do |errors, error|
|
124
|
+
field, message = error
|
125
|
+
errors << "#{record.class.human_attribute_name(field)} #{message.join ', '}"
|
126
|
+
errors
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Needed for seed and tests
|
131
|
+
def last
|
132
|
+
@model_class.last
|
133
|
+
end
|
134
|
+
|
135
|
+
# Needed for seed and tests
|
136
|
+
def destroy_all
|
137
|
+
@model_class.destroy
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
def get_dataset params, columns, for_count=false
|
142
|
+
dataset = @model_class
|
143
|
+
|
144
|
+
graphed=[]
|
145
|
+
|
146
|
+
# Parses and applies grid column filters
|
147
|
+
#
|
148
|
+
# Example column grid data:
|
149
|
+
#
|
150
|
+
# {"0" => {
|
151
|
+
# "data" => {
|
152
|
+
# "type" => "numeric",
|
153
|
+
# "comparison" => "gt",
|
154
|
+
# "value" => 10 },
|
155
|
+
# "field" => "id"
|
156
|
+
# },
|
157
|
+
# "1" => {
|
158
|
+
# "data" => {
|
159
|
+
# "type" => "string",
|
160
|
+
# "value" => "pizza"
|
161
|
+
# },
|
162
|
+
# "field" => "food_name"
|
163
|
+
# }}
|
164
|
+
#
|
165
|
+
|
166
|
+
if params[:filter]
|
167
|
+
# these are still JSON-encoded due to the migration to Ext.direct
|
168
|
+
column_filter=JSON.parse(params[:filter])
|
169
|
+
|
170
|
+
column_filter.each do |v|
|
171
|
+
field = v["field"]
|
172
|
+
assoc, method = field.split('__')
|
173
|
+
if method
|
174
|
+
# when filtering on association's columns, we need to graph for LEFT OUTER JOIN
|
175
|
+
dataset = dataset.eager_graph assoc.to_sym unless graphed.include? assoc.to_sym
|
176
|
+
graphed << assoc.to_sym
|
177
|
+
end
|
178
|
+
|
179
|
+
value = v["value"]
|
180
|
+
type = v["type"]
|
181
|
+
op = v["comparison"]
|
182
|
+
|
183
|
+
if type == "string"
|
184
|
+
# strings are always LIKEd (case-insensitive)
|
185
|
+
dataset = dataset.filter field.to_sym.ilike("%#{value}%")
|
186
|
+
else
|
187
|
+
if type == "date"
|
188
|
+
# convert value to the DB date
|
189
|
+
value.match /(\d\d)\/(\d\d)\/(\d\d\d\d)/
|
190
|
+
value = "#{$3}-#{$1}-#{$2}"
|
191
|
+
end
|
192
|
+
# if it's NOT an association column, we need to qualify column name with model's table_name
|
193
|
+
qualified_column_name = method ? field.to_sym : field.to_sym.qualify(@model_class.table_name)
|
194
|
+
case op
|
195
|
+
when 'lt'
|
196
|
+
dataset = dataset.filter ":column < '#{value}'", :column => qualified_column_name
|
197
|
+
when 'gt'
|
198
|
+
dataset = dataset.filter ":column > '#{value}'", :column => qualified_column_name
|
199
|
+
else
|
200
|
+
dataset = dataset.filter qualified_column_name => value
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
# skip sorting, eager joining and paging if dataset is used for count
|
206
|
+
unless for_count
|
207
|
+
if params[:sort] && sort_params = params[:sort]
|
208
|
+
sort_params.each do |sort_param|
|
209
|
+
assoc, method = sort_param["property"].split("__")
|
210
|
+
dir = sort_param["direction"].downcase
|
211
|
+
|
212
|
+
# if a sorting scope is set, call the scope with the given direction
|
213
|
+
column = columns.detect { |c| c[:name] == sort_param["property"] }
|
214
|
+
if column.try(:'has_key?', :sorting_scope)
|
215
|
+
dataset = dataset.send(column[:sorting_scope].to_sym, dir.to_sym)
|
216
|
+
else
|
217
|
+
if method # sorting on associations column
|
218
|
+
# graph the association for LEFT OUTER JOIN
|
219
|
+
dataset = dataset.eager_graph(assoc.to_sym) unless graphed.include? assoc.to_sym
|
220
|
+
graphed << assoc.to_sym
|
221
|
+
end
|
222
|
+
# coincidentally, netzkes convention of specifying association's attributes
|
223
|
+
# i.e. "author__name" on Book matches sequel's convention
|
224
|
+
# so we can just pass symbolized property here
|
225
|
+
dataset = dataset.order(sort_param["property"].to_sym.send(dir))
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# eager load the associations indicated by columns,
|
231
|
+
# but only if we didn't eager_graph them before (for ordering/filtering)
|
232
|
+
# because this saves a ID IN query
|
233
|
+
columns.each do |column|
|
234
|
+
if column[:name].index('__')
|
235
|
+
assoc, _ = column[:name].split('__')
|
236
|
+
dataset = dataset.eager(assoc.to_sym) unless graphed.include? assoc.to_sym
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# apply paging
|
241
|
+
if params[:limit]
|
242
|
+
if params[:start]
|
243
|
+
dataset = dataset.limit params[:limit], params[:start]
|
244
|
+
else
|
245
|
+
dataset = dataset.limit params[:limit]
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# apply scope
|
251
|
+
# need to symbolize_keys, because when the request is made from client-side (as opposed
|
252
|
+
# to server-side on inital render), the scope's keys are given as string {"author_id" => 1}
|
253
|
+
# If we give Sequel a filter like this, it will (correctly) do WHERE 'author_id' = 1 - note the quotes
|
254
|
+
# making the database match the string author_id to 1 and to the column.
|
255
|
+
dataset = dataset.extend_with(params[:scope].symbolize_keys) if params[:scope]
|
256
|
+
dataset
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
@@ -99,18 +99,18 @@ module Netzke
|
|
99
99
|
|
100
100
|
def js_config
|
101
101
|
super.tap do |res|
|
102
|
-
res[:pri] = data_class && data_class.primary_key
|
102
|
+
res[:pri] = data_class && data_class.primary_key.to_s
|
103
103
|
res[:record] = js_record_data if record
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
107
|
# A hash of record data including the meta field
|
108
108
|
def js_record_data
|
109
|
-
record.
|
109
|
+
record.netzke_hash(fields).merge(:_meta => meta_field).literalize_keys
|
110
110
|
end
|
111
111
|
|
112
112
|
def record
|
113
|
-
@record ||= config[:record] || config[:record_id] && data_class &&
|
113
|
+
@record ||= config[:record] || config[:record_id] && data_class && data_adapter.find_record(config[:record_id])
|
114
114
|
end
|
115
115
|
|
116
116
|
private
|
@@ -10,12 +10,11 @@ module Netzke
|
|
10
10
|
@form_panel_items ||= begin
|
11
11
|
res = normalize_fields(super || data_class && data_class.netzke_attributes || []) # netzke_attributes as default items
|
12
12
|
# if primary key isn't there, insert it as first
|
13
|
-
if data_class && !res.detect{ |f| f[:name] == data_class.primary_key}
|
13
|
+
if data_class && !res.detect{ |f| f[:name] == data_class.primary_key.to_s}
|
14
14
|
primary_key_item = normalize_field(data_class.primary_key.to_sym)
|
15
15
|
@fields_from_config[data_class.primary_key.to_sym] = primary_key_item
|
16
16
|
res.insert(0, primary_key_item)
|
17
17
|
end
|
18
|
-
|
19
18
|
res
|
20
19
|
end
|
21
20
|
end
|
@@ -121,14 +120,11 @@ module Netzke
|
|
121
120
|
def detect_association_with_method(c)
|
122
121
|
if c[:name].index('__')
|
123
122
|
assoc_name, method = c[:name].split('__').map(&:to_sym)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
else
|
130
|
-
c[:xtype] ||= assoc_method_type == :boolean ? xtype_for_attr_type(assoc_method_type) : xtype_for_association
|
131
|
-
end
|
123
|
+
assoc_method_type = data_adapter.get_assoc_property_type(assoc_name, method)
|
124
|
+
if c[:nested_attribute]
|
125
|
+
c[:xtype] ||= xtype_for_attr_type(assoc_method_type)
|
126
|
+
else
|
127
|
+
c[:xtype] ||= assoc_method_type == :boolean ? xtype_for_attr_type(assoc_method_type) : xtype_for_association
|
132
128
|
end
|
133
129
|
end
|
134
130
|
end
|
@@ -18,7 +18,7 @@ module Netzke
|
|
18
18
|
#
|
19
19
|
# someForm.netzkeLoad({id: 100});
|
20
20
|
endpoint :netzke_load do |params|
|
21
|
-
@record = data_class &&
|
21
|
+
@record = data_class && data_adapter.find_record(params[:id])
|
22
22
|
{:set_form_values => js_record_data}
|
23
23
|
end
|
24
24
|
|
@@ -42,16 +42,19 @@ module Netzke
|
|
42
42
|
|
43
43
|
# Returns array of form values according to the configured columns
|
44
44
|
# def array_of_values
|
45
|
-
# @record && @record.
|
45
|
+
# @record && @record.netzke_array(fields)
|
46
46
|
# end
|
47
47
|
|
48
48
|
def values
|
49
|
-
record && record.
|
49
|
+
record && record.netzke_hash(fields)
|
50
50
|
end
|
51
51
|
|
52
52
|
# Implementation for the "netzke_submit" endpoint (for backward compatibility)
|
53
53
|
def netzke_submit(params)
|
54
54
|
data = ActiveSupport::JSON.decode(params[:data])
|
55
|
+
data.each_pair do |k,v|
|
56
|
+
data[k]=nil if v.blank? || v == "null" # Ext JS returns "null" on empty date fields, or "" for not filled optional integer fields, which gives errors when passed to model (at least in DataMapper)
|
57
|
+
end
|
55
58
|
|
56
59
|
# File uploads are in raw params instead of "data" hash, so, mix them in into "data"
|
57
60
|
if config[:file_upload]
|
@@ -66,8 +69,8 @@ module Netzke
|
|
66
69
|
{:set_form_values => js_record_data, :set_result => true}
|
67
70
|
else
|
68
71
|
# flash eventual errors
|
69
|
-
@record.
|
70
|
-
flash :error =>
|
72
|
+
data_adapter.errors_array(@record).each do |error|
|
73
|
+
flash :error => error
|
71
74
|
end
|
72
75
|
{:netzke_feedback => @flash, :apply_form_errors => build_form_errors(record)}
|
73
76
|
end
|
@@ -78,14 +81,10 @@ module Netzke
|
|
78
81
|
# Builds the form errors
|
79
82
|
def build_form_errors(record)
|
80
83
|
form_errors = {}
|
81
|
-
foreign_keys =
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
foreign_keys[r.association_foreign_key.to_sym] = r.name
|
86
|
-
}
|
87
|
-
|
88
|
-
record.errors.map{|field, error|
|
84
|
+
foreign_keys = data_adapter.hash_fk_model
|
85
|
+
record.errors.to_hash.map{|field, error|
|
86
|
+
# some ORM return an array for error
|
87
|
+
error = error.join ', ' if error.kind_of? Array
|
89
88
|
# Get the correct field name for the errors on foreign keys
|
90
89
|
if foreign_keys.has_key?(field)
|
91
90
|
fields.each do |k, v|
|
@@ -93,7 +92,6 @@ module Netzke
|
|
93
92
|
field = k.to_s.gsub('__', '____') if k.to_s.split('__').first == foreign_keys[field].to_s
|
94
93
|
end
|
95
94
|
end
|
96
|
-
|
97
95
|
form_errors[field] ||= []
|
98
96
|
form_errors[field] << error
|
99
97
|
}
|
@@ -103,7 +101,8 @@ module Netzke
|
|
103
101
|
# Creates/updates a record from hash
|
104
102
|
def create_or_update_record(hsh)
|
105
103
|
hsh.merge!(config[:strong_default_attrs]) if config[:strong_default_attrs]
|
106
|
-
@record ||=
|
104
|
+
@record ||= data_adapter.find_record hsh.delete(data_class.primary_key.to_s) # only pick up the record specified in the params if it was not provided in the configuration
|
105
|
+
#data_class.find(:first, :conditions => {data_class.primary_key => hsh.delete(data_class.primary_key)})
|
107
106
|
success = true
|
108
107
|
|
109
108
|
@record = data_class.new if @record.nil?
|
@@ -123,7 +122,7 @@ module Netzke
|
|
123
122
|
#end
|
124
123
|
|
125
124
|
# did we have complete success?
|
126
|
-
success && @record
|
125
|
+
success && data_adapter.save_record(@record)
|
127
126
|
end
|
128
127
|
|
129
128
|
# API handling form load
|
@@ -126,6 +126,11 @@ module Netzke
|
|
126
126
|
class GridPanel < Netzke::Base
|
127
127
|
js_base_class "Ext.grid.Panel"
|
128
128
|
|
129
|
+
class_attribute :columns_attr
|
130
|
+
|
131
|
+
class_attribute :overridden_columns_attr
|
132
|
+
self.overridden_columns_attr = {}
|
133
|
+
|
129
134
|
# Class-level configuration. These options directly influence the amount of generated
|
130
135
|
# javascript code for this component's class. For example, if you don't want filters for the grid,
|
131
136
|
# set column_filters_available to false, and the javascript for the filters won't be included at all.
|
@@ -198,15 +203,14 @@ module Netzke
|
|
198
203
|
base.class_eval do
|
199
204
|
class << self
|
200
205
|
def column(name, config = {})
|
201
|
-
columns = self.
|
202
|
-
columns
|
203
|
-
self.
|
206
|
+
columns = self.columns_attr || []
|
207
|
+
columns |= [config.merge(:name => name.to_s)]
|
208
|
+
self.columns_attr = columns
|
204
209
|
end
|
205
210
|
|
206
211
|
def override_column(name, config)
|
207
|
-
columns = self.
|
208
|
-
columns.merge
|
209
|
-
self.write_inheritable_attribute(:overridden_columns, columns)
|
212
|
+
columns = self.overridden_columns_attr.dup
|
213
|
+
self.overridden_columns_attr = columns.merge(name.to_sym => config)
|
210
214
|
end
|
211
215
|
end
|
212
216
|
end
|
@@ -214,10 +218,10 @@ module Netzke
|
|
214
218
|
|
215
219
|
def configuration
|
216
220
|
super.tap do |c|
|
217
|
-
c[:columns] ||= self.
|
221
|
+
c[:columns] ||= self.columns_attr
|
218
222
|
|
219
223
|
# user-passed :override_columns option should get deep_merged with the defaults
|
220
|
-
c[:override_columns] =
|
224
|
+
c[:override_columns] = self.overridden_columns_attr.deep_merge(c[:override_columns] || {})
|
221
225
|
end
|
222
226
|
end
|
223
227
|
|
@@ -243,8 +247,10 @@ module Netzke
|
|
243
247
|
|
244
248
|
def get_default_association_values #:nodoc:
|
245
249
|
columns.select{ |c| c[:name].index("__") && c[:default_value] }.each.inject({}) do |r,c|
|
246
|
-
|
247
|
-
|
250
|
+
assoc_name, assoc_method = c[:name].split '__'
|
251
|
+
assoc_class = data_adapter.class_for(assoc_name)
|
252
|
+
assoc_data_adapter = Netzke::Basepack::DataAdapters::AbstractAdapter.adapter_class(assoc_class).new(assoc_class)
|
253
|
+
assoc_instance = assoc_data_adapter.find_record c[:default_value]
|
248
254
|
r.merge(c[:name] => assoc_instance.send(assoc_method))
|
249
255
|
end
|
250
256
|
end
|