lib/imw/resource.rb in imw-0.2.18 vs lib/imw/resource.rb in imw-0.3.0
- old
+ new
@@ -1,157 +1,41 @@
require 'imw/utils/has_uri'
module IMW
-
- # 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
- # <tt>imw/resources</tt> 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 <tt>:mode</tt> option changes this:
- #
- # IMW::Resource.new('/path/to/my_new_file', :mode => 'w')
- #
- # If the <tt>:skip_modules</tt> 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.
class Resource
- # The mode in which to access this resource.
- attr_accessor :mode
+ attr_accessor :mode, :resource_options
- # A copy of the options passed to this resource on initialization.
- attr_accessor :resource_options
-
- # 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
- # <tt>:no_modules</tt>:
- #
- # r = IMW::Resource.new("http://www.infochimps.com", :no_modules => true)
- # r.modules
- # => []
- #
- # And you can exert more fine-grained control with the
- # <tt>:use_modules</tt> and <tt>:skip_modules</tt> options, see
- # IMW::Resource.extend_instance! for details.
- #
- # @param [String, Addressable::URI] uri
- # @param [Hash] options
- # @option options [String] mode the mode to open the resource in (will be ignored when inapplicable)
- # @return [IMW::Resource]
def initialize uri, options={}
self.uri = uri
self.resource_options = options
self.mode = options[:mode] || 'r'
extend_appropriately!(options)
end
# Provides resources with a wrapped Addressable::URI object.
include IMW::Utils::HasURI
- # Provides resources with a summary, metadata, & schema.
- include IMW::Metadata::HasSummary
-
# Gives IMW::Resource instances with the ability to dynamically
# extend themselves with modules chosen from a set of handlers
# stored by the IMW::Resource class.
include IMW::Utils::DynamicallyExtendable
- [IMW::Schemes::HANDLERS, IMW::CompressedFiles::HANDLERS, IMW::Archives::HANDLERS, IMW::Formats::HANDLERS].each do |handlers|
+ [IMW::Schemes::HANDLERS, IMW::Formats::HANDLERS].each do |handlers|
register_handlers *handlers
end
-
- # Raise an error unless this resource exists.
- #
- # @param [String] message an optional message to include
+
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
- # Close this resource.
- #
- # Modules should hook into super() as they need to redefine this
- # method.
def close
end
- # 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...
- #
- # @return [IMW::Resource] the new (old) resource
def reopen
IMW.open(uri.to_s)
- end
-
- # 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 <tt>is_archive?</tt> 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).
- 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
end
end