active_scaffold 3.2.20 → 3.3.0.rc

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.
Files changed (152) hide show
  1. data/CHANGELOG +19 -13
  2. data/README +66 -0
  3. data/app/assets/javascripts/jquery/active_scaffold.js +156 -113
  4. data/app/assets/javascripts/jquery/active_scaffold_chosen.js +11 -0
  5. data/app/assets/javascripts/jquery/date_picker_bridge.js.erb +0 -1
  6. data/app/assets/javascripts/jquery/jquery.editinplace.js +132 -128
  7. data/app/assets/javascripts/prototype/active_scaffold.js +68 -25
  8. data/{frontends/default/views/_horizontal_subform_footer.html.erb → app/assets/javascripts/prototype/active_scaffold_chosen.js} +0 -0
  9. data/app/assets/stylesheets/active_scaffold_colors.css.scss +8 -1
  10. data/app/assets/stylesheets/active_scaffold_layout.css +14 -8
  11. data/{frontends/default/views → app/views/active_scaffold_overrides}/_add_existing_form.html.erb +0 -0
  12. data/{frontends/default/views → app/views/active_scaffold_overrides}/_base_form.html.erb +0 -0
  13. data/{frontends/default/views → app/views/active_scaffold_overrides}/_create_form.html.erb +0 -0
  14. data/{frontends/default/views → app/views/active_scaffold_overrides}/_create_form_on_list.html.erb +0 -0
  15. data/{frontends/default/views → app/views/active_scaffold_overrides}/_field_search.html.erb +0 -0
  16. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form.html.erb +0 -0
  17. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_association.html.erb +8 -3
  18. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_association_footer.html.erb +5 -4
  19. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +85 -0
  20. data/app/views/active_scaffold_overrides/_form_attribute.html.erb +23 -0
  21. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_hidden_attribute.html.erb +0 -0
  22. data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_messages.html.erb +0 -0
  23. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +12 -0
  24. data/app/views/active_scaffold_overrides/_horizontal_subform_footer.html.erb +0 -0
  25. data/{frontends/default/views → app/views/active_scaffold_overrides}/_horizontal_subform_header.html.erb +3 -2
  26. data/{frontends/default/views → app/views/active_scaffold_overrides}/_human_conditions.html.erb +0 -0
  27. data/app/views/active_scaffold_overrides/_list.html.erb +35 -0
  28. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_calculations.html.erb +0 -0
  29. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_column_headings.html.erb +0 -0
  30. data/app/views/active_scaffold_overrides/_list_header.html.erb +8 -0
  31. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_inline_adapter.html.erb +0 -0
  32. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_messages.html.erb +4 -4
  33. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_pagination.html.erb +0 -0
  34. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_pagination_links.html.erb +0 -0
  35. data/app/views/active_scaffold_overrides/_list_record.html.erb +30 -0
  36. data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_with_header.html.erb +0 -0
  37. data/{frontends/default/views → app/views/active_scaffold_overrides}/_messages.html.erb +0 -0
  38. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +1 -0
  39. data/{frontends/default/views → app/views/active_scaffold_overrides}/_render_field.js.erb +9 -1
  40. data/{frontends/default/views → app/views/active_scaffold_overrides}/_row.html.erb +0 -0
  41. data/{frontends/default/views → app/views/active_scaffold_overrides}/_search.html.erb +0 -0
  42. data/{frontends/default/views → app/views/active_scaffold_overrides}/_search_attribute.html.erb +0 -0
  43. data/{frontends/default/views → app/views/active_scaffold_overrides}/_show.html.erb +0 -0
  44. data/{frontends/default/views → app/views/active_scaffold_overrides}/_show_columns.html.erb +0 -0
  45. data/app/views/active_scaffold_overrides/_update_actions.html.erb +9 -0
  46. data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_calculations.js.erb +0 -0
  47. data/app/views/active_scaffold_overrides/_update_column.js.erb +16 -0
  48. data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_form.html.erb +0 -0
  49. data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_messages.js.erb +0 -0
  50. data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +8 -0
  51. data/{frontends/default/views → app/views/active_scaffold_overrides}/action_confirmation.html.erb +0 -0
  52. data/{frontends/default/views → app/views/active_scaffold_overrides}/add_existing.js.erb +0 -0
  53. data/{frontends/default/views → app/views/active_scaffold_overrides}/add_existing_form.html.erb +0 -0
  54. data/{frontends/default/views → app/views/active_scaffold_overrides}/create.html.erb +0 -0
  55. data/{frontends/default/views → app/views/active_scaffold_overrides}/delete.html.erb +0 -0
  56. data/{frontends/default/views → app/views/active_scaffold_overrides}/destroy.js.erb +0 -0
  57. data/{frontends/default/views → app/views/active_scaffold_overrides}/edit_associated.js.erb +1 -1
  58. data/{frontends/default/views → app/views/active_scaffold_overrides}/field_search.html.erb +0 -0
  59. data/{frontends/default/views → app/views/active_scaffold_overrides}/form_messages.js.erb +0 -0
  60. data/{frontends/default/views → app/views/active_scaffold_overrides}/list.html.erb +0 -0
  61. data/{frontends/default/views → app/views/active_scaffold_overrides}/on_action_update.js.erb +3 -3
  62. data/{frontends/default/views → app/views/active_scaffold_overrides}/on_create.js.erb +1 -1
  63. data/{frontends/default/views → app/views/active_scaffold_overrides}/on_mark.js.erb +0 -0
  64. data/{frontends/default/views → app/views/active_scaffold_overrides}/on_update.js.erb +4 -4
  65. data/{frontends/default/views → app/views/active_scaffold_overrides}/render_field.js.erb +0 -0
  66. data/{frontends/default/views → app/views/active_scaffold_overrides}/row.js.erb +1 -1
  67. data/{frontends/default/views → app/views/active_scaffold_overrides}/search.html.erb +0 -0
  68. data/{frontends/default/views → app/views/active_scaffold_overrides}/show.html.erb +0 -0
  69. data/{frontends/default/views → app/views/active_scaffold_overrides}/update.html.erb +1 -1
  70. data/app/views/active_scaffold_overrides/update_column.js.erb +26 -0
  71. data/{frontends/default/views → app/views/active_scaffold_overrides}/update_row.js.erb +0 -0
  72. data/config/locales/de.yml +1 -0
  73. data/config/locales/en.yml +1 -0
  74. data/config/locales/es.yml +1 -0
  75. data/config/locales/fr.yml +1 -0
  76. data/config/locales/hu.yml +1 -0
  77. data/config/locales/ja.yml +1 -0
  78. data/config/locales/ru.yml +1 -0
  79. data/lib/active_scaffold.rb +14 -26
  80. data/lib/active_scaffold/actions/core.rb +14 -11
  81. data/lib/active_scaffold/actions/create.rb +3 -3
  82. data/lib/active_scaffold/actions/delete.rb +3 -0
  83. data/lib/active_scaffold/actions/list.rb +9 -6
  84. data/lib/active_scaffold/actions/mark.rb +1 -1
  85. data/lib/active_scaffold/actions/nested.rb +8 -6
  86. data/lib/active_scaffold/actions/show.rb +6 -1
  87. data/lib/active_scaffold/actions/update.rb +39 -19
  88. data/lib/active_scaffold/active_record_permissions.rb +29 -12
  89. data/lib/active_scaffold/attribute_params.rb +14 -7
  90. data/lib/active_scaffold/bridges/calendar_date_select.rb +1 -1
  91. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +1 -2
  92. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
  93. data/lib/active_scaffold/bridges/chosen.rb +14 -0
  94. data/lib/active_scaffold/bridges/chosen/helpers.rb +48 -0
  95. data/lib/active_scaffold/bridges/date_picker/helper.rb +7 -6
  96. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +1 -1
  97. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  98. data/lib/active_scaffold/bridges/file_column.rb +1 -1
  99. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  100. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +2 -2
  101. data/lib/active_scaffold/bridges/file_column/list_ui.rb +4 -4
  102. data/lib/active_scaffold/bridges/paperclip.rb +1 -1
  103. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +1 -1
  104. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  105. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +1 -1
  106. data/lib/active_scaffold/bridges/shared/date_bridge.rb +1 -1
  107. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +1 -1
  108. data/lib/active_scaffold/config/core.rb +9 -2
  109. data/lib/active_scaffold/config/list.rb +9 -13
  110. data/lib/active_scaffold/config/nested.rb +11 -2
  111. data/lib/active_scaffold/data_structures/action_columns.rb +19 -5
  112. data/lib/active_scaffold/data_structures/action_link.rb +9 -2
  113. data/lib/active_scaffold/data_structures/action_links.rb +5 -36
  114. data/lib/active_scaffold/data_structures/column.rb +21 -21
  115. data/lib/active_scaffold/data_structures/nested_info.rb +31 -44
  116. data/lib/active_scaffold/extensions/action_controller_rescueing.rb +1 -0
  117. data/lib/active_scaffold/extensions/action_view_rendering.rb +30 -36
  118. data/lib/active_scaffold/extensions/reverse_associations.rb +10 -6
  119. data/lib/active_scaffold/extensions/routing_mapper.rb +6 -5
  120. data/lib/active_scaffold/extensions/unsaved_associated.rb +1 -1
  121. data/lib/active_scaffold/finder.rb +18 -10
  122. data/lib/active_scaffold/helpers/association_helpers.rb +21 -2
  123. data/lib/active_scaffold/helpers/controller_helpers.rb +14 -16
  124. data/lib/active_scaffold/helpers/form_column_helpers.rb +161 -21
  125. data/lib/active_scaffold/helpers/id_helpers.rb +7 -7
  126. data/lib/active_scaffold/helpers/list_column_helpers.rb +42 -92
  127. data/lib/active_scaffold/helpers/search_column_helpers.rb +10 -3
  128. data/lib/active_scaffold/helpers/show_column_helpers.rb +4 -9
  129. data/lib/active_scaffold/helpers/view_helpers.rb +278 -78
  130. data/lib/active_scaffold/version.rb +2 -2
  131. data/lib/generators/active_scaffold_controller/templates/controller.rb +1 -1
  132. data/test/bridges/paperclip_test.rb +2 -2
  133. data/vendor/assets/javascripts/jquery-ui-timepicker-addon.js +1882 -1276
  134. metadata +79 -80
  135. data/README.md +0 -67
  136. data/frontends/default/views/_action_group.html.erb +0 -24
  137. data/frontends/default/views/_form_attribute.html.erb +0 -23
  138. data/frontends/default/views/_horizontal_subform.html.erb +0 -22
  139. data/frontends/default/views/_horizontal_subform_record.html.erb +0 -43
  140. data/frontends/default/views/_list.html.erb +0 -18
  141. data/frontends/default/views/_list_actions.html.erb +0 -15
  142. data/frontends/default/views/_list_header.html.erb +0 -10
  143. data/frontends/default/views/_list_record.html.erb +0 -13
  144. data/frontends/default/views/_list_record_columns.html.erb +0 -8
  145. data/frontends/default/views/_refresh_list.js.erb +0 -1
  146. data/frontends/default/views/_update_actions.html.erb +0 -9
  147. data/frontends/default/views/_vertical_subform.html.erb +0 -12
  148. data/frontends/default/views/_vertical_subform_record.html.erb +0 -43
  149. data/frontends/default/views/refresh_list.js.erb +0 -2
  150. data/frontends/default/views/update_column.js.erb +0 -15
  151. data/lib/active_scaffold/extensions/active_record_offset.rb +0 -12
  152. data/lib/active_scaffold/extensions/nil_id_in_url_params.rb +0 -7
