Class: IMW::Resource

Inherits:
Object
  • Object
show all
Includes:
Metadata::Schematized, Utils::DynamicallyExtendable, Utils::HasURI
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. As an example, calling

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

would return an IMW::Resource extended by IMW::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::Resource.handlers. You can define your own handlers by defining the constant IMW::Resource::USER_DEFINED_HANDLERS in your configuration file.

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

my_archive.modules #=> [IMW::Local::Base, IMW::Local::File, IMW::Local::Compressible, IMW::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.

You can also instantiate an IMW::Resource using IMW.open, which accepts all the same arguments as IMW::Resource.new.

Instance Attribute Summary collapse

Attributes included from Utils::HasURI

#uri

Instance Method Summary collapse

Methods included from Utils::DynamicallyExtendable

#extend, #extend_appropriately!, included, #modules

Methods included from Metadata::Schematized

#schema, #schema=

Methods included from Utils::HasURI

#basename, #dirname, #extension, #extname, #fragment, #name, #password, #scheme, #stripped_uri, #to_s, #user

Constructor Details

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

Create a new resource representing uri.

IMW will automatically extend the resulting IMW::Resource instance with modules appropriate for the given URI:

r = IMW::Resource.new("http://www.infochimps.com")
r.modules
=> [IMW::Schemes::Remote::Base, IMW::Schemes::Remote::RemoteFile, IMW::Schemes::HTTP, IMW::Formats::Html]

You can prevent this altogether by passing in :no_modules:

r = IMW::Resource.new("http://www.infochimps.com", :no_modules => true)
r.modules
=> []

And you can exert more fine-grained control with the :use_modules and :skip_modules options, see IMW::Resource.extend_instance! for details.

Parameters:

Options Hash (options):

  • no_modules (true, false)
  • mode (String)

    the mode to open the resource in (will be ignored when inapplicable)

  • schema (IMW::Metadata::Record, Array)

    the schema of this resource



80
81
82
83
84
85
86
# File 'lib/imw/resource.rb', line 80

def initialize uri, options={}
  self.uri              = uri
  self.resource_options = options
  self.mode             = options[:mode] || 'r'
  self.schema           = options[:schema]   if options[:schema]
  extend_appropriately!(options)
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).



150
151
152
153
154
155
156
157
# File 'lib/imw/resource.rb', line 150

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 #{modules.join(', ')}"
  end
end

Instance Attribute Details

#modeObject

The mode in which to access this resource.



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

def mode
  @mode
end

#resource_optionsObject

A copy of the options passed to this resource on initialization.



52
53
54
# File 'lib/imw/resource.rb', line 52

def resource_options
  @resource_options
end

Instance Method Details

#closeObject

Close this resource.

Modules should hook into super() as they need to redefine this method.



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

def close
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:



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

def reopen
  IMW.open(uri.to_s)
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:



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

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