Class: Edgarj::EdgarjController
- Inherits:
-
ApplicationController
- Object
- ApplicationController
- Edgarj::EdgarjController
- Includes:
- ControllerMixinCommon, PermissionMixin
- Defined in:
- app/controllers/edgarj/edgarj_controller.rb
Overview
Generic CRUD(Create/Read/Update/Delte) controller with Ajax.
EdgarjController v.s. ApplicationController
When concreate controller (e.g. CustomersController) inherits EdgarjController, it has the following features:
-
CRUD with default form on Ajax
-
form can be customized.
-
-
QBE (Query By Example) search form
-
popup-selection on ‘belongs_to’ column
-
sort on list
-
saving search-conditions and reuse it
If these are not necessary, just inherits ApplicationController.
Tasks when adding new model which is handled under EdgarjController
For example, when want to add Post model:
-
generate edgarj:scaffold:
rails generate edgarj:scaffold post name:string body:text published:boolean
-
add controller entry to CONTROLLER_MENU (config/initializers/edgarj.rb)
It will take about ~3 min.
For the detail of customization, please see:
http://sourceforge.net/apps/trac/jjedgarj/wiki/customize
Architecture
see architecture (OpenOffice Presentation)
Access Control
There are two dimentions of access control:
-
Page level (Controller level) access control.
-
Edgarj::UserGroup with kind==ROLE and Edgarj::ModelPermission
represents access control on each controller.
-
Admin user, who belongs to ‘admin’ user_group, can access any page.
-
When a user belongs to a user_group (kind==ROLE) and a model_permission belongs to the user_group, the user can access the controller which model is the model in model_permission.
-
More precisely, 4 kind of access controls, CREATE, READ, UPDATE, and DELETE can be set with any conbination on the controller.
-
See Edgarj::ModelPermission for more detail.
-
-
Data scope.
-
data scope access is controlled by ‘user_scoped(user, context)’ scope defined at each model.
-
Where, user is currently accessing person to the model.
-
context is any kind of 2nd parameter. Default is session object of Edgarj::Sssn, but it can be overwritten ‘scope_context’ method at the target controller.
-
See Author.user_scoped as an example.
-
Naming Convention
-
‘record’ is an instance of ‘Model’.
-
‘drawer’ is an instance of ‘Drawer’ class.
Implementation Note
Why not to choose mixin rather than class is because it is easier to use edgarj’s view at client controller. For example, AuthorsController, which inherits from EdgarjController, can automatically use edgarj’s view by rails view-selection feature.
SEE ALSO
- PopupController
-
‘belongs_to’ popup for EdgarjController
Direct Known Subclasses
ModelPermissionsController, UserGroupUsersController, UserGroupsController
Constant Summary collapse
- READ_ACTIONS =
%w( index show clear search search_clear search_save search_load zip_complete csv_download file_download map page_info_save)
Instance Method Summary collapse
-
#clear ⇒ Object
Ajax method to clear form.
-
#create ⇒ Object
save new record.
-
#csv_download ⇒ Object
download model under current condition.
-
#destroy ⇒ Object
Permission ModelPermission::DELETE on this controller is required.
-
#file_download ⇒ Object
To prevent unassociated file access, do:.
-
#index ⇒ Object
draw search result in whole page.
-
#map ⇒ Object
draw Google map.
-
#search ⇒ Object
Ajax method to execute search.
-
#search_clear ⇒ Object
Ajax method to clear search conditions.
-
#search_load ⇒ Object
Ajax method to load search condition, lines, order_by, dir, and page.
-
#search_save ⇒ Object
Ajax method to save search conditions.
-
#show ⇒ Object
Show detail of one record.
-
#top ⇒ Object
This page is for following purposes:.
-
#update ⇒ Object
save existence modified record.
Methods included from PermissionMixin
Methods included from ControllerMixinCommon
Instance Method Details
#clear ⇒ Object
Ajax method to clear form
Permission
ModelPermission::READ on this controller is required.
208 209 210 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 208 def clear @record = model.new end |
#create ⇒ Object
save new record
Permission
ModelPermission::CREATE on this controller is required.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 134 def create upsert do # NOTE: create!() is not used because assign to @record to draw form. # Otherwise, @record would be in nil so failure at edgarj/_form rendering. # # NOTE2: valid? after create() calls validate_on_update. This is not # an expected behavior. So, new, valid?, then save. @record = model.new(permitted_params(:create)) @record_saved = @record # copy for possible later use on_upsert #upsert_files raise ActiveRecord::RecordNotSaved if !@record.valid? @record.save # clear @record values for next data-entry @record = model.new end end |
#csv_download ⇒ Object
download model under current condition
respond_to...format.csv
approach was not used since @list is different as follows:
-
csv returns all of records under the conditions
-
HTML returns just in specified ‘page’.
Permission
ModelPermission::READ on this controller is required.
FIXME: file.close(true) deletes files BEFORE actually send file so that comment it out. Need to clean these work files.
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 329 def csv_download dir = '/tmp/edgarj/csv_download' FileUtils.mkdir_p(dir) filename = sprintf("%s-%s.csv", model_name, Time.now.strftime("%Y%m%d-%H%M%S")) file = Tempfile.new(filename, dir) csv_visitor = EdgarjHelper::CsvVisitor.new(view_context) file.write CSV.generate_line(model.columns.map{|c| c.name}) for rec in user_scoped.where(page_info.record.conditions). order( page_info.order_by.blank? ? nil : page_info.order_by + ' ' + page_info.dir) do array = [] for col in model.columns do array << csv_visitor.visit_column(rec, col) end file.write CSV.generate_line(array) end file.close send_file(file.path, { type: 'text/csv', filename: filename}) #file.close(true) end |
#destroy ⇒ Object
Permission
ModelPermission::DELETE on this controller is required.
193 194 195 196 197 198 199 200 201 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 193 def destroy m = model.find(user_scoped.find(params[:id]).id) @record_saved = m # copy for possible later use m.destroy prepare_list @record = model.new @flash_notice = t('delete_ok') end |
#file_download ⇒ Object
To prevent unassociated file access, do:
-
check if it is in model object
-
check if it is a edgarj_file column
Permission
ModelPermission::READ on this controller is required.
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 364 def file_download if !model.edgarj_file?(params[:column]) flash[:error] = t('edgarj_file.no_assoc') return end file_info_id = user_scoped.find(params[:id]).send(params[:column]) if file_info_id file_info = FileInfo.find(file_info_id) if file_info send_file(file_info.full_filename, :filename => file_info.filename) return end end logger.warn 'invalid file_info' end |
#index ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 112 def index page_info # update @page_info.page when page is specified. # Otherwise, reset page to 1. # # Just set, not save. It will be done later when saving sssn with # 'has_many page_infos ... autosave: true' @page_info.page = (params[:page] || 1) #clear_topic_path prepare_list @search = page_info.record @record = model.new end |
#map ⇒ Object
draw Google map.
Permission
ModelPermission::READ on this controller is required.
386 387 388 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 386 def map render :template=>'edgarj/map', :layout=>false end |
#search ⇒ Object
Ajax method to execute search
Actually, this doesn’t execute search. Rather, this just saves condition. Search will be executed at any listing action like ‘index’, ‘create’, or ‘update’.
Permission
ModelPermission::READ on this controller is required.
221 222 223 224 225 226 227 228 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 221 def search pi = page_info pi.record = SearchForm.new(model, params[:edgarj_search_form]) pi.page = 1 pi.save! @search = pi.record prepare_list if @search.valid? end |
#search_clear ⇒ Object
Ajax method to clear search conditions
Permission
ModelPermission::READ on this controller is required.
235 236 237 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 235 def search_clear @search = SearchForm.new(model) end |
#search_load ⇒ Object
Ajax method to load search condition, lines, order_by, dir, and page.
278 279 280 281 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 278 def search_load @search = current_user.saved_page_infos.find(params[:id]).load(@sssn).model draw_search_form end |
#search_save ⇒ Object
Ajax method to save search conditions
call flow
Edgarj.SearchSavePopup.open() (javascript)
(show $('search_save_popup'))
Edgarj.SearchSavePopup.submit() (javascript)
(copy entered name into $('saved_page_info_name') in form)
call :action=>'search_save'
TRICKY PART
There are two requirements:
-
use modal-dialog to enter name to decrese busy in search form.
-
send Search Form with name to server.
To comply these, Edgarj.SearchSavePopup copies the entered name to ‘saved_page_info_name’ hidden field and then sends the form which includes the copied name.
Permission
ModelPermission::READ on this controller is required.
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 260 def search_save SavedVcontext.save(current_user, nil, params[:saved_page_info_name], page_info) render :update do |page| page << "Edgarj.SearchSavePopup.close();" page.replace 'edgarj_load_condition_menu', :partial=>'edgarj/load_condition_menu' end rescue ActiveRecord::ActiveRecordError app_rescue render :update do |page| page.replace_html 'search_save_popup_flash_error', :text=>t('save_fail') end end |
#show ⇒ Object
Show detail of one record. Format of html & js should be supported.
Permission
ModelPermission::READ on this controller is required.
158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 158 def show @record = user_scoped.find(params[:id]) #add_topic_path respond_to do |format| format.html { prepare_list @search = page_info.record render :action=>'index' } format.js end end |
#top ⇒ Object
This page is for following purposes:
-
top page which contain latest info (TBD)
-
any error message on HTML format access
-
on Ajax access, rather edgarj_error_popup is used
-
95 96 97 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 95 def top render :action => 'top' end |
#update ⇒ Object
save existence modified record
Permission
ModelPermission::UPDATE on this controller is required.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'app/controllers/edgarj/edgarj_controller.rb', line 176 def update upsert do # NOTE: # 1. update ++then++ valid to set new values in @record to draw form. # 1. user_scoped may have joins so that record could be # ActiveRecord::ReadOnlyRecord so that's why access again from # model. @record = model.find(user_scoped.find(params[:id]).id) #upsert_files if !@record.update_attributes(permitted_params(:update)) raise ActiveRecord::RecordInvalid.new(@record) end end end |