@@ -55,25 +55,25 @@ module ActiveScaffold::Actions
55
55
  end
56
56
 
57
57
  def row_respond_to_js
58
- render
58
+ render :action => 'row'
59
59
  end
60
60
 
61
61
  # The actual algorithm to prepare for the list view
62
- def set_includes_for_list_columns
62
+ def set_includes_for_columns(action = :list)
63
63
  @cache_associations = true
64
- includes_for_list_columns = active_scaffold_config.list.columns.collect{ |c| c.includes }.flatten.uniq.compact
64
+ includes_for_list_columns = active_scaffold_config.send(action).columns.collect{ |c| c.includes }.flatten.uniq.compact
65
65
  self.active_scaffold_includes.concat includes_for_list_columns
66
66
  end
67
67
 
68
68
  def get_row
69
- set_includes_for_list_columns
69
+ set_includes_for_columns
70
70
  klass = beginning_of_chain.includes(active_scaffold_includes)
71
71
  @record = find_if_allowed(params[:id], :read, klass)
72
72
  end
73
73
 
74
74
  # The actual algorithm to prepare for the list view
75
75
  def do_list
76
- set_includes_for_list_columns
76
+ set_includes_for_columns
77
77
 
78
78
  options = { :sorting => active_scaffold_config.list.user.sorting,
79
79
  :count_includes => active_scaffold_config.list.user.count_includes }
