hatio-core 0.0.6
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +28 -0
- data/Rakefile +6 -0
- data/lib/generators/hatio/bundle/USAGE +68 -0
- data/lib/generators/hatio/bundle/bundle_generator.rb +100 -0
- data/lib/generators/hatio/bundle/templates/04_seed_entities.rb +9 -0
- data/lib/generators/hatio/bundle/templates/05_seed_common_codes.rb +8 -0
- data/lib/generators/hatio/bundle/templates/06_seed_menus.rb +6 -0
- data/lib/generators/hatio/bundle/templates/Controller.js +24 -0
- data/lib/generators/hatio/bundle/templates/Gemfile +4 -0
- data/lib/generators/hatio/bundle/templates/LICENSE.txt +22 -0
- data/lib/generators/hatio/bundle/templates/README.md +29 -0
- data/lib/generators/hatio/bundle/templates/Rakefile +1 -0
- data/lib/generators/hatio/bundle/templates/engine.rb +7 -0
- data/lib/generators/hatio/bundle/templates/gemspec +19 -0
- data/lib/generators/hatio/bundle/templates/index.js +14 -0
- data/lib/generators/hatio/bundle/templates/init.rb +1 -0
- data/lib/generators/hatio/bundle/templates/lib_bundle.rb +12 -0
- data/lib/generators/hatio/bundle/templates/locale.js +13 -0
- data/lib/generators/hatio/bundle/templates/locales.yml +27 -0
- data/lib/generators/hatio/bundle/templates/pluggable_spot.rb +3 -0
- data/lib/generators/hatio/bundle/templates/routes.rb +3 -0
- data/lib/generators/hatio/bundle/templates/seeds.rb +4 -0
- data/lib/generators/hatio/bundle/templates/task.rake +4 -0
- data/lib/generators/hatio/bundle/templates/test.rb +8 -0
- data/lib/generators/hatio/bundle/templates/test_helper.rb +3 -0
- data/lib/generators/hatio/bundle/templates/version.rb +3 -0
- data/lib/generators/hatio/resource_api/resource_api_generator.rb +92 -0
- data/lib/generators/hatio/resource_api/templates/controller.rb +7 -0
- data/lib/generators/hatio/resource_api/templates/create.json.jbuilder +1 -0
- data/lib/generators/hatio/resource_api/templates/destroy.json.jbuilder +1 -0
- data/lib/generators/hatio/resource_api/templates/index.json.jbuilder +1 -0
- data/lib/generators/hatio/resource_api/templates/migration.rb +1 -0
- data/lib/generators/hatio/resource_api/templates/model.rb +3 -0
- data/lib/generators/hatio/resource_api/templates/show.json.jbuilder +3 -0
- data/lib/generators/hatio/resource_api/templates/update.json.jbuilder +2 -0
- data/lib/generators/hatio/resource_model/resource_model_generator.rb +52 -0
- data/lib/generators/hatio/resource_model/templates/migration.rb +1 -0
- data/lib/generators/hatio/resource_model/templates/model.rb +3 -0
- data/lib/generators/hatio/resource_view/USAGE +16 -0
- data/lib/generators/hatio/resource_view/resource_view_generator.rb +154 -0
- data/lib/generators/hatio/resource_view/templates/Model.js +19 -0
- data/lib/generators/hatio/resource_view/templates/Store.js +34 -0
- data/lib/generators/hatio/resource_view/templates/detail/Controller.js +81 -0
- data/lib/generators/hatio/resource_view/templates/detail/DetailForm.js +17 -0
- data/lib/generators/hatio/resource_view/templates/detail/DetailMain.js +26 -0
- data/lib/generators/hatio/resource_view/templates/detail/DetailPopup.js +25 -0
- data/lib/generators/hatio/resource_view/templates/detail/PopupController.js +90 -0
- data/lib/generators/hatio/resource_view/templates/detail/ViewController.js +78 -0
- data/lib/generators/hatio/resource_view/templates/item/Controller.js +81 -0
- data/lib/generators/hatio/resource_view/templates/item/ItemForm.js +19 -0
- data/lib/generators/hatio/resource_view/templates/item/ItemMain.js +18 -0
- data/lib/generators/hatio/resource_view/templates/item/ItemPopup.js +25 -0
- data/lib/generators/hatio/resource_view/templates/item/PopupController.js +90 -0
- data/lib/generators/hatio/resource_view/templates/item/ViewController.js +47 -0
- data/lib/generators/hatio/resource_view/templates/list/Controller.js +36 -0
- data/lib/generators/hatio/resource_view/templates/list/ListGrid.js +10 -0
- data/lib/generators/hatio/resource_view/templates/list/ListMain.js +20 -0
- data/lib/generators/hatio/resource_view/templates/list/ListSearch.js +9 -0
- data/lib/generators/hatio/resource_view/templates/report/Controller.js +53 -0
- data/lib/generators/hatio/resource_view/templates/report/ReportList.js +27 -0
- data/lib/generators/hatio/resource_view/templates/report/ReportMain.js +18 -0
- data/lib/generators/hatio/resource_view/templates/report/ReportSearch.js +9 -0
- data/lib/generators/hatio/util/api_util.rb +97 -0
- data/lib/generators/hatio/util/migration_util.rb +178 -0
- data/lib/generators/hatio/util/model_util.rb +77 -0
- data/lib/generators/hatio/util/report_view_util.rb +32 -0
- data/lib/generators/hatio/util/resource_view_util.rb +383 -0
- data/lib/generators/hatio/util/view_util.rb +214 -0
- data/lib/hatio-core.rb +33 -0
- data/lib/hatio-core/action_controller/search_helper.rb +332 -0
- data/lib/hatio-core/active_record/extension_logic.rb +36 -0
- data/lib/hatio-core/active_record/rem_tracker.rb +35 -0
- data/lib/hatio-core/active_record/stringified_id.rb +75 -0
- data/lib/hatio-core/active_record/stripper.rb +37 -0
- data/lib/hatio-core/active_record/userstamp.rb +48 -0
- data/lib/hatio-core/birt/birt_report.rb +42 -0
- data/lib/hatio-core/bundle/hatio_bundle.rb +37 -0
- data/lib/hatio-core/engine.rb +5 -0
- data/lib/hatio-core/exception/exceptions.rb +33 -0
- data/lib/hatio-core/patch/actionpack_hatio_patch.rb +28 -0
- data/lib/hatio-core/patch/date.rb +11 -0
- data/lib/hatio-core/patch/string_key.rb +56 -0
- data/lib/hatio-core/pluggable/pluggable_spot.rb +22 -0
- data/lib/hatio-core/util/hatio_util.rb +106 -0
- data/lib/hatio-core/version.rb +3 -0
- data/lib/tasks/hatiocore_tasks.rake +75 -0
- data/lib/utils/detect_invalid_js_format.rb +0 -0
- data/lib/utils/detect_mismatch_tags.rb +57 -0
- data/lib/utils/update_license.rb +5 -0
- data/lib/utils/upload_locale.rb +67 -0
- metadata +148 -0
@@ -0,0 +1,214 @@
|
|
1
|
+
module Hatio
|
2
|
+
module Generators
|
3
|
+
class ViewUtil
|
4
|
+
|
5
|
+
#
|
6
|
+
# columns 정보로 부터 그리드를 생성
|
7
|
+
#
|
8
|
+
def self.generate_grid(singularName, columns, options, indent)
|
9
|
+
output = "columns : [\n"
|
10
|
+
indent = "\t\t" unless indent
|
11
|
+
|
12
|
+
output << "#{indent}{ dataIndex : '_cud_flag_', hidden : true, value : '' },\n"
|
13
|
+
|
14
|
+
columns.each do |col|
|
15
|
+
if(col.name == 'id')
|
16
|
+
output << "#{indent}{ header : T('label.id'), dataIndex : 'id', hidden : true },\n"
|
17
|
+
elsif(col.name == 'name')
|
18
|
+
output << "#{indent}{ header : T('label.name'), dataIndex : 'name', editor : { xtype : 'textfield', allowBlank : false } },\n"
|
19
|
+
elsif(col.name == 'description')
|
20
|
+
output << "#{indent}{ header : T('label.description'), dataIndex : 'description', editor : { xtype : 'textfield', allowBlank : true } },\n"
|
21
|
+
elsif(col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id')
|
22
|
+
output << "#{indent}{ dataIndex : '#{col.name}', hidden : true },\n"
|
23
|
+
elsif(col.name == 'created_at' || col.name == 'updated_at')
|
24
|
+
output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', xtype : 'datecolumn', disabled : true, format : T('format.datetime') },\n"
|
25
|
+
else
|
26
|
+
if(col.type == :string)
|
27
|
+
output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'textfield' } },\n"
|
28
|
+
elsif(col.type == :text)
|
29
|
+
output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'textareafield' } },\n"
|
30
|
+
elsif(col.type == :boolean)
|
31
|
+
output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', xtype : 'checkcolumn' },\n"
|
32
|
+
elsif(col.type == :date)
|
33
|
+
output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'datefield', format : T('format.date') } },\n"
|
34
|
+
elsif(col.type == :datetime)
|
35
|
+
output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'datefield', format : T('format.datetime') } },\n"
|
36
|
+
elsif(col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
|
37
|
+
output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'numberfield' } },\n"
|
38
|
+
else
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
output << "#{indent}],\n"
|
44
|
+
output
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# resource의 columns로 부터 form 정보를 생성하여 리턴
|
49
|
+
#
|
50
|
+
def self.generate_form(resourceName, columns, options, indent)
|
51
|
+
output = ""
|
52
|
+
indent = "\t\t" unless indent
|
53
|
+
|
54
|
+
columns.each do |col|
|
55
|
+
|
56
|
+
if(col.name == 'id')
|
57
|
+
output << "#{indent}{ name : 'id', fieldLabel : T('label.id'), hidden : true },\n"
|
58
|
+
elsif(col.name == 'domain_id')
|
59
|
+
output << "#{indent}{ name : 'domain_id', value : login.current_domain_id, hidden : true },\n"
|
60
|
+
elsif(col.name == 'creator_id' || col.name == 'updater_id')
|
61
|
+
# skip
|
62
|
+
elsif(col.name == 'created_at' || col.name == 'updated_at')
|
63
|
+
output << "#{indent}{ xtype : 'datefield', name : '#{col.name}', disabled : true, fieldLabel : T('label.#{col.name}'), format : T('format.datetime') },\n"
|
64
|
+
elsif(col.name == 'image_data')
|
65
|
+
output << "#{indent}{ id : '#{resourceName}-image-upload', itemId : '#{resourceName}-image-upload', xtype : 'fileuploadfield', inputType : 'file', name : 'image_upload', fieldLabel : T('label.image') }, \n"
|
66
|
+
output << "#{indent}{ xtype : 'textareafield', name : '#{col.name}', fieldLabel : T('label.data'), rows : 16, readOnly : true }, \n"
|
67
|
+
else
|
68
|
+
if(col.type == :string)
|
69
|
+
output << "#{indent}{ name : '#{col.name}', fieldLabel : T('label.#{col.name}') },\n"
|
70
|
+
elsif(col.type == :text)
|
71
|
+
output << "#{indent}{ xtype : 'textareafield', name : '#{col.name}', fieldLabel : T('label.#{col.name}') }, \n"
|
72
|
+
elsif(col.type == :boolean)
|
73
|
+
output << "#{indent}{ name : '#{col.name}', fieldLabel : T('label.#{col.name}'), xtype : 'checkboxfield', inputValue : true },\n"
|
74
|
+
elsif(col.type == :date)
|
75
|
+
output << "#{indent}{ xtype : 'datefield', name : '#{col.name}', disabled : true, fieldLabel : T('label.#{col.name}'), format : T('format.date') },\n"
|
76
|
+
elsif(col.type == :datetime)
|
77
|
+
output << "#{indent}{ xtype : 'datefield', name : '#{col.name}', disabled : true, fieldLabel : T('label.#{col.name}'), format : T('format.datetime') },\n"
|
78
|
+
elsif(col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
|
79
|
+
output << "#{indent}{ name : '#{col.name}', fieldLabel : T('label.#{col.name}'), xtype : 'numberfield' },\n"
|
80
|
+
else
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
output
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# columns 정보로 부터 search condition items를 생성
|
90
|
+
#
|
91
|
+
def self.generate_search_items(resourceName, columns, options, indent)
|
92
|
+
output = "items : [ \n"
|
93
|
+
indent = "\t\t" unless indent
|
94
|
+
|
95
|
+
columns.each do |col|
|
96
|
+
if(col.name == 'id' || col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id')
|
97
|
+
elsif(col.name == 'created_at' || col.name == 'updated_at')
|
98
|
+
#output << "#{indent}{ fieldLabel : T('label.#{col.name}_from'), name : '#{col.name}-gte', xtype : 'datefield', format : T('format.date') },\n"
|
99
|
+
#output << "#{indent}{ fieldLabel : T('label.#{col.name}_to'), name : '#{col.name}-lte', xtype : 'datefield', format : T('format.date') },\n"
|
100
|
+
else
|
101
|
+
if(col.type == :string || col.type == :text)
|
102
|
+
output << "#{indent}{ fieldLabel : T('label.#{col.name}'), name : '#{col.name}-like' },\n"
|
103
|
+
elsif(col.type == :boolean)
|
104
|
+
output << "#{indent}{ fieldLabel : T('label.#{col.name}'), name : '#{col.name}-eq', inputValue : true, xtype : 'checkboxfield', inputValue : true },\n"
|
105
|
+
elsif(col.type == :date)
|
106
|
+
output << "#{indent}{ fieldLabel : T('label.#{col.name}_from'), name : '#{col.name}-gte', xtype : 'datefield', format : T('format.date') },\n"
|
107
|
+
output << "#{indent}{ fieldLabel : T('label.#{col.name}_to'), name : '#{col.name}-lte', xtype : 'datefield', format : T('format.date') },\n"
|
108
|
+
elsif(col.type == :datetime)
|
109
|
+
output << "#{indent}{ fieldLabel : T('label.#{col.name}_from'), name : '#{col.name}-gte', xtype : 'datefield', format : T('format.datetime') },\n"
|
110
|
+
output << "#{indent}{ fieldLabel : T('label.#{col.name}_to'), name : '#{col.name}-lte', xtype : 'datefield', format : T('format.datetime') },\n"
|
111
|
+
elsif(col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
|
112
|
+
output << "#{indent}{ fieldLabel : T('label.#{col.name}'), name : '#{col.name}-eq', xtype : 'numberfield' },\n"
|
113
|
+
else
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
output << "#{indent}],\n"
|
119
|
+
output
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# columns 정보로 부터 store filter 코드 생성
|
124
|
+
#
|
125
|
+
def self.generateStoreFilter(resourceName, columns, options, indent)
|
126
|
+
indent = "\t\t" unless indent
|
127
|
+
output = "store.filter([ {\n"
|
128
|
+
output << "#{indent}#{indent}property : 'domain_id-eq',\n"
|
129
|
+
output << "#{indent}#{indent}value : login.current_domain_id\n"
|
130
|
+
output << "#{indent}}, \n"
|
131
|
+
|
132
|
+
columns.each do |col|
|
133
|
+
if(col.name == 'id' || col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id' || col.name == 'created_at' || col.name == 'updated_at')
|
134
|
+
elsif(col.name.end_with?('_id'))
|
135
|
+
output << "#{indent}{ \n"
|
136
|
+
output << "#{indent}#{indent}property : '#{col.name}-eq',\n"
|
137
|
+
output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_filter').getValue()\n"
|
138
|
+
output << "#{indent}},\n"
|
139
|
+
else
|
140
|
+
if(col.type == :string || col.type == :text)
|
141
|
+
output << "#{indent}{ \n"
|
142
|
+
output << "#{indent}#{indent}property : '#{col.name}-like',\n"
|
143
|
+
output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_filter').getValue()\n"
|
144
|
+
output << "#{indent}},\n"
|
145
|
+
elsif(col.type == :date || col.type == :datetime)
|
146
|
+
output << "#{indent}{ \n"
|
147
|
+
output << "#{indent}#{indent}property : '#{col.name}-gte',\n"
|
148
|
+
output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_from_filter').getValue()\n"
|
149
|
+
output << "#{indent}},\n"
|
150
|
+
output << "#{indent}{ \n"
|
151
|
+
output << "#{indent}#{indent}property : '#{col.name}-lte',\n"
|
152
|
+
output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_to_filter').getValue()\n"
|
153
|
+
output << "#{indent}},\n"
|
154
|
+
elsif(col.type == :boolean || col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
|
155
|
+
output << "#{indent}{ \n"
|
156
|
+
output << "#{indent}#{indent}property : '#{col.name}-eq',\n"
|
157
|
+
output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_filter').getValue()\n"
|
158
|
+
output << "#{indent}},\n"
|
159
|
+
else
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
output << "#{indent}]);\n"
|
165
|
+
output
|
166
|
+
end
|
167
|
+
|
168
|
+
#
|
169
|
+
# columns 정보로 부터 search filter를 리셋
|
170
|
+
#
|
171
|
+
def self.generateResetFilters(resourceName, columns, options, indent)
|
172
|
+
indent = "\t\t" unless indent
|
173
|
+
output = ""
|
174
|
+
|
175
|
+
columns.each do |col|
|
176
|
+
if(col.name == 'id' || col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id' || col.name == 'created_at' || col.name == 'updated_at')
|
177
|
+
else
|
178
|
+
if(col.type == :string || col.type == :text)
|
179
|
+
output << "#{indent}this.findItem(' \##{col.name}_filter').setValue('');\n";
|
180
|
+
elsif(col.type == :date || col.type == :datetime)
|
181
|
+
output << "#{indent}this.findItem(' \##{col.name}_filter').setValue('');\n";
|
182
|
+
elsif(col.type == :boolean || col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
|
183
|
+
output << "#{indent}this.findItem(' \##{col.name}_filter').setValue(false);\n";
|
184
|
+
else
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
output
|
190
|
+
end
|
191
|
+
|
192
|
+
#
|
193
|
+
# 새로운 model 생성
|
194
|
+
#
|
195
|
+
def self.generateNewModel(resourceName, columns, options, indent)
|
196
|
+
indent = "\t" unless indent
|
197
|
+
output = "data = data || {\n"
|
198
|
+
output << "#{indent}#{indent}#{indent}domain_id : login.current_domain_id,\n"
|
199
|
+
|
200
|
+
columns.each do |col|
|
201
|
+
if(col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id' || col.name == 'created_at' || col.name == 'updated_at')
|
202
|
+
else
|
203
|
+
output << "#{indent}#{indent}#{indent}#{col.name} : '',\n"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
output << "#{indent}#{indent}#{indent}_cud_flag_ : 'c'};\n"
|
207
|
+
output << "#{indent}#{indent}return Ext.create('#{options.bundle}.model.#{resourceName}', data);"
|
208
|
+
output
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|
data/lib/hatio-core.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'hatio-core/engine'
|
2
|
+
require 'hatio-core/version'
|
3
|
+
require 'hatio-core/engine'
|
4
|
+
|
5
|
+
require 'hatio-core/pluggable/pluggable_spot'
|
6
|
+
require 'hatio-core/action_controller/search_helper'
|
7
|
+
require 'hatio-core/patch/string_key'
|
8
|
+
require 'hatio-core/patch/actionpack_hatio_patch'
|
9
|
+
require 'hatio-core/patch/date'
|
10
|
+
require 'hatio-core/active_record/stripper'
|
11
|
+
require 'hatio-core/active_record/stringified_id'
|
12
|
+
require 'hatio-core/active_record/userstamp'
|
13
|
+
require 'hatio-core/active_record/rem_tracker'
|
14
|
+
require 'hatio-core/active_record/extension_logic'
|
15
|
+
require 'hatio-core/util/hatio_util'
|
16
|
+
require 'hatio-core/bundle/hatio_bundle'
|
17
|
+
require 'hatio-core/exception/exceptions'
|
18
|
+
# require 'hatio-core/birt/birt_report'
|
19
|
+
|
20
|
+
include Hatio::Util::HatioUtil
|
21
|
+
|
22
|
+
ActiveRecord::Base.send :include, Hatio::Stripper
|
23
|
+
ActiveRecord::Base.send :include, Hatio::StringfiedID
|
24
|
+
ActiveRecord::Base.send :include, Hatio::Userstamp
|
25
|
+
ActiveRecord::Base.send :include, Hatio::RemTracker
|
26
|
+
ActiveRecord::Base.send :include, Hatio::ExtensionLogic
|
27
|
+
ActionController::Base.send :include, Hatio::SearchHelper
|
28
|
+
|
29
|
+
puts "Things Framework Loaded!"
|
30
|
+
|
31
|
+
Hatio::Bundle.new 'hatio-core', HatioCore::VERSION do |bundle|
|
32
|
+
bundle.dependencies = []
|
33
|
+
end
|
@@ -0,0 +1,332 @@
|
|
1
|
+
module Hatio
|
2
|
+
module SearchHelper
|
3
|
+
|
4
|
+
#
|
5
|
+
# 검색 조건, 소트 조건, Pagination 조건을 분석하여 검색을 구현
|
6
|
+
#
|
7
|
+
def search_filter resource, options = {}
|
8
|
+
# pagination 정보는 넘어온 page, limit 정보를 이용
|
9
|
+
page, limit, offset = find_pagination_info
|
10
|
+
search_param_type, search_params = nil, nil
|
11
|
+
|
12
|
+
# search parameter는 filter or _q 파라미터를 이용
|
13
|
+
if(!params[:_q].blank?)
|
14
|
+
search_param_type, search_params = 1, params[:_q]
|
15
|
+
elsif(!params[:filter].blank?)
|
16
|
+
search_param_type, search_params = 2, params[:filter]
|
17
|
+
else
|
18
|
+
search_param_type, search_params = 1, params
|
19
|
+
end
|
20
|
+
|
21
|
+
# sort parameter는 sort or _o 파라미터를 이용
|
22
|
+
sort_type, sort_params, order_result = nil, nil, ""
|
23
|
+
if(!params[:_o].blank?)
|
24
|
+
sort_type, sort_params = 1, params[:_o]
|
25
|
+
elsif(!params[:sort].blank?)
|
26
|
+
sort_type, sort_params = 2, params[:sort]
|
27
|
+
end
|
28
|
+
|
29
|
+
# table name을 찾고 where 조건의 컬럼명 앞에 table_name.을 붙인다. Join 쿼리를 사용 할 경우 애매한 열 정의를 없애기 위함
|
30
|
+
table_name = options.key?(:table_name) ? options[:table_name] : resource.table_name
|
31
|
+
entity = Entity.find_by_name(resource.to_s)
|
32
|
+
if(entity)
|
33
|
+
columns = entity.columns_for_search
|
34
|
+
# select fields는 select parameter가 있으면 select parameter를, 없으면 select *
|
35
|
+
list_columns = find_select_columns(columns)
|
36
|
+
|
37
|
+
if(search_param_type == 1)
|
38
|
+
conditions = build_conditions_by_search_params(table_name, search_params, columns)
|
39
|
+
elsif(search_param_type == 2)
|
40
|
+
conditions = build_conditions_by_filters(table_name, search_params, columns)
|
41
|
+
end
|
42
|
+
|
43
|
+
# select parameter로 association이 있는 부분을 찾아서 ...
|
44
|
+
include_arr = find_association_list(resource, list_columns, options)
|
45
|
+
order_result = (sort_type == 1) ? build_orders_by_sort_params(sort_params) : build_orders_by_sorters(sort_params) if(sort_type)
|
46
|
+
return conditions, include_arr, order_result, limit, offset
|
47
|
+
else
|
48
|
+
debug_print "Not found Entity of resource [#{resource.to_s}]"
|
49
|
+
return "", [], "", limit, offset
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# select fields를 찾는다. select 파라미터가 넘어오면 해당 필드만, 그렇지 않으면 모든 필드가 select 대상이다.
|
55
|
+
#
|
56
|
+
def find_select_columns(columns)
|
57
|
+
select_columns = (!params[:_s] || params[:_s].blank?) ? [] : params[:_s]
|
58
|
+
return select_columns.empty? ?
|
59
|
+
columns :
|
60
|
+
columns.select{ |c| select_columns.include?(c.name) || select_columns.include?(c.name.sub(/_id$/, '')) }
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# 필드 타입 정보를 바탕으로 검색 조건 값을 sql에 맞게 변환한다.
|
65
|
+
#
|
66
|
+
def convert_value_by_col_type(filter_value, column)
|
67
|
+
if(column.col_type == 'time' || column.col_type == 'datetime' || column.col_type == 'timestamp')
|
68
|
+
return (filter_value.size <= 10) ? parse_date(filter_value) : parse_time_to_db(filter_value)
|
69
|
+
elsif(column.col_type == 'date')
|
70
|
+
return parse_date(filter_value)
|
71
|
+
elsif(column.col_type == 'boolean')
|
72
|
+
return (filter_value.to_s =~ /^(t|true|on|y|yes)$/i) == 0 ? true : false
|
73
|
+
else
|
74
|
+
return filter_value
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# like 타입 검색 조건이면 like 검색을 위해서 검색 조건 값을 like문에 맞게 변환한다.
|
80
|
+
#
|
81
|
+
def convert_like_type_condition_value(operator, value)
|
82
|
+
return value unless like_type_operator?(operator)
|
83
|
+
value = value.strip
|
84
|
+
|
85
|
+
case operator
|
86
|
+
when 'like' # like
|
87
|
+
return "%#{value}%"
|
88
|
+
when 'contains' # equals to like
|
89
|
+
return "%#{value}%"
|
90
|
+
when 'nlike' # not like
|
91
|
+
return "%#{value}%"
|
92
|
+
when 'sw' # starts with
|
93
|
+
return "#{value}%"
|
94
|
+
when 'dnsw' # does not start with
|
95
|
+
return "#{value}%"
|
96
|
+
when 'ew' # ends with
|
97
|
+
return "%#{value}"
|
98
|
+
when 'dnew' # does not end with
|
99
|
+
return "%#{value}"
|
100
|
+
when 'in'
|
101
|
+
val_arr = value.split(",")
|
102
|
+
return val_arr;
|
103
|
+
when 'notin'
|
104
|
+
val_arr = value.split(",")
|
105
|
+
return val_arr;
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# 검색 조건 중에 검색 조건 값이 필요 없는 검색 조건인지 판단한다.
|
111
|
+
#
|
112
|
+
def none_value_operator?(operator)
|
113
|
+
['is_null', 'is_not_null', 'is_true', 'is_false', 'is_present', 'is_blank'].include?(operator)
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# 검색 조건 중에 like 타입의 조건인지를 판단한다.
|
118
|
+
#
|
119
|
+
def like_type_operator?(operator)
|
120
|
+
['like', 'contains', 'nlike', 'sw', 'dnsw', 'ew', 'dnew', 'in', 'notin'].include?(operator)
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# 검색 조건 타입에 따라 sql where 문을 작성한다.
|
125
|
+
#
|
126
|
+
def get_condition_str(table_name, column_name, operator)
|
127
|
+
case operator
|
128
|
+
when 'eq' # equal
|
129
|
+
return " #{table_name}.#{column_name} = ?"
|
130
|
+
when 'noteq' # not equal
|
131
|
+
return " #{table_name}.#{column_name} != ?"
|
132
|
+
when 'in' # in
|
133
|
+
return " #{table_name}.#{column_name} in (?)"
|
134
|
+
when 'notin' # not in
|
135
|
+
return " #{table_name}.#{column_name} not in (?)"
|
136
|
+
when 'like', 'contains', 'sw', 'ew' # like
|
137
|
+
return " lower(#{table_name}.#{column_name}) like lower(?)"
|
138
|
+
when 'nlike', 'dnsw', 'dnew' # not like
|
139
|
+
return " lower(#{table_name}.#{column_name}) not like lower(?)"
|
140
|
+
when 'gt' # greater than
|
141
|
+
return " #{table_name}.#{column_name} > ?"
|
142
|
+
when 'gte' # greater than equal
|
143
|
+
return " #{table_name}.#{column_name} >= ?"
|
144
|
+
when 'lt' # less than
|
145
|
+
return " #{table_name}.#{column_name} < ?"
|
146
|
+
when 'lte' # less than equal
|
147
|
+
return " #{table_name}.#{column_name} <= ?"
|
148
|
+
|
149
|
+
when 'dt_eq' # date equal
|
150
|
+
return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) = ?"
|
151
|
+
when 'dt_noteq' # date not equal
|
152
|
+
return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) != ?"
|
153
|
+
when 'dt_gt' # date greater than
|
154
|
+
return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) > ?"
|
155
|
+
when 'dt_gte' # date greater than equal
|
156
|
+
return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) >= ?"
|
157
|
+
when 'dt_lt' # date less than
|
158
|
+
return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) < ?"
|
159
|
+
when 'dt_lte' # date less than equal
|
160
|
+
return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) <= ?"
|
161
|
+
|
162
|
+
when 'is_null' # is null
|
163
|
+
return " #{table_name}.#{column_name} is null"
|
164
|
+
when 'is_not_null' # is not null
|
165
|
+
return " #{table_name}.#{column_name} is not null"
|
166
|
+
when 'is_true' # is true
|
167
|
+
return " #{table_name}.#{column_name} = true"
|
168
|
+
when 'is_false' # is false
|
169
|
+
return " #{table_name}.#{column_name} = false"
|
170
|
+
when 'is_present' # not null or not empty string
|
171
|
+
return " (#{table_name}.#{column_name} is not null and #{table_name}.#{column_name} != '')"
|
172
|
+
when 'is_blank' # null or empty string
|
173
|
+
return " (#{table_name}.#{column_name} is null or #{table_name}.#{column_name} = '')"
|
174
|
+
end
|
175
|
+
return "";
|
176
|
+
end
|
177
|
+
|
178
|
+
#
|
179
|
+
# filter로 search condition 정보 생성
|
180
|
+
#
|
181
|
+
def build_conditions_by_filters(table_name, filter_str, columns)
|
182
|
+
# filter_str을 파싱하여 filter 오브젝트로 변환
|
183
|
+
filters, where_sql_arr, conditions = JSON.parse(filter_str), ["#{table_name}.id is not null"], []
|
184
|
+
filters.each do |filter|
|
185
|
+
# filter의 name, value으로 validation check
|
186
|
+
filter_name, filter_value, operator = validate_filter_info(columns, filter['property'], filter['value'])
|
187
|
+
# valid 하지 않으면 처리하지 않는다.
|
188
|
+
next unless filter_name
|
189
|
+
# 검색조건 필드명이 entity_column에 등록되어 있는 경우에는 entity_column에서 필드 타입을 찾아 알맞은 타입으로 조건 값을 변경
|
190
|
+
entity_column = columns.find { |c| c.name == filter_name } if columns
|
191
|
+
filter_value = convert_value_by_col_type(filter_value, entity_column) if entity_column
|
192
|
+
# like 타입이라면 검색 조건이라면 like문에 맞게 값에 조건문을 수정한다. (like, not like)
|
193
|
+
where_sql_arr << get_condition_str(table_name, filter_name, operator)
|
194
|
+
# like 타입이라면 검색 조건이라면 like문에 맞게 값에 %를 붙인다. ('%찾을 문자열%', '%찾을 문자열', '찾을 문자열%')
|
195
|
+
filter_value = convert_like_type_condition_value(operator, filter_value)
|
196
|
+
#debug_print("Filter : #{filter_name}, Value : #{filter_value}, Operator : #{operator}")
|
197
|
+
# 하나의 필드에 대한 조건 값을 conditions 배열에 추가한다.
|
198
|
+
conditions.push(filter_value) unless none_value_operator?(operator)
|
199
|
+
end
|
200
|
+
# 최종적으로 만들어진 sql where문을 conditions 배열 맨 앞쪽에 추가한다.
|
201
|
+
conditions.insert(0, where_sql_arr.join(" and "))
|
202
|
+
end
|
203
|
+
|
204
|
+
#
|
205
|
+
# search params로 search condition 정보 생성
|
206
|
+
#
|
207
|
+
def build_conditions_by_search_params(table_name, search_params, columns)
|
208
|
+
where_sql_arr, conditions = ["#{table_name}.id is not null"], []
|
209
|
+
# 넘어온 검색 조건 값을 - 로 구분하여 앞 부분은 검색 조건 필드명으로, 뒷 부분은 검색을 위한 operator로 사용햔다.
|
210
|
+
search_params.each do |param_name, param_value|
|
211
|
+
# filter의 name, value으로 validation check
|
212
|
+
filter_name, filter_value, operator = validate_filter_info(columns, param_name, param_value)
|
213
|
+
# valid 하지 않으면 처리하지 않는다.
|
214
|
+
next unless filter_name
|
215
|
+
# 검색조건 필드명이 entity_column에 등록되어 있는 경우에는 entity_column에서 필드 타입을 찾아 알맞은 타입으로 조건 값을 변경
|
216
|
+
entity_column = columns.find { |c| c.name == filter_name } if columns
|
217
|
+
filter_value = convert_value_by_col_type(filter_value, entity_column) if entity_column
|
218
|
+
# like 타입이라면 검색 조건이라면 like문에 맞게 값에 조건문을 수정한다. (like, not like)
|
219
|
+
where_sql_arr << get_condition_str(table_name, filter_name, operator)
|
220
|
+
# like 타입이라면 검색 조건이라면 like문에 맞게 값에 %를 붙인다. ('%찾을 문자열%', '%찾을 문자열', '찾을 문자열%')
|
221
|
+
filter_value = convert_like_type_condition_value(operator, filter_value)
|
222
|
+
#debug_print("Filter : #{filter_name}, Value : #{filter_value}, Operator : #{operator}")
|
223
|
+
# 하나의 필드에 대한 조건 값을 conditions 배열에 추가한다.
|
224
|
+
conditions.push(filter_value) unless none_value_operator?(operator)
|
225
|
+
end
|
226
|
+
conditions.insert(0, where_sql_arr.join(" and "))
|
227
|
+
end
|
228
|
+
|
229
|
+
#
|
230
|
+
# filter 정보를 validation한다.
|
231
|
+
#
|
232
|
+
def validate_filter_info(columns, filter_name, filter_value)
|
233
|
+
# filter_name이 domain_id라면 스킵
|
234
|
+
return false if(filter_name.start_with?('domain_id'))
|
235
|
+
gubunIndex = filter_name.rindex('-')
|
236
|
+
filter_name_length = filter_name.length
|
237
|
+
# - 로 구분된 문자열이 없다면 조건 검색을 위한 용도가 아니라고 판단
|
238
|
+
return false unless gubunIndex
|
239
|
+
# operator는 무조건 두 글자 이상이어야 한다.
|
240
|
+
return false unless (filter_name_length - gubunIndex > 1)
|
241
|
+
# 넘어온 검색 조건 값을 - 로 구분하여 앞 부분은 검색 조건 필드명으로, 뒷 부분은 검색을 위한 operator로 사용햔다.
|
242
|
+
column_name, operator = filter_name[0 .. (gubunIndex - 1)], filter_name[(gubunIndex + 1) .. (filter_name_length - 1)]
|
243
|
+
# resource.name-eq 형식으로 넘어온 경우는 Resource.find_by_name으로 검색하고 파라미터 명은 resource_id-eq형식으로 변환한다.
|
244
|
+
column_name, filter_value, operator = convert_reference_filter(column_name, filter_value, operator)
|
245
|
+
# 값이 비어 있고 조건 값이 필요없는 경우 ('is_null', 'is_not_null', 'is_true', 'is_false', 'is_present', 'is_blank')가 아니면 스킵
|
246
|
+
return false if (filter_value.blank? && !none_value_operator?(operator))
|
247
|
+
return false unless (include_entity_column?(columns, column_name))
|
248
|
+
return column_name, filter_value, operator
|
249
|
+
end
|
250
|
+
|
251
|
+
#
|
252
|
+
# filter name이 entity column내에 속해 있는지 확인한다.
|
253
|
+
#
|
254
|
+
def include_entity_column?(columns, filter_name)
|
255
|
+
fc = columns.find { |column| column.name == filter_name }
|
256
|
+
return !fc.nil?
|
257
|
+
end
|
258
|
+
|
259
|
+
#
|
260
|
+
# resource.name-eq 형식으로 넘어온 파라미터는 Resource.find_by_name(파라미터 값)으로 검색하여 id를 찾아 값을 대치하고 파라미터 명도 resource_id-eq로 대치
|
261
|
+
# TODO operator가 like 였을 경우 join query가 되어야 하고 파라미터 값은 join table의 검색 조건으로 변경되어야 한다.
|
262
|
+
#
|
263
|
+
def convert_reference_filter(column_name, filter_value, operator)
|
264
|
+
column_name_arr = column_name.split('.')
|
265
|
+
return column_name, filter_value, operator if(column_name_arr.size <= 1 || filter_value.blank?)
|
266
|
+
|
267
|
+
# 새로운 컬럼명 : {entityname}_id
|
268
|
+
new_column_name = "#{column_name_arr[0]}_id"
|
269
|
+
if(column_name_arr[1] == 'id')
|
270
|
+
return new_column_name, filter_value, operator
|
271
|
+
else
|
272
|
+
resource = column_name_arr[0].camelcase.constantize
|
273
|
+
conds = { column_name_arr[1].to_sym => filter_value }
|
274
|
+
#conds[:domain_id] = @domain.id if(@domain.respond_to?(resource.name.pluralize.to_sym))
|
275
|
+
instance = resource.where(conds).first
|
276
|
+
return new_column_name, (instance ? instance.id : ''), operator
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
#
|
281
|
+
# 넘어온 sort 정보로 부터 sort정보를 추출 - "[{"property":"name","direction":"DESC"}]"
|
282
|
+
#
|
283
|
+
def build_orders_by_sort_params(orders)
|
284
|
+
return (orders && !orders.empty?) ? orders.collect { |name, direction| "#{name} #{direction}"}.join(",") : ""
|
285
|
+
end
|
286
|
+
|
287
|
+
#
|
288
|
+
# 넘어온 sort parameter 정보로 부터 sort정보를 추출
|
289
|
+
#
|
290
|
+
def build_orders_by_sorters(sorter_str)
|
291
|
+
order_result = ""
|
292
|
+
if(sorter_str && !sorter_str.blank?)
|
293
|
+
sorters = JSON.parse(sorter_str)
|
294
|
+
order_result = sorters.collect { |sorter| "#{sorter['property']} #{sorter['direction']}" }.join(",")
|
295
|
+
end
|
296
|
+
return order_result
|
297
|
+
end
|
298
|
+
|
299
|
+
#
|
300
|
+
# params로 부터 pagination을 위한 정보를 추출한다.
|
301
|
+
#
|
302
|
+
def find_pagination_info
|
303
|
+
page = (params[:page] || 1).to_i
|
304
|
+
limit = (params[:limit] || GlobalConfig.default_page_size).to_i
|
305
|
+
offset = (page - 1) * limit
|
306
|
+
return page, limit, offset
|
307
|
+
end
|
308
|
+
|
309
|
+
#
|
310
|
+
# resource의 entity_columns 정보 중 select 필드를 바탕으로 관계 정보를 추출한다.
|
311
|
+
#
|
312
|
+
def find_association_list(resource, columns, options = {})
|
313
|
+
ref_columns = columns.select { |c| c.name != "domain_id" && c.ref_type == "Entity" && c.ref_name }
|
314
|
+
return ref_columns.collect do |column|
|
315
|
+
association_symbol = column.name.sub(/_id$/, '').to_sym
|
316
|
+
association = resource.reflect_on_association association_symbol
|
317
|
+
if association
|
318
|
+
association_symbol unless association.options[:polymorphic] == true
|
319
|
+
else
|
320
|
+
association = resource.reflect_on_all_associations.detect { |a| a.options[:foreign_key] == column.name.to_sym }
|
321
|
+
if association
|
322
|
+
association.name.to_sym
|
323
|
+
else
|
324
|
+
association = resource.reflect_on_all_associations.detect { |a| a.options[:class_name] == column.ref_name }
|
325
|
+
association.name.to_sym if association
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end.compact
|
329
|
+
end
|
330
|
+
|
331
|
+
end
|
332
|
+
end
|