Module: Merb::Slices::ModuleMixin

Defined in:
merb-slices/lib/merb-slices/module_mixin.rb

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Object) extended(slice_module)



8
9
10
11
12
13
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 8

def self.extended(slice_module)
  slice_module.meta_class.module_eval do
    attr_accessor :identifier, :identifier_sym, :root, :file
    attr_accessor :description, :version, :author
  end
end

Instance Method Details

- (Object) [](key)

Returns The configuration value.

Parameters:

  • The (Symbol)

    configuration key.

Returns:

  • (Object)

    The configuration value.



54
55
56
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 54

def [](key)
  self.config[key]
end

- (Object) []=(key, value)

Parameters:

  • The (Symbol)

    configuration key.

  • The (Object)

    configuration value.



61
62
63
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 61

def []=(key, value)
  self.config[key] = value
end

- (Object) activate

Stub activation hook - runs after AfterAppLoads BootLoader.



28
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 28

def activate; end

- (Array<Symbol>) app_components

Return all application path component types.

Returns:

  • (Array<Symbol>)


271
272
273
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 271

def app_components
  [:view, :model, :controller, :helper, :mailer, :part]
end

- (String) app_dir_for(type)

Retrieve the absolute path to a app-level directory.

Parameters:

  • type (Symbol)

    The type of path to retrieve directory for, e.g. :view.

Returns:

  • (String)

    The directory for the requested type.



152
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 152

def app_dir_for(type) self.app_paths[type].first end

- (String) app_glob_for(type)

Returns The pattern with which to match files within the type directory.

Parameters:

  • type (Symbol)

    The type of path to retrieve glob for, e.g. :view.

Returns:

  • (String)

    The pattern with which to match files within the type directory.



159
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 159

def app_glob_for(type) self.app_paths[type][1] end

- (String) app_path_for(type, *segments)

Construct an app-level path.