@@ -96,6 +96,7 @@ module ActiveScaffold::Actions
96
96
  end
97
97
 
98
98
  def do_refresh_list
99
+ params.delete(:id)
99
100
  do_search if respond_to? :do_search
100
101
  do_list
101
102
  end
@@ -135,7 +136,9 @@ module ActiveScaffold::Actions
135
136
  @action_link = active_scaffold_config.action_links[action_name]
136
137
  if params[:id] && params[:id] && params[:id].to_i > 0
137
138
  crud_type ||= (request.post? || request.put?) ? :update : :delete
138
- @record = find_if_allowed(params[:id], crud_type)
139
+ set_includes_for_columns
140
+ klass = beginning_of_chain.includes(active_scaffold_includes)
141
+ @record = find_if_allowed(params[:id], crud_type, klass)
139
142
  unless @record.nil?
140
143
  yield @record
141
144
  else
@@ -29,7 +29,7 @@ module ActiveScaffold::Actions
29
29
  def mark_respond_to_js
30
30
  if params[:id]
31
31
  do_search if respond_to? :do_search
32
- set_includes_for_list_columns
32
+ set_includes_for_columns if active_scaffold_config.actions.include? :list
33
33
  @page = find_page(:pagination => active_scaffold_config.mark.mark_all_mode != :page)
