Class: IMW::Resource

Inherits:
Object
  • Object
show all
Defined in:
lib/imw/resource.rb

Overview

A resource can be anything addressable via a URI. Examples include local files, remote files, webpages, &c.

The IMW::Resource class takes a URI as input and then dynamically extends itself with appropriate modules from IMW::Resources. As an example, calling

my_archive = IMW::Resource.new('/path/to/my/archive.tar.bz2')

would return an IMW::Resource extended by IMW::Resources::Archives::Tarbz2 (among other modules) which therefore has methods for extracting, listing, and appending to the archive.

Modules are so extended based on handlers defined in the imw/resources directory and accessible via IMW::Resources#handlers. You can define your own handlers by defining the constant IMW::Resources::USER_DEFINED_HANDLERS in your configuration file.

The modules extending a particular IMW::Resource instance can be listed as follows

my_archive.resource_modules #=> [IMW::Resources::LocalObj, IMW::Resources::LocalFile, IMW::Resources::Compressible, IMW::Resources::Archives::Tarbz2]

By default, resources are opened for reading. Passing in the appropriate :mode option changes this:

IMW::Resource.new('/path/to/my_new_file', :mode => 'w')

If the :skip_modules option is passed in then the resource will not extend itself with any modules and will essentially only retain the bare functionality of a URI. This can be useful when subclassing IMW::Resource or dealing with a very strange kind of resource.

Read the documentation for modules in IMW::Resources to learn more about the various behaviors an IMW::Resource can acquire.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, options = {}) ⇒ Resource

Returns a new instance of Resource.



48
49
50
51
52
# File 'lib/imw/resource.rb', line 48

def initialize uri, options={}
  self.uri = uri
  @mode    = options[:mode] || 'r'
  extend_appropriately! unless options[:skip_modules]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

If method begins with the strings is, on, or via and ends with a question mark then we interpret it as a question this resource doesn’t know how to answer – so we have it answer false.

As an example, consider the following loop:

IMW.open('/tmp').all_contents.each do |obj|
  if obj.is_archive?
    # ... do something
  end
end

When obj is initialized and it _isn’t_ an archive, then it doesn’t know about the is_archive? method – but it should therefore answer false anyway.

This lets a basic text file answer questions about whether it’s an archive (or on S3, or accessed via some user-defined scheme, &c.) without needing to know anything about archives (or S3 or the user-defined scheme).



181
182
183
184
185
186
187
188
# File 'lib/imw/resource.rb', line 181

def method_missing method, *args
  if args.empty? && method.to_s =~ /(is|on|via)_.*\?$/
    # querying for a boolean response so answer false
    return false
  else
    raise IMW::NoMethodError, "undefined method `#{method}' for #{self}, extended by #{resource_modules.join(', ')}"
  end
end

Instance Attribute Details

#modeObject (readonly)

Returns the value of attribute mode.



46
47
48
# File 'lib/imw/resource.rb', line 46

def mode
  @mode
end

#uriObject

Returns the value of attribute uri.



46
47
48
# File 'lib/imw/resource.rb', line 46

def uri
  @uri
end

Instance Method Details

#basenameString

The basename of this resource’s path.

Returns:



108
109
110
# File 'lib/imw/resource.rb', line 108

def basename
  @basename ||= File.basename(path)
end

#dirnameString

The directory name of this resource’s path.

Returns:



101
102
103
# File 'lib/imw/resource.rb', line 101

def dirname
  @dirname  ||= File.dirname(path)
end

#extend(mod) ⇒ Object

Works just like Object#extend except it keeps track of the modules it has extended, see Resource#resource_modules.



63
64
65
66
# File 'lib/imw/resource.rb', line 63

def extend mod
  resource_modules << mod
  super mod
end

#extend_appropriately!Object

Extend this resource with modules by passing it through a collection of handlers defined by IMW::Resources#handlers



70
71
72
# File 'lib/imw/resource.rb', line 70

def extend_appropriately!
  IMW::Resources.extend_resource!(self)
end

#extensionString

Returns the extension (WITHOUT the ‘.’) of this resource’s path.

Returns:



124
125
126
# File 'lib/imw/resource.rb', line 124

def extension
  @extension ||= extname[1..-1] || ''
end

#extnameString

Returns the extension (INCLUDING the ‘.’) of this resource’s path. Redefine this in an including class for which this is weird (‘.tar.gz’ I’m talking to you…)

Returns:



117
118
119
# File 'lib/imw/resource.rb', line 117

def extname
  @extname ||= File.extname(path)
end

#nameString

Returns the basename of the file with its extension removed

IMW.open('/path/to/some_file.tar.gz').name # => some_file

Returns:



133
134
135
# File 'lib/imw/resource.rb', line 133

def name
  @name ||= extname ? basename[0,basename.length - extname.length] : basename
end

#reopenIMW::Resource

Open a copy of this resource.

This is useful when wanting to reset file handles. Though – be warned – it does not close any file handles itself…

Returns:



156
157
158
# File 'lib/imw/resource.rb', line 156

def reopen
  IMW.open(self.uri.to_s)
end

#resource_modulesArray

Return the modules this resource has been extended by.

Returns:

  • (Array)

    the modules this resource has been extended by.



57
58
59
# File 'lib/imw/resource.rb', line 57

def resource_modules
  @resource_modules ||= []
end

#schemeString

The scheme of this resource. Will be nil for local resources.

Returns:



94
95
96
# File 'lib/imw/resource.rb', line 94

def scheme
  @scheme ||= uri.scheme
end

#should_exist!(message = nil) ⇒ Object

Raise an error unless this resource exists.

Parameters:

  • message (String) (defaults to: nil)

    an optional message to include

Raises:



144
145
146
147
148
# File 'lib/imw/resource.rb', line 144

def should_exist!(message=nil)
  raise IMW::Error.new([message, "No path defined for #{self.inspect} extended by #{resource_modules.join(' ')}"].compact.join(', '))          unless respond_to?(:path)
  raise IMW::Error.new([message, "No exist? method defined for #{self.inspect} extended by #{resource_modules.join(' ')}"].compact.join(', ')) unless respond_to?(:exist?)
  raise IMW::PathError.new([message, "#{path} does not exist"].compact.join(', '))                                                             unless exist?
end

#to_sObject



137
138
139
# File 'lib/imw/resource.rb', line 137

def to_s
  uri.to_s
end