Module: ActiveScaffold::ClassMethods

Defined in:
lib/active_scaffold.rb

Instance Method Summary collapse

Instance Method Details

To be called after include action modules



214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/active_scaffold.rb', line 214

def _add_sti_create_links
  new_action_link = active_scaffold_config.action_links.collection['new']
  unless new_action_link.nil? || active_scaffold_config.sti_children.empty?
    active_scaffold_config.action_links.collection.delete('new')
    active_scaffold_config.sti_children.each do |child|
      new_sti_link = Marshal.load(Marshal.dump(new_action_link)) # deep clone
      new_sti_link.label = child.to_s.camelize.constantize.model_name.human
      new_sti_link.parameters = {:parent_sti => controller_path}
      new_sti_link.controller = Proc.new { active_scaffold_controller_for(child.to_s.camelize.constantize).controller_path }
      active_scaffold_config.action_links.collection.create.add(new_sti_link)
    end
  end
end

#active_scaffold(model_id = nil, &block) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/active_scaffold.rb', line 151

def active_scaffold(model_id = nil, &block)
  # initialize bridges here
  ActiveScaffold::Bridges::Bridge.run_all

  # converts Foo::BarController to 'bar' and FooBarsController to 'foo_bar' and AddressController to 'address'
  model_id = self.to_s.split('::').last.sub(/Controller$/, '').pluralize.singularize.underscore unless model_id

  # run the configuration
  @active_scaffold_config = ActiveScaffold::Config::Core.new(model_id)
  @active_scaffold_config_block = block
  self.links_for_associations

  @active_scaffold_overrides = []
  ActionController::Base.view_paths.each do |dir|
    active_scaffold_overrides_dir = File.join(dir.to_s,"active_scaffold_overrides")
    @active_scaffold_overrides << active_scaffold_overrides_dir if File.exists?(active_scaffold_overrides_dir)
  end
  @active_scaffold_overrides.uniq! # Fix rails duplicating some view_paths
  @active_scaffold_frontends = []
  if active_scaffold_config.frontend.to_sym != :default
    active_scaffold_custom_frontend_path = File.join(ActiveScaffold::Config::Core.plugin_directory, 'frontends', active_scaffold_config.frontend.to_s , 'views')
    @active_scaffold_frontends << active_scaffold_custom_frontend_path
  end
  active_scaffold_default_frontend_path = File.join(ActiveScaffold::Config::Core.plugin_directory, 'frontends', 'default' , 'views')
  @active_scaffold_frontends << active_scaffold_default_frontend_path
  @active_scaffold_custom_paths = []

  self.active_scaffold_superclasses_blocks.each {|superblock| self.active_scaffold_config.configure &superblock}
  self.active_scaffold_config.sti_children = nil # reset sti_children if set in parent block
  self.active_scaffold_config.configure &block if block_given?
  self.active_scaffold_config._configure_sti unless self.active_scaffold_config.sti_children.nil?
  self.active_scaffold_config._load_action_columns

  # defines the attribute read methods on the model, so record.send() doesn't find protected/private methods instead
  klass = self.active_scaffold_config.model
  klass.define_attribute_methods unless klass.attribute_methods_generated?
  # include the rest of the code into the controller: the action core and the included actions
  module_eval do
    include ActiveScaffold::Finder
    include ActiveScaffold::Constraints
    include ActiveScaffold::AttributeParams
    include ActiveScaffold::Actions::Core
    active_scaffold_config.actions.each do |mod|
      name = mod.to_s.camelize
      include "ActiveScaffold::Actions::#{name}".constantize

      # sneak the action links from the actions into the main set
      if link = active_scaffold_config.send(mod).link rescue nil
        if link.is_a? Array
          link.each {|current| active_scaffold_config.action_links.add_to_group(current, active_scaffold_config.send(mod).action_group)}
        elsif link.is_a? ActiveScaffold::DataStructures::ActionLink
          active_scaffold_config.action_links.add_to_group(link, active_scaffold_config.send(mod).action_group)
        end
      end
    end
  end
  active_scaffold_paths.each do |path|
    self.append_view_path(ActionView::ActiveScaffoldResolver.new(path))
  end
  self._add_sti_create_links if self.active_scaffold_config.add_sti_create_links?
end

#active_scaffold_configObject



304
305
306
307
308
309
310
# File 'lib/active_scaffold.rb', line 304

def active_scaffold_config
  if @active_scaffold_config.nil?
    self.superclass.active_scaffold_config if self.superclass.respond_to? :active_scaffold_config
  else
    @active_scaffold_config
  end
end

#active_scaffold_config_blockObject



312
313
314
# File 'lib/active_scaffold.rb', line 312

def active_scaffold_config_block
  @active_scaffold_config_block
end

#active_scaffold_config_for(klass) ⇒ Object



326
327
328
329
330
331
332
333
334
335
336
# File 'lib/active_scaffold.rb', line 326

def active_scaffold_config_for(klass)
  begin
    controller = active_scaffold_controller_for(klass)
  rescue ActiveScaffold::ControllerNotFound
    config = ActiveScaffold::Config::Core.new(klass)
    config._load_action_columns
    config
  else
    controller.active_scaffold_config
  end
end

#active_scaffold_controller_for(klass) ⇒ Object

Tries to find a controller for the given ActiveRecord model. Searches in the namespace of the current controller for singular and plural versions of the conventional “#modelController” syntax. You may override this method to customize the search routine.



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/active_scaffold.rb', line 341