34
34
  render :action => 'on_mark'
35
35
  else
@@ -37,7 +37,7 @@ module ActiveScaffold::Actions
37
37
  else
38
38
  as_(:nested_for_model, :nested_model => active_scaffold_config.list.label, :parent_model => nested_parent_record.to_label)
39
39
  end
40
- if nested.sorted?
40
+ if nested.sorted? && !active_scaffold_config.nested.ignore_order_from_association
41
41
  active_scaffold_config.list.user.nested_default_sorting = {:table_name => active_scaffold_config.model.model_name, :default_sorting => nested.default_sorting}
42
42
  end
43
43
  end
@@ -73,16 +73,18 @@ module ActiveScaffold::Actions
73
73
  end
74
74
 
75
75
  def beginning_of_chain
76
- if nested? && nested.association && !nested.association.belongs_to?
76
+ if nested? && nested.association
77
77
  if nested.association.collection?
78
- nested.parent_scope.send(nested.association.name)
79
- elsif nested.association.options[:through] # has_one :through doesn't need conditions
78
+ nested_parent_record.send(nested.association.name)
79
+ elsif nested.association.options[:through] || nested.child_association.nil? # has_one :through doesn't need conditions, and without child_association is not possible to add them
80
80
  active_scaffold_config.model
81
81
  elsif nested.child_association.belongs_to?
82
- active_scaffold_config.model.where(nested.child_association.foreign_key => nested.parent_scope)
82
+ active_scaffold_config.model.where(nested.child_association.foreign_key => nested_parent_record)
83
+ elsif nested.association.belongs_to?
84
+ active_scaffold_config.model.joins(nested.child_association.name).where(nested.association.active_record.table_name => {nested.association.active_record.primary_key => nested_parent_record}).readonly(false)
83
85
  end
84
86
  elsif nested? && nested.scope
85
- nested.parent_scope.send(nested.scope)
87
+ nested_parent_record.send(nested.scope)
86
88
  else
87
89
  active_scaffold_config.model
88
90
  end
@@ -41,7 +41,9 @@ module ActiveScaffold::Actions
41
41
  # A simple method to retrieve and prepare a record for showing.
42
42
  # May be overridden to customize show routine
43
43
  def do_show
