active_scaffold 3.0.23 → 3.0.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/frontends/default/views/_action_group.html.erb +1 -1
  2. data/frontends/default/views/_action_group.html.erb~ +24 -0
  3. data/frontends/default/views/_form.html.erb~ +26 -0
  4. data/frontends/default/views/_form_association.html.erb~ +19 -0
  5. data/frontends/default/views/_form_association_footer.html.erb~ +16 -6
  6. data/frontends/default/views/_horizontal_subform.html.erb~ +29 -0
  7. data/frontends/default/views/_horizontal_subform_header.html.erb~ +3 -2
  8. data/frontends/default/views/_list_actions.html.erb~ +15 -0
  9. data/frontends/default/views/_list_inline_adapter.html.erb~ +10 -0
  10. data/frontends/default/views/_list_messages.html.erb~ +30 -0
  11. data/frontends/default/views/_list_pagination.html.erb~ +11 -0
  12. data/frontends/default/views/_list_pagination_links.html.erb~ +0 -0
  13. data/frontends/default/views/_render_field.js.erb~ +23 -0
  14. data/frontends/default/views/_row.html.erb~ +6 -0
  15. data/frontends/default/views/_vertical_subform.html.erb~ +12 -0
  16. data/frontends/default/views/edit_associated.js.erb~ +13 -0
  17. data/frontends/default/views/on_create.js.rjs +2 -2
  18. data/frontends/default/views/render_field.js.erb~ +1 -0
  19. data/lib/active_scaffold/actions/core.rb~ +13 -5
  20. data/lib/active_scaffold/actions/create.rb~ +149 -0
  21. data/lib/active_scaffold/actions/list.rb~ +196 -0
  22. data/lib/active_scaffold/actions/nested.rb +6 -2
  23. data/lib/active_scaffold/actions/nested.rb~ +252 -0
  24. data/lib/active_scaffold/actions/search.rb~ +49 -0
  25. data/lib/active_scaffold/actions/subform.rb~ +27 -0
  26. data/lib/active_scaffold/actions/update.rb~ +149 -0
  27. data/lib/active_scaffold/attribute_params.rb~ +202 -0
  28. data/lib/active_scaffold/bridges/record_select/{lib/record_select_bridge.rb~ → helpers.rb~} +7 -16
  29. data/lib/active_scaffold/bridges/shared/date_bridge.rb~ +209 -0
  30. data/lib/active_scaffold/config/create.rb +4 -4
  31. data/lib/active_scaffold/config/nested.rb +1 -0
  32. data/lib/active_scaffold/config/nested.rb~ +41 -0
  33. data/lib/active_scaffold/config/search.rb~ +74 -0
  34. data/lib/active_scaffold/constraints.rb~ +186 -0
  35. data/lib/active_scaffold/data_structures/action_columns.rb~ +140 -0
  36. data/lib/active_scaffold/data_structures/action_link.rb +4 -4
  37. data/lib/active_scaffold/data_structures/action_link.rb~ +179 -0
  38. data/lib/active_scaffold/data_structures/nested_info.rb~ +124 -0
  39. data/lib/active_scaffold/extensions/action_controller_rendering.rb~ +22 -0
  40. data/lib/active_scaffold/extensions/action_view_rendering.rb~ +108 -0
  41. data/lib/active_scaffold/extensions/cache_association.rb~ +12 -0
  42. data/lib/active_scaffold/extensions/reverse_associations.rb~ +64 -0
  43. data/lib/active_scaffold/extensions/routing_mapper.rb~ +34 -0
  44. data/lib/active_scaffold/extensions/unsaved_associated.rb~ +62 -0
  45. data/lib/active_scaffold/finder.rb~ +370 -0
  46. data/lib/active_scaffold/helpers/controller_helpers.rb~ +101 -0
  47. data/lib/active_scaffold/helpers/form_column_helpers.rb~ +321 -0
  48. data/lib/active_scaffold/helpers/id_helpers.rb~ +123 -0
  49. data/lib/active_scaffold/helpers/list_column_helpers.rb +9 -6
  50. data/lib/active_scaffold/helpers/list_column_helpers.rb~ +368 -0
  51. data/lib/active_scaffold/helpers/search_column_helpers.rb~ +94 -46
  52. data/lib/active_scaffold/helpers/view_helpers.rb +1 -1
  53. data/lib/active_scaffold/helpers/view_helpers.rb~ +353 -0
  54. data/lib/active_scaffold/version.rb +1 -1
  55. data/lib/active_scaffold.rb +1 -1
  56. data/lib/active_scaffold.rb~ +362 -0
  57. metadata +110 -76
  58. data/lib/active_scaffold/bridges/dragonfly/bridge.rb~ +0 -12
  59. data/lib/active_scaffold/bridges/dragonfly/lib/dragonfly_bridge.rb~ +0 -36
  60. data/lib/active_scaffold/bridges/dragonfly/lib/dragonfly_bridge_helpers.rb~ +0 -12
  61. data/lib/active_scaffold/bridges/dragonfly/lib/form_ui.rb~ +0 -27
  62. data/lib/active_scaffold/bridges/dragonfly/lib/list_ui.rb~ +0 -16