Parameters:

  • The (Symbol)

    type of component.

  • *segments (Array<#to_s>)

    Path segments to append.

Returns:

  • (String)

    A path within the host application, with added segments.



192
193
194
195
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 192

def app_path_for(type, *segments)
  prefix = type.is_a?(Symbol) ? self.app_dir_for(type) : self.app_dir_for(:root) / type
  File.join(prefix, *segments)
end

- (Hash) app_paths

The app-level load paths to use when loading the slice.

Returns:

  • (Hash)

    The load paths which make up the app-level structure.



121
122
123
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 121

def app_paths
  @app_paths ||= Hash.new { [Merb.root] }
end

- (Array<Array>) clone_slice!

Clone all files from the slice to their app-level location. This will also copy /lib, causing merb-slices to pick up the slice there.

Returns:

  • (Array<Array>)

    Array of two arrays, one for all copied files, the other for overrides that may have been preserved to resolve collisions.



329
330
331
332
333
334
335
336
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 329

def clone_slice!
  app_slice_root = app_dir_for(:root)
  copied, duplicated = [], []
  manifest.each do |source, relative_path|
    mirror_file(source, app_slice_root / relative_path, copied, duplicated)
  end
  [copied, duplicated]
end

- (Array<String>) collected_app_paths

The app-level load paths that have been used when the slice was loaded.

This may be a subset of app_paths, which includes any path to look for.

Returns:

  • (Array<String>)

    Application load paths (with glob pattern).



107
108
109
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 107

def collected_app_paths
  @collected_app_paths ||= []
end

- (Array<String>) collected_slice_paths

The slice-level load paths that have been used when the slice was loaded.

This may be a subset of app_paths, which includes any path to look for.

Returns:

  • (Array<String>)

    Load paths (with glob pattern).



98
99
100
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 98

def collected_slice_paths
  @collected_slice_paths ||= []
end

- (Hash) config

Returns The configuration for this slice.

Returns:

  • (Hash)

    The configuration for this slice.



66
67
68
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 66

def config
  Merb::Slices::config[self.identifier_sym] ||= {}
end

- (Object) deactivate

Stub deactivation method - not triggered automatically.



31
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 31

def deactivate; end

- (String) dir_for(type)

Retrieve the absolute path to a slice-level directory.

Parameters:

  • type (Symbol)

    The type of path to retrieve directory for, e.g., :view.

Returns:

  • (String)

    The absolute path for the requested type.



137
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 137

def dir_for(type) self.slice_paths[type].first end

- (String) glob_for(type)

Returns The pattern with which to match files within the type directory.

Parameters:

  • type (Symbol)

    The type of path to retrieve glob for, e.g. :view.

Returns:

  • (String)

    The pattern with which to match files within the type directory.



144
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 144

def glob_for(type) self.slice_paths[type][1] end

- (Object) init

Stub initialization hook - runs before AfterAppLoads BootLoader.



25
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 25

def init; end

- (Object) load_slice

Load slice and its classes located in the slice-level load paths.

Assigns collected_slice_paths and collected_app_paths, then loads the collected_slice_paths and triggers the #loaded hook method.



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 79

def load_slice
  # load application.rb (or similar) for thin slices
  Merb::Slices::Loader.load_file self.dir_for(:application) if File.file?(self.dir_for(:application))
  # assign all relevant paths for slice-level and app-level
  self.collect_load_paths
  # load all slice-level classes from paths
  Merb::Slices::Loader.load_classes self.collected_slice_paths
  # call hook if available
  self.loaded if self.respond_to?(:loaded)
  Merb.logger.info!("Loaded slice '#{self}' ...")
rescue => e
  Merb.logger.warn!("Failed loading #{self} (#{e.message})")
end

- (Array<String>) loadable_files

Return all *.rb files from valid component paths.

Returns:

  • (Array<String>)

    Full paths to loadable ruby files.



260
261
262
263
264
265
266
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 260

def loadable_files
  app_components.inject([]) do |paths, type|
    paths += Dir[dir_for(type) / '**/*.rb'] if slice_paths.key?(type)
    paths += Dir[app_dir_for(type) / '**/*.rb'] if app_paths.key?(type)
    paths
  end        
end

- (Object) loaded

Stub classes loaded hook - runs before LoadClasses BootLoader right after a slice's classes have been loaded internally.



22
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 22

def loaded; end

- (Array<Array>) manifest(type = :root)

Return all slice files mapped from the source to their relative path.

Parameters:

  • type (Symbol) (defaults to: :root)

    Which type to use; defaults to all types.

Returns:

  • (Array<Array>)

    An array of arrays [abs. source, relative dest.]



311
312
313
314
315
316
317
318
319
320
321
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 311

def manifest(type = :root)
  files = if type == :root
    Dir.glob(self.root / "**/*")
  elsif slice_paths.key?(type)
    glob = ((type == :view) ? view_templates_glob : glob_for(type) || "**/*")
    Dir.glob(dir_for(type) / glob)
  else 
    []
  end
  files.map { |source| [source, source.relative_path_from(root)] }
end

- (Array<Array>) mirror_all!

Copies all files from mirrored_components to their app-level location. This includes application and public components.

Returns:

  • (Array<Array>)

    Array of two arrays, one for all copied files, the other for overrides that may have been preserved to resolve collisions.



358
359
360
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 358

def mirror_all!
  mirror_files_for mirrored_components + mirrored_public_components
end

- (Array<Array>) mirror_app!

Copies all application files from mirrored_components to their app-level location.

Returns:

  • (Array<Array>)

    Array of two arrays, one for all copied files, the other for overrides that may have been preserved to resolve collisions.



374
375
376
377
378
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 374

def mirror_app!
  components = mirrored_app_components
  components << :application if application_file?
  mirror_files_for components
end

- (Array<Array>) mirror_files_for(*types)

Note:

Only explicitly defined component paths will be taken into account to avoid cluttering the app's Merb.root by mistake since undefined paths default to that.

Copy files from specified component path types to their app-level location.

App-level overrides are preserved by creating duplicates before writing gem-level files. Because of their _override postfix they will load after their original implementation. In the case of views, this won't work, but the user override is preserved nonetheless.

Returns:

  • (Array<Array>)

    Array of two arrays, one for all copied files, the other for overrides that may have been preserved to resolve collisions.



402
403
404
405
406
407
408
409
410
411
412
413
414
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 402

def mirror_files_for(*types)
  seen, copied, duplicated = [], [], [] # keep track of files we copied
  types.flatten.each do |type|
    if app_paths.key?(type) && (source_path = dir_for(type)) && (destination_path = app_dir_for(type))
      manifest(type).each do |source, relative_path| # this relative path is not what we need here
        next if seen.include?(source)
        mirror_file(source, destination_path / source.relative_path_from(source_path), copied, duplicated)
        seen << source
      end
    end
  end
  [copied, duplicated]
end

- (Array<Array>) mirror_public!

Copies all application files from mirrored_components to their app-level location.

Returns:

  • (Array<Array>)

    Array of two arrays, one for all copied files, the other for overrides that may have been preserved to resolve collisions.



384
385
386
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 384

def mirror_public!
  mirror_files_for mirrored_public_components
end

- (Array<Array>) mirror_stubs!

Copies all files from the (optional) stubs directory to their app-level location

Returns:

  • (Array<Array>)

    Array of two arrays, one for all copied files, the other for overrides that may have been preserved to resolve collisions.



366
367
368
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 366

def mirror_stubs!
  mirror_files_for :stub
end

- (Array<Symbol>) mirrored_app_components

Return all application path component types to mirror.

Returns:

  • (Array<Symbol>)


296
297
298
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 296

def mirrored_app_components
  mirrored_components & app_components
end

- (Array<Symbol>) mirrored_components

Return all path component types to mirror.

If config option :mirror is set return a subset, otherwise return all types.

Returns:

  • (Array<Symbol>)


288
289
290
291
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 288

def mirrored_components
  all = slice_paths.keys
  config[:mirror].is_a?(Array) ? config[:mirror] & all : all
end

- (ArraySymbol) mirrored_public_components

Return all public path component types to mirror.

Returns:

  • (ArraySymbol)

    ]