44
- @record = find_if_allowed(params[:id], :read)
44
+ set_includes_for_columns(:show) if active_scaffold_config.actions.include? :list
45
+ klass = beginning_of_chain.includes(active_scaffold_includes)
46
+ @record = find_if_allowed(params[:id], :read, klass)
45
47
  end
46
48
 
47
49
  # The default security delegates to ActiveRecordPermissions.
@@ -49,6 +51,9 @@ module ActiveScaffold::Actions
49
51
  def show_authorized?(record = nil)
50
52
  (record || self).send(:authorized_for?, :crud_type => :read)
51
53
  end
54
+ def show_ignore?(record = nil)
55
+ !self.send(:authorized_for?, :crud_type => :read)
56
+ end
52
57
  private
53
58
  def show_authorized_filter
54
59
  link = active_scaffold_config.show.link || active_scaffold_config.show.class.link
@@ -18,7 +18,7 @@ module ActiveScaffold::Actions
18
18
  # for inline (inlist) editing
19
19
  def update_column
20
20
  do_update_column
21
- @column_span_id = params[:editor_id] || params[:editorId]
21
+ @column_span_id = params.delete(:editor_id) || params.delete(:editorId)
22
22
  end
23
23
 
24
24
  protected
@@ -35,7 +35,7 @@ module ActiveScaffold::Actions
35
35
  def update_respond_to_html
36
36
  if params[:iframe]=='true' # was this an iframe post ?
37
37
  responds_to_parent do
38
- render :action => 'on_update.js', :layout => false
38
+ render :action => 'on_update', :formats => [:js], :layout => false
39
39
  end
40
40
  else # just a regular post
41
41
  if successful?
@@ -48,7 +48,13 @@ module ActiveScaffold::Actions
48
48
  end
49
49
  def update_respond_to_js
50
50
  if successful?
51
- do_refresh_list if update_refresh_list? && !render_parent?
51
+ if !render_parent? && active_scaffold_config.actions.include?(:list)
52
+ if update_refresh_list?
53
+ do_refresh_list
54
+ else
55
+ get_row
56
+ end
57
+ end
52
58
  flash.now[:info] = as_(:updated_model, :model => @record.to_label) if active_scaffold_config.update.persistent
53
59
  end
54
60
  render :action => 'on_update'
@@ -62,6 +68,7 @@ module ActiveScaffold::Actions
62
68
  def update_respond_to_yaml
63
69
  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
70
  end
71
+
65
72
  # A simple method to find and prepare a record for editing
66
73
  # May be overridden to customize the record (set default values, etc.)
67
74
  def do_edit
@@ -81,7 +88,7 @@ module ActiveScaffold::Actions
81
88
  active_scaffold_config.model.transaction do
82
89
  @record = update_record_from_params(@record, active_scaffold_config.update.columns, attributes) unless options[:no_record_param_update]
83
90
  before_update_save(@record)
84
- self.successful = [@record.valid?, @record.associated_valid?].all? {|v| v == true} # this syntax avoids a short-circuit
91
+ self.successful = [@record.valid?, @record.associated_valid?].all? # this syntax avoids a short-circuit
85
92
  if successful?
86
93
  @record.save! and @record.save_associated!
87
94
  after_update_save(@record)
@@ -104,23 +111,33 @@ module ActiveScaffold::Actions
104
111
  end
105
112
 
106
113
  def do_update_column
107
- @record = active_scaffold_config.model.find(params[:id])
108
- if @record.authorized_for?(:crud_type => :update, :column => params[:column])
109
- column = active_scaffold_config.columns[params[:column].to_sym]
110
- unless @record.column_for_attribute(params[:column]).nil? || @record.column_for_attribute(params[:column]).null
111
- if @record.column_for_attribute(params[:column]).default == true
112
- params[:value] ||= false
113
- else
114
- params[:value] ||= @record.column_for_attribute(params[:column]).default
115
- end
114
+ # delete from params so update :table won't break urls, also they shouldn't be used in sort links too
115
+ value = params.delete(:value)
116
+ column = params.delete(:column).to_sym
117
+ params.delete(:original_html)
118
+ params.delete(:original_value)
119
+
120
+ @record = find_if_allowed(params[:id], :read)
121
+ if @record.authorized_for?(:crud_type => :update, :column => column)
122
+ @column = active_scaffold_config.columns[column]
123
+ value ||= unless @column.column.nil? || @column.column.null
124
+ @column.column.default == true ? false : @column.column.default
116
125
  end