@@ -0,0 +1,196 @@
1
+ module ActiveScaffold::Actions
2
+ module List
3
+ def self.included(base)
4
+ base.before_filter :list_authorized_filter, :only => [:index, :row]
5
+ base.helper_method :list_columns
6
+ end
7
+
8
+ def index
9
+ list
10
+ end
11
+
12
+ # get just a single row
13
+ def row
14
+ @record = find_if_allowed(params[:id], :read)
15
+ respond_to_action(:row)
16
+ end
17
+
18
+ def list
19
+ do_list
20
+ do_new if active_scaffold_config.list.always_show_create
21
+ @record ||= new_model if active_scaffold_config.list.always_show_search
22
+ @nested_auto_open = active_scaffold_config.list.nested_auto_open
23
+ respond_to_action(:list)
24
+ end
25
+
26
+ protected
27
+ def list_respond_to_html
28
+ if params.delete(:embedded)
29
+ render :action => 'list', :layout => false
30
+ else
31
+ render :action => 'list'
32
+ end
33
+ end
34
+ def list_respond_to_js
35
+ if params[:adapter]
36
+ render(:partial => 'list_with_header')
37
+ elsif params[:embedded]
38
+ params.delete(:embedded)
39
+ render(:partial => 'list_with_header')
40
+ else
41
+ render :action => 'list.js'
42
+ end
43
+ end
44
+ def list_respond_to_xml
45
+ render :xml => response_object.to_xml(:only => list_columns_names), :content_type => Mime::XML, :status => response_status
46
+ end
47
+ def list_respond_to_json
48
+ render :text => response_object.to_json(:only => list_columns_names), :content_type => Mime::JSON, :status => response_status
49
+ end
50
+ def list_respond_to_yaml
51
+ render :text => Hash.from_xml(response_object.to_xml(:only => list_columns_names)).to_yaml, :content_type => Mime::YAML, :status => response_status
52
+ end
53
+
54
+ def row_respond_to_html
55
+ render(:partial => 'row', :locals => {:record => @record})
56
+ end
57
+
58
+ # The actual algorithm to prepare for the list view
59
+ def set_includes_for_list_columns
60
+ includes_for_list_columns = active_scaffold_config.list.columns.collect{ |c| c.includes }.flatten.uniq.compact
61
+ self.active_scaffold_includes.concat includes_for_list_columns
62
+ end
63
+
64
+ # The actual algorithm to prepare for the list view
65
+ def do_list
66
+ set_includes_for_list_columns
67
+
68
+ options = { :sorting => active_scaffold_config.list.user.sorting,
69
+ :count_includes => active_scaffold_config.list.user.count_includes }
70
+ paginate = (params[:format].nil?) ? (accepts? :html, :js) : ['html', 'js'].include?(params[:format])
71
+ if paginate
72
+ options.merge!({
73
+ :per_page => active_scaffold_config.list.user.per_page,
74
+ :page => active_scaffold_config.list.user.page,
75
+ :pagination => active_scaffold_config.list.pagination
76
+ })
77
+ end
78
+
79
+ page = find_page(options)
80
+ if page.items.blank? && !page.pager.infinite?
81
+ page = page.pager.last
82
+ active_scaffold_config.list.user.page = page.number
83
+ end
84
+ @page, @records = page, page.items
85
+ end
86
+
87
+ def each_record_in_page
88
+ _page = active_scaffold_config.list.user.page
89
+ do_search if respond_to? :do_search
90
+ active_scaffold_config.list.user.page = _page
91
+ do_list
92
+ @page.items.each {|record| yield record}
93
+ end
94
+
95
+ def each_record_in_scope
96
+ do_search if respond_to? :do_search
97
+ finder_options = { :order => "#{active_scaffold_config.model.connection.quote_table_name(active_scaffold_config.model.table_name)}.#{active_scaffold_config.model.primary_key} ASC",
98
+ :conditions => all_conditions,
99
+ :joins => joins_for_finder}
100
+ finder_options.merge! custom_finder_options
101
+ finder_options.merge! :include => (active_scaffold_includes.blank? ? nil : active_scaffold_includes)
102
+ klass = beginning_of_chain
103
+ klass.all(finder_options).each {|record| yield record}
104
+ end
105
+
106
+ # The default security delegates to ActiveRecordPermissions.
107
+ # You may override the method to customize.
108
+ def list_authorized?
109
+ authorized_for?(:crud_type => :read)
110
+ end
111
+
112
+ # call this method in your action_link action to simplify processing of actions
113
+ # eg for member action_link :fire
114
+ # process_action_link_action do |record|
115
+ # record.update_attributes(:fired => true)
116
+ # self.successful = true
117
+ # flash[:info] = 'Player fired'
118
+ # end
119
+ def process_action_link_action(render_action = :action_update, crud_type = nil)
120
+ if request.get?
121
+ # someone has disabled javascript, we have to show confirmation form first
122
+ @record = find_if_allowed(params[:id], :read) if params[:id] && params[:id] && params[:id].to_i > 0
123
+ respond_to_action(:action_confirmation)
124
+ else
125
+ if params[:id] && params[:id] && params[:id].to_i > 0
126
+ crud_type ||= (request.post? || request.put?) ? :update : :delete
127
+ @record = find_if_allowed(params[:id], crud_type)
128
+ unless @record.nil?
129
+ yield @record
130
+ else
131
+ self.successful = false
132
+ flash[:error] = as_(:no_authorization_for_action, :action => action_name)
133
+ end
134
+ else
135
+ yield
136
+ end
137
+ respond_to_action(render_action)
138
+ end
139
+ end
140
+
141
+ def action_confirmation_respond_to_html(confirm_action = action_name.to_sym)
142
+ link = active_scaffold_config.action_links[confirm_action]
143
+ render :action => 'action_confirmation', :locals => {:record => @record, :link => link}
144
+ end
145
+
146
+ def action_update_respond_to_html
147
+ do_search if respond_to? :do_search
148
+ do_list
149
+ redirect_to :action => 'index'
150
+ end
151
+
152
+ def action_update_respond_to_js
153
+ render(:action => 'on_action_update')
154
+ end
155
+
156
+ def action_update_respond_to_xml
157
+ render :xml => successful? ? "" : response_object.to_xml(:only => list_columns_names), :content_type => Mime::XML, :status => response_status
158
+ end
159
+
160
+ def action_update_respond_to_json
161
+ render :text => successful? ? "" : response_object.to_json(:only => list_columns_names), :content_type => Mime::JSON, :status => response_status
162
+ end
163
+
164
+ def action_update_respond_to_yaml
165
+ render :text => successful? ? "" : Hash.from_xml(response_object.to_xml(:only => list_columns_names)).to_yaml, :content_type => Mime::YAML, :status => response_status
166
+ end
167
+
168
+ private
169
+ def list_authorized_filter
170
+ raise ActiveScaffold::ActionNotAllowed unless list_authorized?
171
+ end
172
+
173
+ def list_formats
174
+ (default_formats + active_scaffold_config.formats + active_scaffold_config.list.formats).uniq
175
+ end
176
+ alias_method :index_formats, :list_formats
177
+
178
+ alias_method :row_formats, :list_formats
179
+
180
+ def action_update_formats
181
+ (default_formats + active_scaffold_config.formats).uniq
182
+ end
183
+
184
+ def action_confirmation_formats
185
+ (default_formats + active_scaffold_config.formats).uniq
186
+ end
187
+
188
+ def list_columns
189
+ active_scaffold_config.list.columns.collect_visible
190
+ end
191
+
192
+ def list_columns_names
193
+ list_columns.collect(&:name)
194
+ end
195
+ end
196
+ end
@@ -82,8 +82,12 @@ module ActiveScaffold::Actions
82
82
  end
