active_scaffold 3.0.4 → 3.0.5

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 (33) hide show
  1. data/CHANGELOG +5 -0
  2. data/active_scaffold.gemspec +1 -1
  3. data/frontends/default/stylesheets/stylesheet.css +40 -2
  4. data/lib/active_scaffold.rb +111 -21
  5. data/lib/active_scaffold/actions/nested.rb +5 -1
  6. data/lib/active_scaffold/actions/subform.rb +4 -1
  7. data/lib/active_scaffold/attribute_params.rb +4 -4
  8. data/lib/active_scaffold/bridges/bridge.rb +2 -5
  9. data/lib/active_scaffold/config/list.rb +9 -9
  10. data/lib/active_scaffold/config/update.rb +1 -1
  11. data/lib/active_scaffold/data_structures/action_links.rb +4 -3
  12. data/lib/active_scaffold/finder.rb +13 -13
  13. data/lib/active_scaffold/helpers/controller_helpers.rb +5 -3
  14. data/lib/active_scaffold/helpers/country_helpers.rb +263 -257
  15. data/lib/active_scaffold/helpers/form_column_helpers.rb +5 -5
  16. data/lib/active_scaffold/helpers/id_helpers.rb +2 -2
  17. data/lib/active_scaffold/helpers/search_column_helpers.rb +11 -11
  18. data/lib/active_scaffold/helpers/view_helpers.rb +15 -15
  19. data/lib/active_scaffold/marked_model.rb +6 -6
  20. data/lib/extensions/action_view_rendering.rb +5 -5
  21. data/lib/extensions/active_record_offset.rb +7 -7
  22. data/lib/extensions/localize.rb +1 -1
  23. data/lib/extensions/name_option_for_datetime.rb +1 -1
  24. data/lib/extensions/paginator_extensions.rb +2 -2
  25. data/lib/extensions/reverse_associations.rb +1 -1
  26. data/lib/extensions/routing_mapper.rb +2 -2
  27. data/lib/extensions/usa_state.rb +15 -11
  28. data/lib/generators/active_scaffold/active_scaffold_generator.rb +5 -5
  29. data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +2 -2
  30. data/lib/generators/active_scaffold_setup/active_scaffold_setup_generator.rb +10 -10
  31. metadata +4 -6
  32. data/environment.rb +0 -24
  33. data/install_assets.rb +0 -44
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ = 3.0.5
2
+
3
+ - switch from explicit requires to autoloading
4
+ - get nested action links up and running
5
+
1
6
  = 3.0.4
2
7
 
3
8
  - Fix a typo that made 3.0.3 unusable.
@@ -2,7 +2,7 @@ $:.push File.expand_path("../lib", __FILE__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "active_scaffold"
5
- s.version = "3.0.4"
5
+ s.version = "3.0.5"
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.authors = ["Many, see README"]
8
8
  s.email = ["activescaffold@googlegroups.com"]
@@ -264,7 +264,8 @@ text-align: right;
264
264
  padding: 0 2px;
265
265
  }
266
266
 