117
- unless column.nil?
118
- params[:value] = column_value_from_param_value(@record, column, params[:value])
119
- params[:value] = [] if params[:value].nil? && column.form_ui && column.plural_association?
126
+ unless @column.nil?
127
+ value = column_value_from_param_value(@record, @column, value)
128
+ value = [] if value.nil? && @column.form_ui && @column.plural_association?
120
129
  end
121
- @record.send("#{params[:column]}=", params[:value])
130
+ @record.send("#{@column.name}=", value)
122
131
  before_update_save(@record)
123
- @record.save
132
+ self.successful = @record.save
133
+ if self.successful? && active_scaffold_config.actions.include?(:list)
134
+ if @column.inplace_edit_update == :table
135
+ params.delete(:id)
136
+ do_list
137
+ elsif @column.inplace_edit_update
138
+ get_row
139
+ end
140
+ end
124
141
  after_update_save(@record)
125
142
  end
126
143
  end
@@ -139,7 +156,10 @@ module ActiveScaffold::Actions
139
156
  # The default security delegates to ActiveRecordPermissions.
140
157
  # You may override the method to customize.
141
158
  def update_authorized?(record = nil)
142
- (!nested? || !nested.readonly?) && (record || self).send(:authorized_for?, :crud_type => :update)
159
+ (!nested? || !nested.readonly?) && (record || self).authorized_for?(:crud_type => :update)
160
+ end
161
+ def update_ignore?(record = nil)
162
+ !self.authorized_for?(:crud_type => :update)
143
163
  end
144
164
  private
145
165
  def update_authorized_filter
@@ -65,6 +65,10 @@ module ActiveRecordPermissions
65
65
  def self.included(base)
66
66
  base.extend SecurityMethods
67
67
  base.send :include, SecurityMethods
68
+ class << base
69
+ attr_accessor :class_security_methods
70
+ attr_accessor :instance_security_methods
71
+ end
68
72
  end
69
73
 
70
74
  # Because any class-level queries get delegated to the instance level via a new record,
@@ -85,34 +89,47 @@ module ActiveRecordPermissions
85
89
  def authorized_for?(options = {})
86
90
  raise ArgumentError, "unknown crud type #{options[:crud_type]}" if options[:crud_type] and ![:create, :read, :update, :delete].include?(options[:crud_type])
87
91
 
92
+ # collect other possibly-related methods that actually exist
93
+ methods = cached_authorized_for_methods(options)
94
+ return ActiveRecordPermissions.default_permission if methods.empty?
95
+ return send(methods.first) if methods.one?
96
+
97
+ # if any method returns false, then return false
98
+ return false if methods.any? {|m| !send(m)}
99
+ true
100
+ end
101
+
102
+ def cached_authorized_for_methods(options)
103
+ key = "#{options[:crud_type]}##{options[:column]}##{options[:action]}"
104
+ if self.is_a? Class
105
+ self.class_security_methods ||= {}
106
+ self.class_security_methods[key] ||= authorized_for_methods(options)
107
+ else
108
+ self.class.instance_security_methods ||= {}
109
+ self.class.instance_security_methods[key] ||= authorized_for_methods(options)
110
+ end
111
+ end
112
+
113
+ def authorized_for_methods(options)
88
114
  # column_authorized_for_crud_type? has the highest priority over other methods,
89
115
  # you can disable a crud verb and enable that verb for a column
90
116
  # (for example, disable update and enable inplace_edit in a column)
91
117
  method = column_and_crud_type_security_method(options[:column], options[:crud_type])
92
- return send(method) if method and respond_to?(method)
118
+ return [method] if method and respond_to?(method)
93
119
 
94
120
  # authorized_for_action? has higher priority than other methods,
95
121
  # you can disable a crud verb and enable an action with that crud verb
96
122
  # (for example, disable update and enable an action with update as crud type)
97
123
  method = action_security_method(options[:action])
98
- return send(method) if method and respond_to?(method)
124
+ return [method] if method and respond_to?(method)
99
125
 