83
83
 
84
84
  def beginning_of_chain
85
- if nested? && nested.association && nested.association.collection?
86
- nested.parent_scope.send(nested.association.name)
85
+ if nested? && nested.association && !nested.association.belongs_to?
86
+ if nested.association.collection?
87
+ nested.parent_scope.send(nested.association.name)
88
+ elsif nested.child_association.belongs_to?
89
+ active_scaffold_config.model.where(nested.child_association.foreign_key => nested.parent_scope)
90
+ end
87
91
  elsif nested? && nested.scope
88
92
  nested.parent_scope.send(nested.scope)
89
93
  else
@@ -0,0 +1,252 @@
1
+ module ActiveScaffold::Actions
2
+ # The Nested module basically handles automatically linking controllers together. It does this by creating column links with the right parameters, and by providing any supporting systems (like a /:controller/nested action for returning associated scaffolds).
3
+ module Nested
4
+
5
+ def self.included(base)
6
+ super
7
+ base.module_eval do
8
+ before_filter :register_constraints_with_action_columns
9
+ before_filter :set_nested
10
+ before_filter :configure_nested
11
+ include ActiveScaffold::Actions::Nested::ChildMethods if active_scaffold_config.model.reflect_on_all_associations.any? {|a| a.macro == :has_and_belongs_to_many}
12
+ end
13
+ base.before_filter :include_habtm_actions
14
+ base.helper_method :nested
15
+ base.helper_method :nested_parent_record
16
+ end
17
+
18
+ protected
19
+ def nested
20
+ @nested ||= ActiveScaffold::DataStructures::NestedInfo.get(active_scaffold_config.model, active_scaffold_session_storage)
21
+ if !@nested.nil? && @nested.new_instance?
22
+ register_constraints_with_action_columns(@nested.constrained_fields, active_scaffold_config.list.hide_nested_column ? [] : [:list])
23
+ active_scaffold_constraints[:id] = params[:id] if @nested.belongs_to?
24
+ end
25
+ @nested
26
+ end
27
+
28
+ def nested?
29
+ !nested.nil?
30
+ end
31
+
32
+ def set_nested
33
+ if params[:parent_scaffold] && ((params[:association] && params[:assoc_id]) || params[:named_scope])
34
+ @nested = nil
35
+ active_scaffold_session_storage[:nested] = {:parent_scaffold => params[:parent_scaffold].to_s,
36
+ :name => (params[:association] || params[:named_scope]).to_sym,
37
+ :parent_id => params[:assoc_id]}
38
+ params.delete_if {|key, value| [:parent_scaffold, :association, :named_scope, :assoc_id].include? key.to_sym}
39
+ end
40
+ end
41
+
42
+ def configure_nested
43
+ if nested?
44
+ active_scaffold_session_storage[:list][:label] = if nested.belongs_to?
45
+ as_(:nested_of_model, :nested_model => active_scaffold_config.model.model_name.human, :parent_model => nested_parent_record.to_label)
46
+ else
47
+ as_(:nested_for_model, :nested_model => active_scaffold_config.list.label, :parent_model => nested_parent_record.to_label)
48
+ end
49
+ if nested.sorted?
50
+ active_scaffold_config.list.user.nested_default_sorting = {:table_name => active_scaffold_config.model.model_name, :default_sorting => nested.default_sorting}
51
+ end
52
+ end
53
+ end
54
+
55
+ def nested_authorized?(record = nil)
56
+ true
57
+ end
58
+
59
+ def include_habtm_actions
60
+ if nested?
61
+ if nested.habtm?
62
+ # Production mode is ok with adding a link everytime the scaffold is nested - we ar not ok with that.
63
+ active_scaffold_config.action_links.add('new_existing', :label => :add_existing, :type => :collection, :security_method => :add_existing_authorized?) unless active_scaffold_config.action_links['new_existing']
64
+ if active_scaffold_config.nested.shallow_delete
65
+ active_scaffold_config.action_links.add('destroy_existing', :label => :remove, :type => :member, :confirm => :are_you_sure_to_delete, :method => :delete, :position => false, :security_method => :delete_existing_authorized?) unless active_scaffold_config.action_links['destroy_existing']
66
+ if active_scaffold_config.actions.include?(:delete)
67
+ active_scaffold_config.action_links.delete("delete") if active_scaffold_config.action_links['delete']
68
+ end
69
+ end
70
+ else
71
+ # Production mode is caching this link into a non nested scaffold
72
+ active_scaffold_config.action_links.delete('new_existing') if active_scaffold_config.action_links['new_existing']
73
+
74
+ if active_scaffold_config.nested.shallow_delete
75
+ active_scaffold_config.action_links.delete("destroy_existing") if active_scaffold_config.action_links['destroy_existing']
76
+ if active_scaffold_config.actions.include?(:delete)
77
+ active_scaffold_config.action_links.add(ActiveScaffold::Config::Delete.link) unless active_scaffold_config.action_links['delete']
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def beginning_of_chain
85
+ if nested? && nested.association && !nested.association.belongs_to?
86
+ debugger
87
+ if nested.association.collection?
88
+ nested.parent_scope.send(nested.association.name)
89
+ elsif nested.child_association.belongs_to?
90
+ active_scaffold_config.model.where(nested.child_association.foreign_key => nested.parent_scope)
91
+ end
92
+ elsif nested? && nested.scope
93
+ nested.parent_scope.send(nested.scope)
94
+ else
95
+ active_scaffold_config.model
96
+ end
97
+ end
98
+
99
+ def nested_parent_record(crud = :read)
100
+ @nested_parent_record ||= find_if_allowed(nested.parent_id, crud, nested.parent_model)
101
+ end
102
+
103
+ def create_association_with_parent(record)
104
+ if nested?
105
+ if (nested.belongs_to? || nested.has_one? || nested.habtm?) && nested.child_association
106
+ parent = nested_parent_record(:read)
107
+ case nested.child_association.macro
108
+ when :has_one
109
+ record.send("#{nested.child_association.name}=", parent)
110
+ when :belongs_to
111
+ record.send("#{nested.child_association.name}=", parent)
112
+ when :has_many, :has_and_belongs_to_many
113
+ record.send("#{nested.child_association.name}").send(:<<, parent)
114
+ end unless parent.nil?
115
+ end
116
+ end
117
+ end
118
+
119
+ private
120
+ def nested_formats
121
+ (default_formats + active_scaffold_config.formats + active_scaffold_config.nested.formats).uniq
122
+ end
123
+ end
124
+ end
125
+
126
+ module ActiveScaffold::Actions::Nested
127
+ module ChildMethods
128
+
129
+ def self.included(base)
130
+ super
131
+ end
132
+
133
+ def new_existing
134
+ do_new
135
+ respond_to_action(:new_existing)
136
+ end
137
+
138
+ def add_existing
139
+ do_add_existing
140
+ respond_to_action(:add_existing)
141
+ end
142
+
143
+ def destroy_existing
144
+ return redirect_to(params.merge(:action => :delete)) if request.get?
145
+ do_destroy_existing
146
+ respond_to_action(:destroy_existing)
147
+ end
148
+
149
+ protected
150
+ def new_existing_respond_to_html
151
+ if successful?
152
+ render(:action => 'add_existing_form')
153
+ else
154
+ return_to_main
155
+ end
156
+ end
157
+ def new_existing_respond_to_js
158
+ render(:partial => 'add_existing_form')
159
+ end
160
+ def add_existing_respond_to_html
161
+ if successful?
162
+ flash[:info] = as_(:created_model, :model => @record.to_label)
163
+ return_to_main
164
+ else
165
+ render(:action => 'add_existing_form')
166
+ end
167
+ end
168
+ def add_existing_respond_to_js
169
+ if successful?
170
+ render :action => 'add_existing'
171
+ else
172
+ render :action => 'form_messages'
173
+ end
174
+ end
175
+ def add_existing_respond_to_xml
176
+ render :xml => response_object.to_xml(:only => active_scaffold_config.list.columns.names), :content_type => Mime::XML, :status => response_status
177
+ end
178
+ def add_existing_respond_to_json
179
+ render :text => response_object.to_json(:only => active_scaffold_config.list.columns.names), :content_type => Mime::JSON, :status => response_status
180
+ end
181
+ def add_existing_respond_to_yaml
182
+ render :text => Hash.from_xml(response_object.to_xml(:only => active_scaffold_config.list.columns.names)).to_yaml, :content_type => Mime::YAML, :status => response_status
183
+ end
184
+ def destroy_existing_respond_to_html
185
+ flash[:info] = as_(:deleted_model, :model => @record.to_label)
186
+ return_to_main
187
+ end
188
+
189
+ def destroy_existing_respond_to_js
190
+ render(:action => 'destroy')
191
+ end
192
+
193
+ def destroy_existing_respond_to_xml
194
+ render :xml => successful? ? "" : response_object.to_xml(:only => active_scaffold_config.list.columns.names), :content_type => Mime::XML, :status => response_status
195
+ end
196
+
197
+ def destroy_existing_respond_to_json
198
+ render :text => successful? ? "" : response_object.to_json(:only => active_scaffold_config.list.columns.names), :content_type => Mime::JSON, :status => response_status
199
+ end
200
+
201
+ def destroy_existing_respond_to_yaml
202
+ render :text => successful? ? "" : Hash.from_xml(response_object.to_xml(:only => active_scaffold_config.list.columns.names)).to_yaml, :content_type => Mime::YAML, :status => response_status
203
+ end
204
+
205
+ def add_existing_authorized?(record = nil)
206
+ true
207
+ end
208
+ def delete_existing_authorized?(record = nil)
209
+ true
210
+ end
211
+
212
+ def after_create_save(record)
213
+ if params[:association_macro] == :has_and_belongs_to_many
214
+ params[:associated_id] = record
215
+ do_add_existing
216
+ end
217
+ end
218
+
219
+ # The actual "add_existing" algorithm
220
+ def do_add_existing
221
+ parent_record = nested_parent_record(:update)
222
+ @record = active_scaffold_config.model.find(params[:associated_id])
223
+ if parent_record && @record
224
+ parent_record.send(nested.association.name) << @record
225
+ parent_record.save
226
+ else
227
+ false
228
+ end
229
+ end
230
+
231
+ def do_destroy_existing
232
+ if active_scaffold_config.nested.shallow_delete
233
+ @record = nested_parent_record(:update)
234
+ collection = @record.send(nested.association.name)
235
+ assoc_record = collection.find(params[:id])
236
+ collection.delete(assoc_record)
237
+ else
238
+ do_destroy
239
+ end
240
+ end
241
+ private
242
+ def new_existing_formats
243
+ (default_formats + active_scaffold_config.formats).uniq
244
+ end
245
+ def add_existing_formats
246
+ (default_formats + active_scaffold_config.formats).uniq
247
+ end
248
+ def destroy_existing_formats
249
+ (default_formats + active_scaffold_config.formats).uniq
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,49 @@
1
+ module ActiveScaffold::Actions
2
+ module Search
3
+ include ActiveScaffold::Actions::CommonSearch
4
+ def self.included(base)
5
+ base.before_filter :search_authorized_filter, :only => :show_search
6
+ base.before_filter :store_search_params_into_session, :only => [:index]
7
+ base.before_filter :do_search, :only => [:index]
8
+ base.helper_method :search_params
9
+ end
10
+
11
+ def show_search
12
+ respond_to_action(:search)
13
+ end
14
+
15
+ protected
16
+ def search_respond_to_html
17
+ render(:action => "search")
18
+ end
19
+ def search_respond_to_js
20
+ render(:partial => "search")
21
+ end
22
+ def do_search
23
+ query = search_params.to_s.strip rescue ''
24
+ unless query.empty?
25
+ columns = active_scaffold_config.search.columns
26
+ text_search = active_scaffold_config.search.text_search
27
+ query = query.split(active_scaffold_config.search.split_terms) if active_scaffold_config.search.split_terms
28
+ debugger
29
+ search_conditions = self.class.create_conditions_for_columns(query, columns, text_search)
30
+ self.active_scaffold_conditions = merge_conditions(self.active_scaffold_conditions, search_conditions)
31
+ @filtered = !search_conditions.blank?
32
+
33
+ includes_for_search_columns = columns.collect{ |column| column.includes}.flatten.uniq.compact
34
+ self.active_scaffold_includes.concat includes_for_search_columns
35
+
36
+ active_scaffold_config.list.user.page = nil
37
+ end
38
+ end
39
+
40
+ private
41
+ def search_authorized_filter
42
+ link = active_scaffold_config.search.link || active_scaffold_config.search.class.link
43
+ raise ActiveScaffold::ActionNotAllowed unless self.send(link.security_method)
44
+ end
45
+ def search_formats
46
+ (default_formats + active_scaffold_config.formats + active_scaffold_config.search.formats).uniq
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveScaffold::Actions
2
+ module Subform
3
+ def edit_associated
4
+ do_edit_associated
5
+ render :action => 'edit_associated.js'
6
+ end
7
+
8
+ protected
9
+
10
+ def do_edit_associated
11
+ @parent_record = params[:id].nil? ? new_model : find_if_allowed(params[:id], :update)
12
+ @column = active_scaffold_config.columns[params[:association]]
13
+
14
+ # NOTE: we don't check whether the user is allowed to update this record, because if not, we'll still let them associate the record. we'll just refuse to do more than associate, is all.
15
+ @record = @column.association.klass.find(params[:associated_id]) if params[:associated_id]
16
+ @record ||= if column.singular_association?
17
+ parent_record.send("build_#{column.name}".to_sym)
18
+ else
19
+ parent_record.send(column.name).buildbuild_associated(column, parent_record)
20
+ end
21
+
22
+ @scope = "[#{@column.name}]"
23
+ @scope += (@record.new_record?) ? "[#{(Time.now.to_f*1000).to_i.to_s}]" : "[#{@record.id}]" if @column.plural_association?
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,149 @@
1
+ module ActiveScaffold::Actions
2
+ module Update
3
+ def self.included(base)
4
+ base.before_filter :update_authorized_filter, :only => [:edit, :update]
5
+ base.helper_method :update_refresh_list?
6
+ end
7
+
8
+ def edit
9
+ do_edit
10
+ respond_to_action(:edit)
11
+ end
12
+
13
+ def update
14
+ do_update
15
+ respond_to_action(:update)
16
+ end
17
+
18
+ # for inline (inlist) editing
19
+ def update_column
20
+ do_update_column
21
+ render :action => 'update_column', :locals => {:column_span_id => params[:editor_id] || params[:editorId]}
22
+ end
23
+
24
+ protected
25
+ def edit_respond_to_html
26
+ if successful?
27
+ render(:action => 'update')
28
+ else
29
+ return_to_main
30
+ end
31
+ end
32
+ def edit_respond_to_js
33
+ render(:partial => 'update_form')
34
+ end
35
+ def update_respond_to_html
36
+ if params[:iframe]=='true' # was this an iframe post ?
37
+ responds_to_parent do
38
+ render :action => 'on_update.js', :layout => false
39
+ end
40
+ else # just a regular post
41
+ if successful?
42
+ flash[:info] = as_(:updated_model, :model => @record.to_label)
43
+ return_to_main
44
+ else
45
+ render(:action => 'update')
46
+ end
47
+ end
48
+ end
49
+ def update_respond_to_js
50
+ if successful? && update_refresh_list? && !render_parent?
51
+ do_search if respond_to? :do_search
52
+ do_list
53
+ end
54
+ render :action => 'on_update'
55
+ end
56
+ def update_respond_to_xml
57
+ render :xml => response_object.to_xml(:only => active_scaffold_config.update.columns.names), :content_type => Mime::XML, :status => response_status
58
+ end
59
+ def update_respond_to_json
60
+ render :text => response_object.to_json(:only => active_scaffold_config.update.columns.names), :content_type => Mime::JSON, :status => response_status
61
+ end
62
+ def update_respond_to_yaml
63
+ render :text => Hash.from_xml(response_object.to_xml(:only => active_scaffold_config.update.columns.names)).to_yaml, :content_type => Mime::YAML, :status => response_status
64
+ end
65
+ # A simple method to find and prepare a record for editing
66
+ # May be overridden to customize the record (set default values, etc.)
67
+ def do_edit
68
+ register_constraints_with_action_columns(nested.constrained_fields, active_scaffold_config.update.hide_nested_column ? [] : [:update]) if nested?
69
+ @record = find_if_allowed(params[:id], :update)
70
+ end
71
+
72
+ # A complex method to update a record. The complexity comes from the support for subforms, and saving associated records.
73
+ # If you want to customize this algorithm, consider using the +before_update_save+ callback
74
+ def do_update
75
+ do_edit
76
+ update_save
77
+ end
78
+
79
+ def update_save(options = {})
80
+ begin
81
+ active_scaffold_config.model.transaction do
82
+ @record = update_record_from_params(@record, active_scaffold_config.update.columns, params[:record]) unless options[:no_record_param_update]
83
+ before_update_save(@record)
84
+ self.successful = [@record.valid?, @record.associated_valid?].all? {|v| v == true} # this syntax avoids a short-circuit
85
+ debugger
86
+ if successful?
87
+ @record.save! and @record.save_associated!
88
+ after_update_save(@record)
89
+ else
90
+ # some associations such as habtm are saved before saved is called on parent object
91
+ # we have to revert these changes if validation fails
92
+ raise ActiveRecord::Rollback, "don't save habtm associations unless record is valid"
93
+ end
94
+ end
95
+ rescue ActiveRecord::RecordInvalid
96
+ rescue ActiveRecord::StaleObjectError
97
+ @record.errors.add(:base, as_(:version_inconsistency))
98
+ self.successful=false
99
+ rescue ActiveRecord::RecordNotSaved
100
+ @record.errors.add(:base, as_(:record_not_saved)) if @record.errors.empty?
101
+ self.successful = false
102
+ end
103
+ end
104
+
105
+ def do_update_column
106
+ @record = active_scaffold_config.model.find(params[:id])
107
+ if @record.authorized_for?(:crud_type => :update, :column => params[:column])
108
+ column = active_scaffold_config.columns[params[:column].to_sym]
109
+ params[:value] ||= @record.column_for_attribute(params[:column]).default unless @record.column_for_attribute(params[:column]).nil? || @record.column_for_attribute(params[:column]).null
110
+ unless column.nil?
111
+ params[:value] = column_value_from_param_value(@record, column, params[:value])
112
+ params[:value] = [] if params[:value].nil? && column.form_ui && column.plural_association?
113
+ end
114
+ @record.send("#{params[:column]}=", params[:value])
115
+ before_update_save(@record)
116
+ @record.save
117
+ after_update_save(@record)
118
+ end
119
+ end
120
+
121
+ # override this method if you want to inject data in the record (or its associated objects) before the save
122
+ def before_update_save(record); end
123
+
124
+ # override this method if you want to do something after the save
125
+ def after_update_save(record); end
126
+
127
+ # should we refresh whole list after update operation
128
+ def update_refresh_list?
129
+ active_scaffold_config.update.refresh_list
130
+ end
131
+
132
+ # The default security delegates to ActiveRecordPermissions.
133
+ # You may override the method to customize.
134
+ def update_authorized?(record = nil)
135
+ (!nested? || !nested.readonly?) && authorized_for?(:crud_type => :update)
136
+ end
137
+ private
138
+ def update_authorized_filter
139
+ link = active_scaffold_config.update.link || active_scaffold_config.update.class.link
140
+ raise ActiveScaffold::ActionNotAllowed unless self.send(link.security_method)
141
+ end
142
+ def edit_formats
143
+ (default_formats + active_scaffold_config.formats).uniq
144
+ end
145
+ def update_formats
146
+ (default_formats + active_scaffold_config.formats + active_scaffold_config.update.formats).uniq
147
+ end
148
+ end
149
+ end