def active_scaffold_controller_for(klass)
  controller_namespace = self.to_s.split('::')[0...-1].join('::') + '::'
  error_message = []
  klass = klass.to_s.singularize.camelize.constantize unless klass.is_a? Class
  [controller_namespace, ''].each do |namespace|
    ["#{klass.to_s.underscore.pluralize}", "#{klass.to_s.underscore.pluralize.singularize}"].each do |controller_name|
      begin
        controller = "#{namespace}#{controller_name.camelize}Controller".constantize
      rescue NameError => error
        # Only rescue NameError associated with the controller constant not existing - not other compile errors
        if error.message["uninitialized constant #{controller}"]
          error_message << "#{namespace}#{controller_name.camelize}Controller"
          next
        else
          raise
        end
      end
      raise ActiveScaffold::ControllerNotFound, "#{controller} missing ActiveScaffold", caller unless controller.uses_active_scaffold?
      raise ActiveScaffold::ControllerNotFound, "ActiveScaffold on #{controller} is not for #{klass} model.", caller unless controller.active_scaffold_config.model == klass
      return controller
    end
  end
  raise ActiveScaffold::ControllerNotFound, "Could not find " + error_message.join(" or "), caller
end

#active_scaffold_controller_for_column(column, options = {}) ⇒ Object



240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/active_scaffold.rb', line 240

def active_scaffold_controller_for_column(column, options = {})
  begin
    if column.polymorphic_association?
      :polymorph
    elsif options.include?(:controller)
      "#{options[:controller].to_s.camelize}Controller".constantize
    else
      active_scaffold_controller_for(column.association.klass)
    end
  rescue ActiveScaffold::ControllerNotFound
    nil        
  end
end

#active_scaffold_pathsObject



293
294
295
296
297
298
299
300
301
302
# File 'lib/active_scaffold.rb', line 293

def active_scaffold_paths
  return @active_scaffold_paths unless @active_scaffold_paths.nil?

  #@active_scaffold_paths = ActionView::PathSet.new
  @active_scaffold_paths = []
  @active_scaffold_paths.concat @active_scaffold_overrides unless @active_scaffold_overrides.nil?
  @active_scaffold_paths.concat @active_scaffold_custom_paths unless @active_scaffold_custom_paths.nil?
  @active_scaffold_paths.concat @active_scaffold_frontends unless @active_scaffold_frontends.nil?
  @active_scaffold_paths
end

#active_scaffold_superclasses_blocksObject



316
317
318
319
320
321
322
323
324
# File 'lib/active_scaffold.rb', line 316

def active_scaffold_superclasses_blocks
  blocks = []
  klass = self.superclass
  while klass.respond_to? :active_scaffold_superclasses_blocks
    blocks << klass.active_scaffold_config_block
    klass = klass.superclass
  end
  blocks.compact.reverse
end

#add_active_scaffold_override_path(path) ⇒ Object



288
289
290
291
# File 'lib/active_scaffold.rb', line 288

def add_active_scaffold_override_path(path)
  @active_scaffold_paths = nil # Force active_scaffold_paths to rebuild
  @active_scaffold_overrides.unshift path
end

#add_active_scaffold_path(path) ⇒ Object



283
284
285
286
# File 'lib/active_scaffold.rb', line 283

def add_active_scaffold_path(path)
  @active_scaffold_paths = nil # Force active_scaffold_paths to rebuild
  @active_scaffold_custom_paths << path
end


254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/active_scaffold.rb', line 254

def link_for_association(column, options = {})
  controller = active_scaffold_controller_for_column(column, options)
  
  unless controller.nil?
    options.reverse_merge! :label => column.label, :position => :after, :type => :member, :controller => (controller == :polymorph ? controller : controller.controller_path), :column => column
    options[:parameters] ||= {}
    options[:parameters].reverse_merge! :parent_scaffold => controller_path, :association => column.association.name
    if column.plural_association?
      # note: we can't create nested scaffolds on :through associations because there's no reverse association.
      
      ActiveScaffold::DataStructures::ActionLink.new('index', options) #unless column.through_association?
    else
      actions = [:create, :update, :show] 
      actions = controller.active_scaffold_config.actions unless controller == :polymorph
      column.actions_for_association_links.delete :new unless actions.include? :create
      column.actions_for_association_links.delete :edit unless actions.include? :update
      column.actions_for_association_links.delete :show unless actions.include? :show
      ActiveScaffold::DataStructures::ActionLink.new(nil, options.merge(:html_options => {:class => column.name}))
    end 
  end
end


276
277
278
279
280
281
# File 'lib/active_scaffold.rb', line 276

def link_for_association_as_scope(scope, options = {})
  options.reverse_merge! :label => scope, :position => :after, :type => :member, :controller => controller_path
  options[:parameters] ||= {}
  options[:parameters].reverse_merge! :parent_scaffold => controller_path, :named_scope => scope
  ActiveScaffold::DataStructures::ActionLink.new('index', options)
end

Create the automatic column links. Note that this has to happen when configuration is done, because otherwise the Nested module could be disabled. Actually, it could still be disabled later, couldn’t it?



229
230
231
232
233
234
235
236
237
238
# File 'lib/active_scaffold.rb', line 229

def links_for_associations
  return unless active_scaffold_config.actions.include? :list and active_scaffold_config.actions.include? :nested
  active_scaffold_config.columns.each do |column|
    next unless column.link.nil? and column.autolink?
    #lazy load of action_link, cause it was really slowing down app in dev mode
    #and might lead to trouble cause of cyclic constantization of controllers
    #and might be unnecessary cause it is done before columns are configured
    column.set_link(Proc.new {|col| link_for_association(col)})
  end
end

#uses_active_scaffold?Boolean

Returns:

  • (Boolean)


366
367
368
# File 'lib/active_scaffold.rb', line 366

def uses_active_scaffold?
  !active_scaffold_config.nil?
end