100
126
  # collect other possibly-related methods that actually exist
101
127
  methods = [
102
128
  column_security_method(options[:column]),
103
129
  crud_type_security_method(options[:crud_type]),
104
130
  ].compact.select {|m| respond_to?(m)}
105
-
106
- # if any method returns false, then return false
107
- return false if methods.any? {|m| !send(m)}
108
-
109
- # if any method actually exists then it must've returned true, so return true
110
- return true unless methods.empty?
111
-
112
- # if no method exists, return the default permission
113
- return ActiveRecordPermissions.default_permission
114
131
  end
115
-
132
+
116
133
  private
117
134
 
118
135
  def column_security_method(column)
@@ -66,7 +66,7 @@ module ActiveScaffold
66
66
  if parent_record.new_record?
67
67
  parent_record.class.reflect_on_all_associations.each do |a|
68
68
  next unless [:has_one, :has_many].include?(a.macro) and not (a.options[:through] || a.options[:finder_sql])
69
- next unless association_proxy = parent_record.send(a.name)
69
+ next unless (association_proxy = parent_record.send(a.name)).present?
70
70
 
71
71
  raise ActiveScaffold::ReverseAssociationRequired, "Association #{a.name} in class #{parent_record.class.name}: In order to support :has_one and :has_many where the parent record is new and the child record(s) validate the presence of the parent, ActiveScaffold requires the reverse association (the belongs_to)." unless a.reverse
72
72
 
@@ -100,11 +100,18 @@ module ActiveScaffold
100
100
 
101
101
  def column_value_from_param_simple_value(parent_record, column, value)
102
102
  if column.singular_association?
103
- # it's a single id
104
- column.association.klass.find(value) if value and not value.empty?
103
+ if value.present?
104
+ if column.polymorphic_association?
105
+ class_name = parent_record.send(column.association.foreign_type)
106
+ class_name.constantize.find(value) if class_name
107
+ else
108
+ # it's a single id
109
+ column.association.klass.find(value)
110
+ end
111
+ end
105
112
  elsif column.plural_association?
106
113
  column_plural_assocation_value_from_value(column, Array(value))
107
- elsif column.number? && [:i18n_number, :currency].include?(column.options[:format])
114
+ elsif column.number? && [:i18n_number, :currency].include?(column.options[:format]) && column.form_ui != :number
108
115
  self.class.i18n_number_to_native_format(value)
109
116
  else
110
117
  # convert empty strings into nil. this works better with 'null => true' columns (and validations),
@@ -118,7 +125,7 @@ module ActiveScaffold
118
125
  def column_plural_assocation_value_from_value(column, value)
119
126
  # it's an array of ids
120
127
  if value and not value.empty?
121
- ids = value.select {|id| id.respond_to?(:empty?) ? !id.empty? : true}
128
+ ids = value.select {|id| id.present?}
122
129
  ids.empty? ? [] : column.association.klass.find(ids)
123
130
  end
124
131
  end
@@ -137,7 +144,7 @@ module ActiveScaffold
137
144
  manage_nested_record_from_params(parent_record, column, value)
138
145
  elsif column.plural_association?
139
146
  # HACK to be able to delete all associated records, hash will include "0" => ""
140
- value.collect {|key, value| manage_nested_record_from_params(parent_record, column, value) unless value == ""}.compact
147
+ value.sort.collect {|key, value| manage_nested_record_from_params(parent_record, column, value) unless value == ""}.compact
141
148
  else
142
149
  value
143
150
  end
@@ -190,7 +197,7 @@ module ActiveScaffold
190
197
  if value.is_a?(Hash)
191
198
  attributes_hash_is_empty?(value, klass)
192
199
  elsif value.is_a?(Array)
193
- value.all?(&:blank?)
200
+ value.any? {|id| id.respond_to?(:empty?) ? !id.empty? : true}
194
201
  else
195
202
  value.respond_to?(:empty?) ? value.empty? : false
196
203
  end
@@ -3,7 +3,7 @@ class ActiveScaffold::Bridges::CalendarDateSelect < ActiveScaffold::DataStructur
3
3
  # check to see if the old bridge was installed. If so, warn them