267
- .active-scaffold tr.record td.actions a {
267
+ .active-scaffold tr.record td.actions a,
268
+ .active-scaffold tr.record td.actions span {
268
269
  font: bold 11px verdana, sans-serif;
269
270
  letter-spacing: -1px;
270
271
  padding: 2px;
@@ -273,6 +274,43 @@ line-height: 16px;
273
274
  white-space: nowrap;
274
275
  }
275
276
 
277
+ .active-scaffold tr.record td.actions td.action_list {
278
+ position:relative;
279
+ text-align: left;
280
+ color: #0066CC;
281
+ }
282
+
283
+ .active-scaffold tr.record td.actions .action_list ul {
284
+ border:medium none;
285
+ list-style-type:none;
286
+ margin:0;
287
+ padding:0;
288
+ position:absolute;
289
+ line-height:200%;
290
+ display: none;
291
+ width:100%;
292
+ }
293
+
294
+ .active-scaffold tr.record td.actions .action_list ul li {
295
+ background:none repeat scroll 0 0 #FFF;
296
+ border-bottom:1px solid #AFD0F5;
297
+ border-left:1px solid #AFD0F5;
298
+ border-right:1px solid #AFD0F5;
299
+ color:#000000;
300
+ display:block;
301
+ padding-bottom:5px;
302
+ position:relative;
303
+ width:160px;
304
+ z-index: 2;
305
+ }
306
+
307
+ .active-scaffold tr.record td.actions td.action_list:hover ul {
308
+ display:block;
309
+ }
310
+
311
+
312
+
313
+
276
314
  /* Table :: Inline Adapter
277
315
  ============================= */
278
316
 
@@ -625,7 +663,6 @@ letter-spacing: 0;
625
663
 
626
664
  .active-scaffold li.form-element {
627
665
  clear: both;
628
- padding-top: 2px;
629
666
  }
630
667
 
631
668
  .active-scaffold label {
@@ -653,6 +690,7 @@ margin: 0;
653
690
 
654
691
 
655
692
  .active-scaffold .description {
693
+ display: inline-block;
656
694
  color: #999;
657
695
  font-size: 10px;
658
696
  margin-left: 5px;
@@ -1,3 +1,7 @@
1
+ unless Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR >= 0
2
+ raise "This version of ActiveScaffold requires Rails 3.0 or higher. Please use an earlier version."
3
+ end
4
+
1
5
  require 'render_component' rescue nil
2
6
  require 'verification'
3
7
 
@@ -5,18 +9,43 @@ require 'active_record_permissions'
5
9
  require 'dhtml_confirm'
6
10
  require 'paginator'
7
11
  require 'responds_to_parent'
8
- require 'active_scaffold/attribute_params'
9
- require 'active_scaffold/configurable'
10
- require 'active_scaffold/constraints'
11
- require 'active_scaffold/finder'
12
- require 'active_scaffold/marked_model'
13
- require 'active_scaffold/config/base'
14
- require 'active_scaffold/data_structures/column'
15
- require 'active_scaffold/data_structures/actions'
16
- require 'active_scaffold/data_structures/action_links'
17
- require 'active_scaffold/config/form'
18
12
 
19
13
  module ActiveScaffold
14
+ autoload :AttributeParams, 'active_scaffold/attribute_params'
15
+ autoload :Configurable, 'active_scaffold/configurable'
16
+ autoload :Constraints, 'active_scaffold/constraints'
17
+ autoload :Finder, 'active_scaffold/finder'
18
+ autoload :MarkedModel, 'active_scaffold/marked_model'
19
+
20
+ def self.active_scaffold_autoload_subdir(dir, mod=self)
21
+ Dir["#{File.dirname(__FILE__)}/active_scaffold/#{dir}/*.rb"].each { |file|
22
+ basename = File.basename(file, ".rb")
23
+ mod.module_eval {
24
+ autoload basename.camelcase.to_sym, "active_scaffold/#{dir}/#{basename}"
25
+ }
26
+ }
27
+ end
28
+
29
+ module Actions
30
+ ActiveScaffold.active_scaffold_autoload_subdir('actions', self)
31
+ end
32
+
33
+ module Bridges
34
+ autoload :Bridge, 'active_scaffold/bridges/bridge'
35
+ end
36
+
37
+ module Config
38
+ ActiveScaffold.active_scaffold_autoload_subdir('config', self)
39
+ end
40
+
41
+ module DataStructures
42
+ ActiveScaffold.active_scaffold_autoload_subdir('data_structures', self)
43
+ end
44
+
45
+ module Helpers
46
+ ActiveScaffold.active_scaffold_autoload_subdir('helpers', self)
47
+ end
48
+
20
49
  class ControllerNotFound < RuntimeError; end
21
50
  class DependencyFailure < RuntimeError; end
22
51
  class MalformedConstraint < RuntimeError; end
@@ -71,6 +100,58 @@ module ActiveScaffold
71
100
  @@js_framework ||= :prototype
72
101
  end
73
102
 
103
+ ##
104
+ ## Copy over asset files (javascript/css/images) from directory to public/
105
+ ##
106
+ def self.install_assets_from(directory)
107
+ copy_files("/public", "/public", directory)
108
+
109
+ available_frontends = Dir[File.join(directory, 'frontends', '*')].map { |d| File.basename d }
110
+ [:stylesheets, :javascripts, :images].each do |asset_type|
111
+ path = "/public/#{asset_type}/active_scaffold"
112
+ copy_files(path, path, directory)
113
+
114
+ File.open(File.join(Rails.root, path, 'DO_NOT_EDIT'), 'w') do |f|
115
+ f.puts "Any changes made to files in sub-folders will be lost."
116
+ f.puts "See http://activescaffold.com/tutorials/faq#custom-css."
117
+ end
118
+
119
+ available_frontends.each do |frontend|
120
+ if asset_type == :javascripts
121
+ file_mask = '*.js'
122
+ source = "/frontends/#{frontend}/#{asset_type}/#{ActiveScaffold.js_framework}"
123
+ else
124
+ file_mask = '*.*'
125
+ source = "/frontends/#{frontend}/#{asset_type}"
126
+ end
127
+ destination = "/public/#{asset_type}/active_scaffold/#{frontend}"
128
+ copy_files(source, destination, directory, file_mask)
129
+ end
130
+ end
131
+ end
132
+
133
+ def self.root
134
+ File.dirname(__FILE__) + "/.."
135
+ end
136
+
137
+ def self.delete_stale_assets
138
+ available_frontends = Dir[File.join(root, 'frontends', '*')].map { |d| File.basename d }
139
+ [:stylesheets, :javascripts, :images].each do |asset_type|
140
+ available_frontends.each do |frontend|
141
+ destination = File.join(Rails.root, "/public/#{asset_type}/active_scaffold/#{frontend}")
142
+ FileUtils.rm Dir.glob("#{destination}/*")
143
+ end
144
+ end
145
+ end
146
+
147
+ private
148
+ def self.copy_files(source_path, destination_path, directory, file_mask = '*.*')
149
+ source, destination = File.join(directory, source_path), File.join(Rails.root, destination_path)
150
+ FileUtils.mkdir_p(destination) unless File.exist?(destination)
151
+
152
+ FileUtils.cp_r(Dir.glob("#{source}/#{file_mask}"), destination)
153
+ end
154
+
74
155
  module ClassMethods
75
156
  def active_scaffold(model_id = nil, &block)
76
157
  # initialize bridges here
@@ -228,8 +309,10 @@ module ActiveScaffold
228
309
  end
229
310
 
230
311
  # Tries to find a controller for the given ActiveRecord model.
231
- # Searches in the namespace of the current controller for singular and plural versions of the conventional "#{model}Controller" syntax.
232
- # You may override this method to customize the search routine.
312
+ # Searches in the namespace of the current controller for singular
313
+ # and plural versions of the conventional "#{model}Controller"
314
+ # syntax. You may override this method to customize the search
315
+ # routine.
233
316
  def active_scaffold_controller_for(klass)
234
317
  controller_namespace = self.to_s.split('::')[0...-1].join('::') + '::'
235
318
  error_message = []
@@ -260,22 +343,29 @@ module ActiveScaffold
260
343
  end
261
344
  end
262
345
 
263
- ##
264
- ## Initialize the environment
265
- ##
266
- unless Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR >= 0
267
- raise "This version of ActiveScaffold requires Rails 3.0 or higher. Please use an earlier version."
268
- end
346
+ # TODO: clean up extensions. some could be organized for autoloading, and others could be removed entirely.
347
+ Dir["#{File.dirname __FILE__}/extensions/*.rb"].each { |file| require file }
348
+
349
+ ActionController::Base.send(:include, ActiveScaffold)
350
+ ActionController::Base.send(:include, RespondsToParent)
351
+ ActionController::Base.send(:include, ActiveScaffold::Helpers::ControllerHelpers)
352
+ ActionView::Base.send(:include, ActiveScaffold::Helpers::ViewHelpers)
353
+
354
+ ActionController::Base.class_eval {include ActiveRecordPermissions::ModelUserAccess::Controller}
355
+ ActiveRecord::Base.class_eval {include ActiveRecordPermissions::ModelUserAccess::Model}
356
+ ActiveRecord::Base.class_eval {include ActiveRecordPermissions::Permissions}
269
357
 
270
- require File.dirname(__FILE__) + '/../environment'
358
+ I18n.load_path += Dir[File.join(File.dirname(__FILE__), 'active_scaffold', 'locale', '*.{rb,yml}')]
359
+ #ActiveScaffold.js_framework = :jquery
271
360
 
272
361
  ##
273
362
  ## Run the install assets script, too, just to make sure
274
363
  ## But at least rescue the action in production
275
364
  ##
276
- Rails::Application.initializer("active_scaffold_install_assets") do
365
+ Rails::Application.initializer("active_scaffold.install_assets") do
277
366
  begin
278
- require File.dirname(__FILE__) + '/../install_assets'
367
+ ActiveScaffold.delete_stale_assets
368
+ ActiveScaffold.install_assets_from(ActiveScaffold.root)
279
369
  rescue
280
370
  raise $! unless Rails.env == 'production'
281
371
  end
@@ -1,5 +1,9 @@
1
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).
2
+ # The Nested module basically handles automatically linking
3
+ # controllers together. It does this by creating column links with
4
+ # the right parameters, and by providing any supporting systems
5
+ # (like a /:controller/nested action for returning associated
6
+ # scaffolds).
3
7
  module Nested
4
8
 
5
9
  def self.included(base)
@@ -4,7 +4,10 @@ module ActiveScaffold::Actions
4
4
  @parent_record = params[:id].nil? ? active_scaffold_config.model.new : find_if_allowed(params[:id], :update)
5
5
  @column = active_scaffold_config.columns[params[:association]]
6
6
 
7
- # 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.
7
+ # NOTE: we don't check whether the user is allowed to update
8
+ # this record, because if not, we'll still let them associate
9
+ # the record. we'll just refuse to do more than associate, is
10
+ # all.
8
11
  @record = @column.association.klass.find(params[:associated_id]) if params[:associated_id]
9
12
  @record ||= @column.association.klass.new
10
13
 
@@ -56,11 +56,11 @@ module ActiveScaffold
56
56
  if multi_parameter_attributes.has_key? column.name
57
57
  parent_record.send(:assign_multiparameter_attributes, multi_parameter_attributes[column.name])
58
58
  elsif attributes.has_key? column.name
59
- value = column_value_from_param_value(parent_record, column, attributes[column.name])
59
+ value = column_value_from_param_value(parent_record, column, attributes[column.name])
60
60
 
61
61
  # we avoid assigning a value that already exists because otherwise has_one associations will break (AR bug in has_one_association.rb#replace)
62
62
  parent_record.send("#{column.name}=", value) unless parent_record.send(column.name) == value
63
-
63
+
64
64
  # plural associations may not actually appear in the params if all of the options have been unselected or cleared away.
65
65
  # the "form_ui" check is necessary, becuase without it we have problems
66
66
  # with subforms. the UI cuts out deep associations, which means they're not present in the
@@ -85,7 +85,7 @@ module ActiveScaffold
85
85
 
86
86
  parent_record
87
87
  end
88
-
88
+
89
89
  def manage_nested_record_from_params(parent_record, column, attributes)
90
90
  record = find_or_create_for_params(attributes, column, parent_record)
91
91
  if record
@@ -95,7 +95,7 @@ module ActiveScaffold
95
95
  end
96
96
  record
97
97
  end
98
-
98
+
99
99
  def column_value_from_param_value(parent_record, column, value)
100
100
  # convert the value, possibly by instantiating associated objects
101
101
  if value.is_a?(Hash)
@@ -37,11 +37,8 @@ module ActiveScaffold
37
37
  end
38
38
 
39
39
  def self.run_all
40
- return false if self.bridges_run
41
- ActiveScaffold::Bridges::Bridge.bridges.each{|bridge|
42
- bridge.run
43
- }
44
- self.bridges_run=true
40
+ self.bridges.each(&:run) unless self.bridges_run
41
+ self.bridges_run = true
45
42
  end
46
43
  end
47
44
  end
@@ -9,7 +9,7 @@ module ActiveScaffold::Config
9
9
  # full configuration path is: defaults => global table => local table
10
10
  @per_page = self.class.per_page
11
11
  @page_links_window = self.class.page_links_window
12
-
12
+
13
13
  # originates here
14
14
  @sorting = ActiveScaffold::DataStructures::Sorting.new(@core.columns)
15
15
  @sorting.set_default_sorting(@core.model)
@@ -49,7 +49,7 @@ module ActiveScaffold::Config
49
49
  self.columns = @core.columns._inheritable unless @columns # lazy evaluation
50
50
  @columns
51
51
  end
52
-
52
+
53
53
  public :columns=
54
54
 
55
55
  # how many rows to show at once
@@ -79,7 +79,7 @@ module ActiveScaffold::Config
79
79
  def sorting
80
80
  @sorting ||= ActiveScaffold::DataStructures::Sorting.new(@core.columns)
81
81
  end
82
-
82
+
83
83
  # overwrite the includes used for the count sql query
84
84
  attr_accessor :count_includes
85
85
 
@@ -98,29 +98,29 @@ module ActiveScaffold::Config
98
98
  def filtered_message
99
99
  @filtered_message ? @filtered_message : :filtered
100
100
  end
101
-
101
+
102
102
  attr_writer :always_show_search
103
103
  def always_show_search
104
104
  @always_show_search && !search_partial.blank?
105
105
  end
106
-
106
+
107
107
  def search_partial
108
108
  return "search" if @core.actions.include?(:search)
109
109
  return "field_search" if @core.actions.include?(:field_search)
110
110
  end
111
-
111
+
112
112
  # always show create
113
113
  attr_writer :always_show_create
114
114
  def always_show_create
115
115
  @always_show_create && @core.actions.include?(:create)
116
116
  end
117
-
117
+
118
118
  # might be set to open nested_link automatically in view
119
119
  # conf.nested.add_link(:players)
120
120
  # conf.list.nested_auto_open = {:players => 2}
121
121
  # will open nested players view if there are 2 or less records in parent
122
122
  attr_accessor :nested_auto_open
123
-
123
+
124
124
  class UserSettings < UserSettings
125
125
  # This label has alread been localized.
126
126
  def label
@@ -165,7 +165,7 @@ module ActiveScaffold::Config
165
165
  return default_sorting
166
166
  end
167
167
  end
168
-
168
+
169
169
  def count_includes
170
170
  @conf.count_includes
171
171
  end
@@ -33,6 +33,6 @@ module ActiveScaffold::Config
33
33
  def hide_nested_column
34
34
  @hide_nested_column.nil? ? true : @hide_nested_column
35
35
  end
36
-
36
+
37
37
  end
38
38
  end
@@ -73,12 +73,13 @@ module ActiveScaffold::DataStructures
73
73
  end
74
74
 
75
75
  def traverse(controller, options = {}, &block)
76
- @set.each do |link|
76
+ traverse_method = options.delete(:reverse).nil? ? :each : :reverse_each
77
+ @set.send(traverse_method) do |link|
77
78
  if link.is_a?(ActiveScaffold::DataStructures::ActionLinks)
78
79
  # add top node only if there is anything in the list
79
80
  #yield({:kind => :node, :level => 1, :last => false, :link => link})
80
81
  yield(link, nil, {:node => :start_traversing})
81
- link.traverse(options, &block)
82
+ link.traverse(controller,options, &block)
82
83
  yield(link, nil, {:node => :finished_traversing})
83
84
  #yield({:kind => :completed_group, :level => 1, :last => false, :link => link})
84
85
  elsif controller.nil? || !skip_action_link(controller, link, options[:record])
@@ -89,7 +90,7 @@ module ActiveScaffold::DataStructures
89
90
  end
90
91
 
91
92
  def collect
92
- @set.collect
93
+ @set
93
94
  end
94
95
 
95
96
  def empty?
@@ -98,7 +98,7 @@ module ActiveScaffold
98
98
  nil
99
99
  end
100
100
  end
101
-
101
+
102
102
  def condition_value_for_datetime(value, conversion = :to_time)
103
103
  if value.is_a? Hash
104
104
  Time.zone.local(*[:year, :month, :day, :hour, :minute, :second].collect {|part| value[field][part].to_i}) rescue nil
@@ -132,7 +132,7 @@ module ActiveScaffold
132
132
  value
133
133
  end
134
134
  end
135
-
135
+
136
136
  def condition_for_datetime(column, value, like_pattern = nil)
137
137
  conversion = column.column.type == :date ? :to_date : :to_time
138
138
  from_value = condition_value_for_datetime(value[:from], conversion)
@@ -156,7 +156,7 @@ module ActiveScaffold
156
156
  ["#{column.search_sql} = ?", value]
157
157
  end
158
158
  end
159
-
159
+
160
160
  def condition_for_null_type(column, value, like_pattern = nil)
161
161
  case value.to_sym
162
162
  when :null
@@ -196,8 +196,8 @@ module ActiveScaffold
196
196
  :null,
197
197
  :not_null
198
198
  ]
199
-
200
-
199
+
200
+
201
201
 
202
202
  def self.included(klass)
203
203
  klass.extend ClassMethods
@@ -219,7 +219,7 @@ module ActiveScaffold
219
219
  def active_scaffold_habtm_joins
220
220
  @active_scaffold_habtm_joins ||= []
221
221
  end
222
-
222
+
223
223
  def all_conditions
224
224
  merge_conditions(
225
225
  active_scaffold_conditions, # from the search modules
@@ -229,7 +229,7 @@ module ActiveScaffold
229
229
  active_scaffold_session_storage[:conditions] # embedding conditions (weaker constraints)
230
230
  )
231
231
  end
232
-
232
+
233
233
  # returns a single record (the given id) but only if it's allowed for the specified action.
234
234
  # accomplishes this by checking model.#{action}_authorized?
235
235
  # TODO: this should reside on the model, not the controller
@@ -255,19 +255,19 @@ module ActiveScaffold
255
255
  options[:count_includes] ||= full_includes unless search_conditions.nil?
256
256
 
257
257
  klass = beginning_of_chain
258
-
258
+
259
259
  # create a general-use options array that's compatible with Rails finders
260
260
  finder_options = { :order => options[:sorting].try(:clause),
261
261
  :where => search_conditions,
262
262
  :joins => joins_for_finder,
263
263
  :includes => options[:count_includes]}
264
-
264
+
265
265
  finder_options.merge! custom_finder_options
266
266
 
267
267
  # NOTE: we must use :include in the count query, because some conditions may reference other tables
268
268
  count_query = append_to_query(klass, finder_options.reject{|k, v| [:select, :order].include?(k)})
269
269
  count = count_query.count unless options[:pagination] == :infinite
270
-
270
+
271
271
  # Converts count to an integer if ActiveRecord returned an OrderedHash
272
272
  # that happens when finder_options contains a :group key
273
273
  count = count.length if count.is_a? ActiveSupport::OrderedHash
@@ -288,11 +288,11 @@ module ActiveScaffold
288
288
  end
289
289
  pager.page(options[:page])
290
290
  end
291
-
291
+
292
292
  def append_to_query(query, options)
293
293
  options.assert_valid_keys :where, :select, :group, :order, :limit, :offset, :joins, :includes, :lock, :readonly, :from
294
294
  options.reject{|k, v| v.blank?}.inject(query) do |query, (k, v)|
295
- query.send((k.to_sym), v)
295
+ query.send((k.to_sym), v)
296
296
  end
297
297
  end
298
298
 
@@ -306,7 +306,7 @@ module ActiveScaffold
306
306
  []
307
307
  end + active_scaffold_habtm_joins
308
308
  end
309
-
309
+
310
310
  def merge_conditions(*conditions)
311
311
  segments = []
312
312
  conditions.each do |condition|