Module: Merb::Slices::ModuleMixin

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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(slice_module) ⇒ Object



8
9
10
11
12
13
# File '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

#[](key) ⇒ Object

Returns The configuration value.

Parameters:

  • The (Symbol)

    configuration key.

Returns:

  • (Object)

    The configuration value.



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

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

#[]=(key, value) ⇒ Object

Parameters:

  • The (Symbol)

    configuration key.

  • The (Object)

    configuration value.



59
60
61
# File 'lib/merb-slices/module_mixin.rb', line 59

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

#activateObject

Stub activation hook - runs after AfterAppLoads BootLoader.



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

def activate; end

#app_componentsArray[Symbol]

Return all application path component types

Returns:

  • (Array[Symbol])

    Component types.



257
258
259
# File 'lib/merb-slices/module_mixin.rb', line 257

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

#app_dir_for(type) ⇒ String

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.



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

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

#app_glob_for(type) ⇒ String

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.



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

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

#app_path_for(type, *segments) ⇒ String

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.



183
184
185
186
# File 'lib/merb-slices/module_mixin.rb', line 183

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

#app_pathsHash

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

Returns:

  • (Hash)

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



119
120
121
# File 'lib/merb-slices/module_mixin.rb', line 119

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

#clone_slice!Array[Array]

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.



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

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

#collected_app_pathsArray[String]

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)



105
106
107
# File 'lib/merb-slices/module_mixin.rb', line 105

def collected_app_paths
  @collected_app_paths ||= []
end

#collected_slice_pathsArray[String]

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)



96
97
98
# File 'lib/merb-slices/module_mixin.rb', line 96

def collected_slice_paths
  @collected_slice_paths ||= []
end

#configHash

Returns The configuration for this slice.

Returns:

  • (Hash)

    The configuration for this slice.



64
65
66
# File 'lib/merb-slices/module_mixin.rb', line 64

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

#deactivateObject

Stub deactivation method - not triggered automatically.



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

def deactivate; end

#dir_for(type) ⇒ String

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.



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

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

#glob_for(type) ⇒ String

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.



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

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

#initObject

Stub initialization hook - runs before AfterAppLoads BootLoader.



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

def init; end

#load_sliceObject

Load slice and it’s 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.



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

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

#loadable_filesArray

Return all *.rb files from valid component paths

Returns:

  • (Array)

    Full paths to loadable ruby files.



246
247
248
249
250
251
252
# File 'lib/merb-slices/module_mixin.rb', line 246

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

#loadedObject

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



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

def loaded; end

#manifest(type = :root) ⇒ Array[Array]

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

Parameters:

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

    Which type to use; defaults to :root (all)

Returns:

  • (Array[Array])

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



296
297
298
299
300
301
302
303
304
305
306
# File 'lib/merb-slices/module_mixin.rb', line 296

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

#mirror_all!Array[Array]

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.



348
349
350
# File 'lib/merb-slices/module_mixin.rb', line 348

def mirror_all!
  mirror_files_for mirrored_components + mirrored_public_components
end

#mirror_app!Array[Array]

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.



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

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

#mirror_files_for(*types) ⇒ Array[Array]

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.



393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/merb-slices/module_mixin.rb', line 393

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

#mirror_public!Array[Array]

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.



377
378
379
# File 'lib/merb-slices/module_mixin.rb', line 377

def mirror_public!
  mirror_files_for mirrored_public_components
end

#mirror_stubs!Array[Array]

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.



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

def mirror_stubs!
  mirror_files_for :stub
end

#mirrored_app_componentsArray[Symbol]

Return all application path component types to mirror

Returns:

  • (Array[Symbol])

    Component types.



281
282
283
# File 'lib/merb-slices/module_mixin.rb', line 281

def mirrored_app_components
  mirrored_components & app_components
end

#mirrored_componentsArray[Symbol]

Return all path component types to mirror

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

Returns:

  • (Array[Symbol])

    Component types.



273
274
275
276
# File 'lib/merb-slices/module_mixin.rb', line 273

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

#mirrored_public_componentsArray[Symbol]

Return all public path component types to mirror

Returns:

  • (Array[Symbol])

    Component types.



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

def mirrored_public_components
  mirrored_components & public_components
end

#named_routesHash

Returns The named routes for this slice.

Returns:

  • (Hash)

    The named routes for this slice.



69
70
71
# File 'lib/merb-slices/module_mixin.rb', line 69

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

#public_componentsArray[Symbol]

Return all public path component types

Returns:

  • (Array[Symbol])

    Component types.



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

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

#public_dir_for(type) ⇒ String

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.



159
160
161
162
163
# File 'lib/merb-slices/module_mixin.rb', line 159

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

#public_path_for(type, *segments) ⇒ String

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.



172
173
174
# File 'lib/merb-slices/module_mixin.rb', line 172

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

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

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 registered (i.e. :view)

  • path (String)

    The full path

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

    A glob that will be used to autoload files under the path. Defaults to “*/.rb”.



227
228
229
230
231
232
233
# File 'lib/merb-slices/module_mixin.rb', line 227

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

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

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

Parameters:

  • type (Symbol)

    The type of path being registered (i.e. :view)

  • path (String)

    The full path

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

    A glob that will be used to autoload files under the path. Defaults to “*/.rb”.



206
207
208
209
# File 'lib/merb-slices/module_mixin.rb', line 206

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

#registeredObject

Note:

This is rarely needed but still provided for edge cases.

Stub that gets triggered when a slice has been registered.



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

def registered; end

#remove_app_paths(*args) ⇒ Object

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

Parameters:

  • *args (Array[Symbol])

    Components names, for instance, :views, :models



239
240
241
# File 'lib/merb-slices/module_mixin.rb', line 239

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

#remove_paths(*args) ⇒ Object

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

Parameters:

  • *args (Array[Symbol])

    Components names, for instance, :views, :models



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

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

#root_path(*path) ⇒ String

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.



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

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

#routed?Boolean

Check if there have been any routes setup.

Returns:

  • (Boolean)


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

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

#setup_default_structure!Object

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

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



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/merb-slices/module_mixin.rb', line 412

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

#setup_router(scope) ⇒ Object

Stub to setup routes inside the host application.



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

def setup_router(scope); end

#slice_path_for(type, *segments) ⇒ String

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.



195
196
197
198
# File 'lib/merb-slices/module_mixin.rb', line 195

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

#slice_pathsHash

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

Returns:

  • (Hash)

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



112
113
114
# File 'lib/merb-slices/module_mixin.rb', line 112

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

#standalone?Boolean

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

Returns:

  • (Boolean)


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

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

#to_paramObject

Return a value suitable for routes/urls.



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

def to_param
  self.identifier
end

#unpack_slice!Array[Array]

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.



331
332
333
334
335
336
337
338
339
# File 'lib/merb-slices/module_mixin.rb', line 331

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