303
304
305
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 303

def mirrored_public_components
  mirrored_components & public_components
end

- (Hash) named_routes

Returns The named routes for this slice.

Returns:

  • (Hash)

    The named routes for this slice.



71
72
73
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 71

def named_routes
  Merb::Slices.named_routes[self.identifier_sym] ||= {}
end

- (Array<Symbol>) public_components

Return all public path component types.

Returns:

  • (Array<Symbol>)


278
279
280
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 278

def public_components
  [:stylesheet, :javascript, :image]
end

- (String) public_dir_for(type)

Retrieve the relative path to a public directory.

Parameters:

  • type (Symbol)

    The type of path to retrieve directory for, e.g. :view.

Returns:

  • (String)

    The relative path to the public directory for the requested type.



168
169
170
171
172
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 168

def public_dir_for(type)
  dir = type.is_a?(Symbol) ? self.app_dir_for(type) : self.app_dir_for(:public) / type
  dir = dir.relative_path_from(Merb.dir_for(:public)) rescue '.'
  dir == '.' ? '/' : "/#{dir}"
end

- (String) public_path_for(type, *segments)

Construct a path relative to the public directory.

Parameters:

  • The (Symbol)

    type of component.

  • *segments (Array<#to_s>)

    Path segments to append.

Returns:

  • (String)

    A path relative to the public directory, with added segments.



181
182
183
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 181

def public_path_for(type, *segments)
  File.join(self.public_dir_for(type), *segments)
end

- (Object) push_app_path(type, path, file_glob = "**/*.rb")

Note:

The :public path is adapted when the slice is run from bin/slice.

This is the core mechanism for setting up your app-level layout.

Parameters:

  • type (Symbol)

    The type of path being registeredi, e.g., :view.

  • path (String)

    The full path.

  • file_glob (String) (defaults to: "**/*.rb")

    A glob that will be used to autoload files under the path.



240
241
242
243
244
245
246
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 240

def push_app_path(type, path, file_glob = "**/*.rb")
  enforce!(type => Symbol)
  if type == :public && standalone? && $SLICE_MODULE
    path.gsub!(/\/slices\/#{self.identifier}$/, '')
  end
  app_paths[type] = [path, file_glob]
end

- (Object) push_path(type, path, file_glob = "**/*.rb")

This is the core mechanism for setting up your slice-level layout.

Parameters:

  • type (Symbol)

    The type of path being registeredi, e.g., :view.

  • path (String)

    The full path.

  • file_glob (String) (defaults to: "**/*.rb")

    A glob that will be used to autoload files under the path.



216
217
218
219
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 216

def push_path(type, path, file_glob = "**/*.rb")
  enforce!(type => Symbol)
  slice_paths[type] = [path, file_glob]
end

- (Object) registered

Note:

This is rarely needed but still provided for edge cases.

Stub that gets triggered when a slice has been registered.



18
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 18

def registered; end

- (Object) remove_app_paths(*args)

Removes given types of application components from app-level load path this slice uses for autoloading.

Parameters:

  • *args (Array<Symbol>)

    Components names, e.g., :views, :models.



253
254
255
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 253

def remove_app_paths(*args)
  args.each { |arg| self.app_paths.delete(arg) }
end

- (Object) remove_paths(*args)

Removes given types of application components from slice-level load path this slice uses for autoloading.

Parameters:

  • *args (Array<Symbol>)

    Components names, e.g., :views, :models.



226
227
228
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 226

def remove_paths(*args)
  args.each { |arg| self.slice_paths.delete(arg) }
end

- (String) root_path(*path)

Returns The full path including the root.

Parameters:

  • *path (#to_s)

    The relative path (or list of path components) to a directory under the root of the application.

Returns:

  • (String)

    The full path including the root.



129
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 129

def root_path(*path) File.join(self.root, *path) end

- (Boolean) routed?

Check if there have been any routes setup.

Returns:

  • (Boolean)


37
38
39
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 37

def routed?
  self.named_routes && !self.named_routes.empty?
end

- (Object) setup_default_structure!

This sets up the default slice-level and app-level structure.

You can create your own structure by implementing setup_structure and using #push_path and #push_app_path. By default this setup matches what the merb-gen slice generator creates.



421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 421

def setup_default_structure!
  self.push_app_path(:root, Merb.root / 'slices' / self.identifier, nil)
  
  self.push_path(:stub, root_path('stubs'), nil)
  self.push_app_path(:stub, app_dir_for(:root), nil)
  
  self.push_path(:application, root_path('app'), nil)
  self.push_app_path(:application, app_dir_for(:root) / 'app', nil)

  app_components.each do |component|
    self.push_path(component, dir_for(:application) / "#{component}s")
    self.push_app_path(component, app_dir_for(:application) / "#{component}s")
  end

  self.push_path(:public, root_path('public'), nil)
  self.push_app_path(:public,  Merb.dir_for(:public) / 'slices' / self.identifier, nil)

  public_components.each do |component|
    self.push_path(component, dir_for(:public) / "#{component}s", nil)
    self.push_app_path(component, app_dir_for(:public) / "#{component}s", nil)
  end
end

- (Object) setup_router(scope)

Stub to setup routes inside the host application.



34
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 34

def setup_router(scope); end

- (String) slice_path_for(type, *segments)

Construct a slice-level path.

Parameters:

  • The (Symbol)

    type of component.

  • *segments (Array<#to_s>)

    Path segments to append.

Returns:

  • (String)

    A path within the slice source (Gem), with added segments.



204
205
206
207
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 204

def slice_path_for(type, *segments)
  prefix = type.is_a?(Symbol) ? self.dir_for(type) : self.dir_for(:root) / type
  File.join(prefix, *segments)
end

- (Hash) slice_paths

The slice-level load paths to use when loading the slice.

Returns:

  • (Hash)

    The load paths which make up the slice-level structure.



114
115
116
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 114

def slice_paths
  @slice_paths ||= Hash.new { [self.root] }
end

- (Boolean) standalone?

Whether we're in an application or running from the slice dir itself.

Returns:

  • (Boolean)


42
43
44
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 42

def standalone?
  Merb.root == self.root
end

- (Object) to_param

Return a value suitable for routes/urls.



47
48
49
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 47

def to_param
  self.identifier
end

- (Array<Array>) unpack_slice!

Note:

Files for the :stub component type are skipped.

Unpack a subset of files from the slice to their app-level location. This will also copy /lib, causing merb-slices to pick up the slice there.

Returns:

  • (Array<Array>)

    Array of two arrays, one for all copied files, the other for overrides that may have been preserved to resolve collisions.



344
345
346
347
348
349
350
351
352
# File 'merb-slices/lib/merb-slices/module_mixin.rb', line 344

def unpack_slice!
  app_slice_root = app_dir_for(:root)
  copied, duplicated = mirror_public!
  manifest.each do |source, relative_path|
    next unless unpack_file?(relative_path)
    mirror_file(source, app_slice_root / relative_path, copied, duplicated)
  end
  [copied, duplicated]
end