4
4
  # we can detect this by checking to see if the bridge was installed before calling this code
5
5
 
6
- if ActiveScaffold::Config::Core.instance_methods.include?("initialize_with_calendar_date_select".send(::ActiveScaffold::METHOD_CONVERSION))
6
+ if ActiveScaffold::Config::Core.instance_methods.include?("initialize_with_calendar_date_select")
7
7
  raise RuntimeError, "We've detected that you have active_scaffold_calendar_date_select_bridge installed. This plugin has been moved to core. Please remove active_scaffold_calendar_date_select_bridge to prevent any conflicts"
8
8
  end
9
9
 
@@ -11,8 +11,7 @@ module CanCan
11
11
  module Ability
12
12
  def as_action_aliases
13
13
  alias_action :list, :row, :show_search, :render_field, :to => :read
14
- alias_action :update_column, :add_association, :edit_associated,
15
- :edit_associated, :new_existing, :add_existing, :to => :update
14
+ alias_action :update_column, :edit_associated, :new_existing, :add_existing, :to => :update
16
15
  alias_action :delete, :destroy_existing, :to => :destroy
17
16
  end
18
17
  end
@@ -1,7 +1,7 @@
1
1
  module ActiveScaffold
2
2
  module Helpers
3
3
  module ListColumnHelpers
4
- def active_scaffold_column_carrierwave(column, record)
4
+ def active_scaffold_column_carrierwave(record, column)
5
5
  carrierwave = record.send("#{column.name}")
6
6
  return nil unless !carrierwave.file.blank?
7
7
  thumbnail_style = ActiveScaffold::Bridges::Carrierwave::CarrierwaveBridgeHelpers.thumbnail_style
@@ -0,0 +1,14 @@
1
+ class ActiveScaffold::Bridges::Chosen < ActiveScaffold::DataStructures::Bridge
2
+ def self.install
3
+ require File.join(File.dirname(__FILE__), "chosen/helpers.rb")
4
+ end
5
+ def self.install?
6
+ super && [:jquery, :prototype].include?(ActiveScaffold.js_framework)
7
+ end
8
+ def self.stylesheets
9
+ 'chosen'
10
+ end
11
+ def self.javascripts
12
+ ["chosen-#{ActiveScaffold.js_framework}", "#{ActiveScaffold.js_framework}/active_scaffold_chosen"]
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ class ActiveScaffold::Bridges::Chosen
2
+ module Helpers
3
+ def self.included(base)
4
+ base.class_eval do
5
+ include FormColumnHelpers
6
+ include SearchColumnHelpers
7
+ end
8
+ end
9
+
10
+ module FormColumnHelpers
11
+ # requires RecordSelect plugin to be installed and configured.
12
+ def active_scaffold_input_chosen(column, html_options)
13
+ html_options[:class] << ' chosen'
14
+ if column.plural_association?
15
+ associated_options, select_options = active_scaffold_plural_association_options(column)
16
+ options = {:selected => associated_options.collect {|a| a[1]}, :include_blank => as_(:_select_)}
17
+
18
+ html_options.update(:multiple => true).update(column.options[:html_options] || {})
19
+ options.update(column.options)
20
+ html_options[:name] = "#{html_options[:name]}[]" if html_options[:multiple] == true && !html_options[:name].to_s.ends_with?("[]")
21
+
22
+ if optgroup = options.delete(:optgroup)
23
+ select(:record, column.name, grouped_options_for_select(column, select_options, optgroup), options, html_options)
24
+ else
25
+ collection_select(:record, column.name, select_options, :id, :to_label, options, html_options)
26
+ end
27
+ else
28
+ active_scaffold_input_select(column, html_options)
29
+ end
30
+ end
31
+ end
32
+
33
+ module SearchColumnHelpers
34
+ def active_scaffold_search_chosen(column, options)
35
+ options[:class] << ' chosen'
36
+ active_scaffold_search_select(column, options)
37
+ end
38
+
39
+ def active_scaffold_search_multi_chosen(column, options)
40
+ options[:class] << ' chosen'
41
+ options[:multiple] = true
42
+ active_scaffold_search_select(column, options)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ ActionView::Base.class_eval { include ActiveScaffold::Bridges::Chosen::Helpers }