edgarj 0.01.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +23 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/edgarj/base.js +49 -0
- data/app/assets/javascripts/edgarj/menu.js +39 -0
- data/app/assets/javascripts/edgarj/operator_selection.js +133 -0
- data/app/assets/stylesheets/edgarj/base.css +304 -0
- data/app/assets/stylesheets/edgarj/menu.css +65 -0
- data/app/controllers/edgarj/authentication_mixin.rb.sample +30 -0
- data/app/controllers/edgarj/controller_mixin_common.rb +80 -0
- data/app/controllers/edgarj/controller_mixin_for_app.rb +71 -0
- data/app/controllers/edgarj/edgarj_controller.rb +535 -0
- data/app/controllers/edgarj/model_permissions_controller.rb +8 -0
- data/app/controllers/edgarj/permission_mixin.rb +84 -0
- data/app/controllers/edgarj/popup_controller.rb +128 -0
- data/app/controllers/edgarj/rescue_mixin.rb +37 -0
- data/app/controllers/edgarj/user_group_users_controller.rb +8 -0
- data/app/controllers/edgarj/user_groups_controller.rb +9 -0
- data/app/controllers/edgarj/user_groups_popup_controller.rb +8 -0
- data/app/helpers/edgarj/assoc_helper.rb +369 -0
- data/app/helpers/edgarj/common_helper.rb +37 -0
- data/app/helpers/edgarj/edgarj_helper.rb +20 -0
- data/app/helpers/edgarj/field_helper.rb +397 -0
- data/app/helpers/edgarj/form_drawer.rb +322 -0
- data/app/helpers/edgarj/list_drawer.rb +169 -0
- data/app/helpers/edgarj/menu_helper.rb +92 -0
- data/app/helpers/edgarj/model_permissions_helper.rb +9 -0
- data/app/helpers/edgarj/popup_helper.rb +40 -0
- data/app/helpers/edgarj/search_helper.rb +14 -0
- data/app/helpers/edgarj/sessions_helper.rb +9 -0
- data/app/helpers/edgarj/user_group_users_helper.rb +9 -0
- data/app/helpers/edgarj/user_groups_helper.rb +9 -0
- data/app/helpers/edgarj/user_groups_popup_helper.rb +9 -0
- data/app/models/edgarj/drawer/base.rb +234 -0
- data/app/models/edgarj/drawer/normal.rb +6 -0
- data/app/models/edgarj/drawer/popup.rb +47 -0
- data/app/models/edgarj/drawer.rb +13 -0
- data/app/models/edgarj/model_permission.rb +41 -0
- data/app/models/edgarj/page_info.rb +47 -0
- data/app/models/edgarj/search.rb +81 -0
- data/app/models/edgarj/search_form.rb +255 -0
- data/app/models/edgarj/search_popup.rb +44 -0
- data/app/models/edgarj/sssn.rb +120 -0
- data/app/models/edgarj/user_group.rb +67 -0
- data/app/models/edgarj/user_group_user.rb +18 -0
- data/app/models/edgarj.rb +5 -0
- data/app/views/edgarj/edgarj/_form.html.erb +25 -0
- data/app/views/edgarj/edgarj/_list.html.erb +52 -0
- data/app/views/edgarj/edgarj/_message_popup.html.erb +15 -0
- data/app/views/edgarj/edgarj/_search_form.html.erb +64 -0
- data/app/views/edgarj/edgarj/_search_operator.html.erb +17 -0
- data/app/views/edgarj/edgarj/_search_operator_selection.html.erb +12 -0
- data/app/views/edgarj/edgarj/clear.js.erb +1 -0
- data/app/views/edgarj/edgarj/create.js.erb +4 -0
- data/app/views/edgarj/edgarj/destroy.js.erb +2 -0
- data/app/views/edgarj/edgarj/index.html.erb +37 -0
- data/app/views/edgarj/edgarj/index.js.erb +1 -0
- data/app/views/edgarj/edgarj/message_popup.js.erb +3 -0
- data/app/views/edgarj/edgarj/page_info_save.js.erb +1 -0
- data/app/views/edgarj/edgarj/search.js.erb +4 -0
- data/app/views/edgarj/edgarj/search_clear.js.erb +1 -0
- data/app/views/edgarj/edgarj/show.js.erb +1 -0
- data/app/views/edgarj/edgarj/top.html.erb +4 -0
- data/app/views/edgarj/edgarj/update.js.erb +4 -0
- data/app/views/edgarj/popup/_index.html.erb +16 -0
- data/app/views/edgarj/popup/_list.html.erb +42 -0
- data/app/views/edgarj/popup/_message_popup.html.erb +15 -0
- data/app/views/edgarj/popup/_search.html.erb +42 -0
- data/app/views/edgarj/popup/_search_save_popup.html.erb +16 -0
- data/app/views/edgarj/popup/index.js.erb +5 -0
- data/app/views/edgarj/popup/message_popup.js.erb +3 -0
- data/app/views/edgarj/popup/page_info_save.js.erb +1 -0
- data/app/views/edgarj/popup/search.js.erb +15 -0
- data/app/views/edgarj/popup/view_status_save.js.erb +1 -0
- data/config/routes.rb +15 -0
- data/config/settings.yml +5 -0
- data/db/migrate/20131118084600_create_edgar_sssns.rb +14 -0
- data/db/migrate/20131123124730_create_edgar_page_infos.rb +15 -0
- data/db/migrate/20140116062252_create_edgar_user_groups.rb +18 -0
- data/db/migrate/20140116062327_create_edgar_user_group_users.rb +10 -0
- data/db/migrate/20140206222308_create_edgar_model_permissions.rb +14 -0
- data/db/migrate/20141209053055_rename_edgar_to_edgarj.rb +17 -0
- data/lib/core_ext/active_record.rb +123 -0
- data/lib/core_ext/resources.rb +71 -0
- data/lib/edgarj/engine.rb +64 -0
- data/lib/edgarj/enum_cache.rb +46 -0
- data/lib/edgarj/templates/rails/helper/helper.rb +10 -0
- data/lib/edgarj/templates/test_unit/scaffold/functional_test.rb +575 -0
- data/lib/edgarj/version.rb +3 -0
- data/lib/edgarj.rb +14 -0
- data/lib/generators/edgarj/popup_scaffold/USAGE +6 -0
- data/lib/generators/edgarj/popup_scaffold/popup_scaffold_generator.rb +35 -0
- data/lib/generators/edgarj/popup_scaffold/templates/controller.rb +13 -0
- data/lib/generators/edgarj/popup_scaffold/templates/functional_test.rb +197 -0
- data/lib/generators/edgarj/popup_scaffold/templates/helper.rb +9 -0
- data/lib/generators/edgarj/scaffold/USAGE +17 -0
- data/lib/generators/edgarj/scaffold/scaffold_generator.rb +40 -0
- data/lib/generators/edgarj/scaffold/templates/controller.rb +13 -0
- data/lib/tasks/edgarj_tasks.rake +32 -0
- data/lib/tasks/pakcage.rake +18 -0
- data/locale/en.yml +94 -0
- data/locale/ja.yml +100 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +21 -0
- data/test/dummy/app/assets/javascripts/authors.js +2 -0
- data/test/dummy/app/assets/stylesheets/application.css +16 -0
- data/test/dummy/app/assets/stylesheets/authors.css +4 -0
- data/test/dummy/app/assets/stylesheets/scaffold.css +56 -0
- data/test/dummy/app/controllers/application_controller.rb +15 -0
- data/test/dummy/app/controllers/authors_controller.rb +6 -0
- data/test/dummy/app/controllers/authors_popup_controller.rb +6 -0
- data/test/dummy/app/controllers/books_controller.rb +6 -0
- data/test/dummy/app/controllers/dummy_auth_mixin.rb +36 -0
- data/test/dummy/app/decorators/models/edgarj/user_group_decorator.rb +1 -0
- data/test/dummy/app/helpers/application_helper.rb +3 -0
- data/test/dummy/app/helpers/authors_helper.rb +7 -0
- data/test/dummy/app/helpers/authors_popup_helper.rb +7 -0
- data/test/dummy/app/helpers/books_helper.rb +7 -0
- data/test/dummy/app/models/author.rb +32 -0
- data/test/dummy/app/models/book.rb +5 -0
- data/test/dummy/app/models/user.rb +13 -0
- data/test/dummy/app/views/layouts/application.html.erb +32 -0
- data/test/dummy/app/views/layouts/login.html.erb +20 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +15 -0
- data/test/dummy/config/edgarj/menu_config.rb +28 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +42 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +34 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/strong_parameter.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +26 -0
- data/test/dummy/config/routes.rb +60 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/migrate/20131107120635_create_authors.rb +9 -0
- data/test/dummy/db/migrate/20131218011851_create_books.rb +10 -0
- data/test/dummy/db/migrate/20140201000000_add_user_group_id_to_authors.rb +5 -0
- data/test/dummy/db/migrate/20140807065420_create_users.rb +10 -0
- data/test/dummy/db/schema.rb +93 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/test/functional/authors_controller_test.rb +631 -0
- data/test/dummy/test/functional/books_controller_test.rb +516 -0
- data/test/dummy/test/helpers/authors_helper_test.rb +4 -0
- data/test/dummy/test/unit/author_test.rb +7 -0
- data/test/dummy/test/unit/book_test.rb +7 -0
- data/test/edgar_test.rb +7 -0
- data/test/fixtures/authors.yml +32 -0
- data/test/fixtures/books.yml +56 -0
- data/test/fixtures/edgarj/model_permissions.yml +97 -0
- data/test/fixtures/edgarj/page_infos.yml +84 -0
- data/test/fixtures/edgarj/sssns.yml +38 -0
- data/test/fixtures/edgarj/user_group_users.yml +114 -0
- data/test/fixtures/edgarj/user_groups.yml +95 -0
- data/test/fixtures/users.yml +49 -0
- data/test/functional/edgarj/edgarj_controller_test.rb +24 -0
- data/test/functional/edgarj/model_permissions_controller_test.rb +554 -0
- data/test/functional/edgarj/user_group_users_controller_test.rb +567 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/support/edgarj/controller_supporter.rb +23 -0
- data/test/test_helper.rb +23 -0
- data/test/unit/edgarj/model_permission_test.rb +27 -0
- data/test/unit/edgarj/page_info_test.rb +7 -0
- data/test/unit/edgarj/sssn_test.rb +10 -0
- data/test/unit/edgarj/user_group_test.rb +32 -0
- data/test/unit/edgarj/user_group_user_test.rb +9 -0
- data/test/unit/helpers/edgarj/model_permissions_helper_test.rb +6 -0
- data/test/unit/helpers/edgarj/user_group_users_helper_test.rb +6 -0
- metadata +456 -0
@@ -0,0 +1,234 @@
|
|
1
|
+
module Edgarj
|
2
|
+
module Drawer
|
3
|
+
# 'Mediator' to draw list and form of the model on the view.
|
4
|
+
class Base
|
5
|
+
attr_accessor :vc
|
6
|
+
|
7
|
+
# * options
|
8
|
+
# * list_drawer_options - options for Edgarj::ListDrawer::Normal
|
9
|
+
# * draw_form_options - options for draw_form_options
|
10
|
+
def initialize(view_context, params, page_info, model, options={})
|
11
|
+
@vc = view_context
|
12
|
+
@params = params
|
13
|
+
@page_info = page_info
|
14
|
+
@model = model
|
15
|
+
@options = options.dup
|
16
|
+
end
|
17
|
+
|
18
|
+
# level-1 methods which may be modified most frequently:
|
19
|
+
|
20
|
+
# define model-wide default columns for view.
|
21
|
+
#
|
22
|
+
# If you need to customize, overwrite it at derived model class.
|
23
|
+
# Example:
|
24
|
+
# def columns
|
25
|
+
# %w(id name email updated_at)
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# === SEE ALSO
|
29
|
+
# list_columns:: define list columns
|
30
|
+
# form_columns:: define form columns
|
31
|
+
# search_form_columns:: define search form columns
|
32
|
+
def columns
|
33
|
+
@model.columns.map{|c| c.name}
|
34
|
+
end
|
35
|
+
|
36
|
+
# This defines list columns.
|
37
|
+
# You can overwrite this method at each model if it is different from
|
38
|
+
# columns. Default is calling columns().
|
39
|
+
#
|
40
|
+
# === SEE ALSO
|
41
|
+
# columns:: define default columns
|
42
|
+
# form_columns:: define form columns
|
43
|
+
# search_form_columns:: define search form columns
|
44
|
+
#
|
45
|
+
def list_columns
|
46
|
+
columns
|
47
|
+
end
|
48
|
+
|
49
|
+
# This defines form columns.
|
50
|
+
# You can overwrite this method at each model if it is different from
|
51
|
+
# columns. Default is calling columns().
|
52
|
+
#
|
53
|
+
# === SEE ALSO
|
54
|
+
# columns:: define default columns
|
55
|
+
# list_columns:: define list columns
|
56
|
+
# search_form_columns:: define search form columns
|
57
|
+
#
|
58
|
+
def form_columns
|
59
|
+
columns
|
60
|
+
end
|
61
|
+
|
62
|
+
# This defines search-form columns.
|
63
|
+
# You can overwrite this method at each model if it is different from
|
64
|
+
# columns. Default is calling columns().
|
65
|
+
#
|
66
|
+
# === SEE ALSO
|
67
|
+
# columns:: define default columns
|
68
|
+
# list_columns:: define list columns
|
69
|
+
# form_columns:: define form columns
|
70
|
+
#
|
71
|
+
def search_form_columns
|
72
|
+
columns
|
73
|
+
end
|
74
|
+
|
75
|
+
# level-2 methods which may be modified occasionally:
|
76
|
+
|
77
|
+
# This defines popup path for the column on the model.
|
78
|
+
#
|
79
|
+
# Default returns parent model's popup-controller.
|
80
|
+
# For example, book.author_id -> 'authors_popup' path
|
81
|
+
#
|
82
|
+
# You can overwrite this method at each model if it is different from
|
83
|
+
# columns.
|
84
|
+
#
|
85
|
+
# @see popup_path_on_search popup path for the column on the model's search form
|
86
|
+
def popup_path(col)
|
87
|
+
parent_model = @model.belongs_to_AR(col)
|
88
|
+
raise 'Parent is nil' if !parent_model
|
89
|
+
|
90
|
+
popup_field = PopupHelper::PopupField.new_builder(@model.model_name.param_key, col.name)
|
91
|
+
@vc.main_app.url_for(
|
92
|
+
controller: parent_model.model_name.collection + '_popup',
|
93
|
+
id_target: popup_field.id_target)
|
94
|
+
end
|
95
|
+
|
96
|
+
# This defines popup path for the search column on the model.
|
97
|
+
#
|
98
|
+
# Default returns parent model's popup-controller with id_target
|
99
|
+
# on the search column.
|
100
|
+
#
|
101
|
+
# @see popup_path popup path for the column on the model itself
|
102
|
+
def popup_path_on_search(col)
|
103
|
+
parent_model = @model.belongs_to_AR(col)
|
104
|
+
raise 'Parent is nil' if !parent_model
|
105
|
+
|
106
|
+
popup_field = PopupHelper::PopupField.new_builder(Edgarj::SearchForm.model_name.param_key, col.name)
|
107
|
+
@vc.main_app.url_for(
|
108
|
+
controller: parent_model.model_name.collection + '_popup',
|
109
|
+
id_target: popup_field.id_target)
|
110
|
+
end
|
111
|
+
|
112
|
+
# draw sort link on list column header
|
113
|
+
#
|
114
|
+
# === INPUTS
|
115
|
+
# col:: column data
|
116
|
+
# options:: options to url_for
|
117
|
+
def draw_sort(col, options={})
|
118
|
+
label = @model.human_attribute_name(col.name)
|
119
|
+
dir = 'asc'
|
120
|
+
if @page_info.order_by == fullname(col)
|
121
|
+
# toggle direction
|
122
|
+
if @page_info.dir == 'asc' || @page_info.dir.blank?
|
123
|
+
label += '▲'
|
124
|
+
dir = 'desc'
|
125
|
+
else
|
126
|
+
label += '▼'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
@vc.link_to(label,
|
130
|
+
{
|
131
|
+
:controller => @params[:controller],
|
132
|
+
:action => 'page_info_save',
|
133
|
+
:id => @page_info.id,
|
134
|
+
'edgarj_page_info[order_by]' => fullname(col),
|
135
|
+
'edgarj_page_info[dir]' => dir
|
136
|
+
}.merge(options),
|
137
|
+
:remote => true,
|
138
|
+
:method => :put)
|
139
|
+
end
|
140
|
+
|
141
|
+
# draw list column header for both usual list and popup list
|
142
|
+
def draw_list_column_header(col, options={})
|
143
|
+
parent = @model.belongs_to_AR(col)
|
144
|
+
if parent then
|
145
|
+
@vc.draw_belongs_to_label_sub(@model, col.name, parent)
|
146
|
+
else
|
147
|
+
draw_sort(col, options)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def list_drawer_class
|
152
|
+
Edgarj::ListDrawer::Normal
|
153
|
+
end
|
154
|
+
|
155
|
+
def draw_list(list)
|
156
|
+
line_color = 1
|
157
|
+
d = list_drawer_class.new(
|
158
|
+
self,
|
159
|
+
@options[:list_drawer_options] || {})
|
160
|
+
|
161
|
+
@vc.content_tag(:table, width: '100%', class: 'list') do
|
162
|
+
@vc.content_tag(:tr) do
|
163
|
+
''.html_safe.tap do |result|
|
164
|
+
for col in columns_for(list_columns) do
|
165
|
+
result << @vc.content_tag(:th) do
|
166
|
+
draw_list_column_header(col)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end +
|
171
|
+
''.html_safe.tap do |trs|
|
172
|
+
for rec in list do
|
173
|
+
line_color = 1 - line_color
|
174
|
+
d.set_path(rec)
|
175
|
+
trs << @vc.content_tag(:tr, class: "list_line#{line_color}") do
|
176
|
+
''.html_safe.tap do |cols|
|
177
|
+
for col in columns_for(list_columns) do
|
178
|
+
cols << d.draw_column(rec, col)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# return table_name + col.name
|
188
|
+
def fullname(col)
|
189
|
+
@model.table_name + '.' + col.name
|
190
|
+
end
|
191
|
+
|
192
|
+
def form_drawer_class
|
193
|
+
Edgarj::FormDrawer::Base
|
194
|
+
end
|
195
|
+
|
196
|
+
def draw_form(record)
|
197
|
+
url_hash = {
|
198
|
+
controller: @params[:controller],
|
199
|
+
action: record.new_record? ? 'create' : 'update',
|
200
|
+
}
|
201
|
+
url_hash[:id] = record.id if record.persisted?
|
202
|
+
@vc.form_for(record,
|
203
|
+
remote: true,
|
204
|
+
url: url_hash,
|
205
|
+
html: {
|
206
|
+
id: '_edgarj_form',
|
207
|
+
method: record.new_record? ? 'post' : 'put',
|
208
|
+
multipart: true,
|
209
|
+
#target: 'edgarj_form_frame'
|
210
|
+
}) do |f|
|
211
|
+
form_drawer_class.new(self, record, f).draw() +
|
212
|
+
|
213
|
+
# to avoid submit on 1-textfield form when hit [ENTER] key
|
214
|
+
'<input type="text" name="dummy" style="visibility:hidden" size=0>'.html_safe
|
215
|
+
end +
|
216
|
+
@vc.draw_form_buttons(@options[:draw_form_options] || {})
|
217
|
+
end
|
218
|
+
|
219
|
+
# return array of model columns (ActiveRecord::ConnectionAdapters::X_Column type).
|
220
|
+
#
|
221
|
+
# === INPUTS
|
222
|
+
# column_name_list:: column name list
|
223
|
+
def columns_for(column_name_list)
|
224
|
+
[].tap do |result|
|
225
|
+
for col_name in column_name_list do
|
226
|
+
if (col = @model.columns_hash[col_name])
|
227
|
+
result << col
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Edgarj
|
2
|
+
module Drawer
|
3
|
+
# PopupDrawer is the same as Drawer to draw 'belongs_to' model
|
4
|
+
# to popup window.
|
5
|
+
#
|
6
|
+
# For example, AuthorPopupDrawer is to draw Author popup,
|
7
|
+
# which is called from Book page.
|
8
|
+
#
|
9
|
+
# * options
|
10
|
+
# * list_drawer_options - options for Edgarj::ListDrawer::Normal
|
11
|
+
class Popup < Base
|
12
|
+
def draw_list(list)
|
13
|
+
line_color = 1
|
14
|
+
d = Edgarj::ListDrawer::Normal.new(
|
15
|
+
self,
|
16
|
+
@options[:list_drawer_options] || {})
|
17
|
+
|
18
|
+
@vc.content_tag(:table, width: '100%', class: 'list') do
|
19
|
+
@vc.content_tag(:tr) do
|
20
|
+
''.html_safe.tap do |result|
|
21
|
+
for col in columns_for(list_columns) do
|
22
|
+
result << @vc.content_tag(:th) do
|
23
|
+
draw_list_column_header(col, id_target: @params[:id_target])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end +
|
28
|
+
''.html_safe.tap do |trs|
|
29
|
+
for rec in list do
|
30
|
+
line_color = 1 - line_color
|
31
|
+
d.set_path(rec)
|
32
|
+
trs << @vc.content_tag(:tr,
|
33
|
+
class: "list_line#{line_color} edgarj_popup_list_row",
|
34
|
+
data: {id: rec.id, name: rec.name}) do
|
35
|
+
''.html_safe.tap do |cols|
|
36
|
+
for col in columns_for(list_columns) do
|
37
|
+
cols << d.draw_column(rec, col)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Edgarj
|
2
|
+
# Drawer is a 'presentor' and it is similar to decorator (like Draper),
|
3
|
+
# but this simply connects model to view in order to have view-related
|
4
|
+
# information for the model (or, to isolate view-related information
|
5
|
+
# from the model), while decorator inherits both model and
|
6
|
+
# view.
|
7
|
+
module Drawer
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'edgarj/drawer/base'
|
12
|
+
require 'edgarj/drawer/normal'
|
13
|
+
require 'edgarj/drawer/popup'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Model-wide CRUD permission for role. In other words,
|
2
|
+
# CRUD permission for each model for each role is defined by this.
|
3
|
+
#
|
4
|
+
# This permission is used for two purposes:
|
5
|
+
#
|
6
|
+
# 1. page access permission
|
7
|
+
# * If this object,which relates to a model by model-attribute, exists and
|
8
|
+
# user belongs to the role (= user-group), then the controller,
|
9
|
+
# which 'model_class' method returns the model, can be accessed.
|
10
|
+
# 1. popup access permission
|
11
|
+
# * Popup access for a model-class is an read-permission for that.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# 1. User 'u' belongs to 'x-role' Edgarj::UserGroup.
|
15
|
+
# 1. x-role has author model permission.
|
16
|
+
# 1. User 'u' can access AuthorController page.
|
17
|
+
# 1. If x-role has READ permission on author model, then
|
18
|
+
# user 'u' can see author-popup on any 'belongs_to' related page
|
19
|
+
# (e.g. BookController book form's author-popup).
|
20
|
+
module Edgarj
|
21
|
+
class ModelPermission < ActiveRecord::Base
|
22
|
+
self.table_name = 'edgarj_model_permissions'
|
23
|
+
belongs_to :user_group
|
24
|
+
|
25
|
+
# define bitset on 'flags' column
|
26
|
+
module FlagsBitset
|
27
|
+
CREATE = 0x01
|
28
|
+
READ = 0x02
|
29
|
+
UPDATE = 0x04
|
30
|
+
DELETE = 0x08
|
31
|
+
end
|
32
|
+
FLAGS_ALL = FlagsBitset.constants.inject(0){|sum, flag|
|
33
|
+
sum += FlagsBitset.const_get(flag)
|
34
|
+
}
|
35
|
+
|
36
|
+
# return true if *ALL* requested flags are included in flags
|
37
|
+
def permitted?(requested_flags)
|
38
|
+
(self.flags & requested_flags) == requested_flags
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Edgarj
|
2
|
+
class PageInfo < ActiveRecord::Base
|
3
|
+
self.table_name = 'edgarj_page_infos'
|
4
|
+
|
5
|
+
belongs_to :sssn
|
6
|
+
|
7
|
+
def self.intern(sssn, view, search_obj)
|
8
|
+
if !sssn || !(page_info = sssn.page_infos.find_by_view(view))
|
9
|
+
page_info = sssn.page_infos.build(
|
10
|
+
view: view,
|
11
|
+
lines: 10,
|
12
|
+
order_by: '',
|
13
|
+
dir: '',
|
14
|
+
page: 1)
|
15
|
+
page_info.record = search_obj
|
16
|
+
|
17
|
+
# save it to get id since id will be used later e.g.
|
18
|
+
# @vs.link_to(... @page_info.id) in Edgarj::Drawer::Base#draw_sort
|
19
|
+
page_info.save!
|
20
|
+
end
|
21
|
+
page_info
|
22
|
+
end
|
23
|
+
|
24
|
+
# serialize model and set it to model_data
|
25
|
+
#
|
26
|
+
def record=(record)
|
27
|
+
self.record_data = Base64.encode64(Marshal.dump(record))
|
28
|
+
end
|
29
|
+
|
30
|
+
# de-serialize in model_data and return it
|
31
|
+
#
|
32
|
+
def record
|
33
|
+
if self.record_data
|
34
|
+
# FIXME: Following code fixes the error:
|
35
|
+
# - ArgumentError (undefined class/module Search)
|
36
|
+
# - ArgumentError (undefined class/module SearchForm)
|
37
|
+
#
|
38
|
+
# But some autoload may smartlier fixes this?
|
39
|
+
Search
|
40
|
+
SearchForm
|
41
|
+
Marshal.load(Base64.decode64(self.record_data))
|
42
|
+
else
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Edgarj
|
2
|
+
# Search condition
|
3
|
+
#
|
4
|
+
# Abstract class to SearchForm and SearchPopup to provide common method
|
5
|
+
# 'conditions'.
|
6
|
+
#
|
7
|
+
# 'Search' instance will be stored in view_status.model.
|
8
|
+
#
|
9
|
+
# \@errors will be used for error_messages_for helper in search-form.
|
10
|
+
class Search
|
11
|
+
# required at 'form_for' helper
|
12
|
+
extend ActiveModel::Naming
|
13
|
+
extend ActiveModel::Conversion
|
14
|
+
# include ActiveModel::Conversion ??
|
15
|
+
include ActiveModel::Validations
|
16
|
+
|
17
|
+
# to support 'human_attribute_name'
|
18
|
+
extend ActiveModel::Translation
|
19
|
+
|
20
|
+
# cache the map: column name -> column type
|
21
|
+
#
|
22
|
+
# SearchForm instance is serialized to be stored at session so that
|
23
|
+
# another class (=Cache) is introduced to store cache information.
|
24
|
+
class Cache
|
25
|
+
include Singleton
|
26
|
+
|
27
|
+
attr_accessor :klass_hash, :hit, :miss
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@klass_hash = {}
|
31
|
+
|
32
|
+
# for cache statistics
|
33
|
+
@hit = 0
|
34
|
+
@miss = 0
|
35
|
+
end
|
36
|
+
|
37
|
+
# report hit rate
|
38
|
+
def klass_hash_report
|
39
|
+
sprintf("%d/%d", @hit, @hit + @miss)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_accessor :errors, :_klass_str
|
44
|
+
|
45
|
+
def initialize(klass)
|
46
|
+
@errors = ActiveModel::Errors.new(self)
|
47
|
+
@_klass_str = klass.to_s
|
48
|
+
end
|
49
|
+
|
50
|
+
# generate search-conditions from ActiveRecord attributes
|
51
|
+
#
|
52
|
+
# === RETURN
|
53
|
+
# [condition_string, value_array]:: values for :conditions option on model
|
54
|
+
def conditions
|
55
|
+
raise "Not implemented"
|
56
|
+
end
|
57
|
+
|
58
|
+
def persisted?
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
# cache column type
|
64
|
+
def column_type(col_name)
|
65
|
+
cache = Cache.instance
|
66
|
+
cache.klass_hash[@_klass_str] ||= {}
|
67
|
+
if v = cache.klass_hash[@_klass_str][col_name.to_s]
|
68
|
+
cache.hit += 1
|
69
|
+
v
|
70
|
+
else
|
71
|
+
cache.miss += 1
|
72
|
+
col = @_klass_str.constantize.columns.find{|c|
|
73
|
+
c.name == col_name.to_s
|
74
|
+
}
|
75
|
+
if col
|
76
|
+
cache.klass_hash[@_klass_str][col_name.to_s] = col.type
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|