lib/duracloud/content.rb in duracloud-client-0.1.5 vs lib/duracloud/content.rb in duracloud-client-0.2.0

- old
+ new

@@ -1,56 +1,48 @@ -require "stringio" require "active_model" module Duracloud # # A piece of content in DuraCloud # class Content + include ActiveModel::Model include ActiveModel::Dirty include Persistence include HasProperties CHUNK_SIZE = 1024 * 16 after_save :changes_applied # Does the content exist in DuraCloud? - # @see .new for arguments # @return [Boolean] whether the content exists - def self.exist?(*args) - find(*args) && true + # @raise [Duracloud::MessageDigestError] the provided digest in the :md5 attribute + # does not match the stored value + def self.exist?(params={}) + find(params) && true rescue NotFoundError false end # Find content in DuraCloud. - # @see .new for arguments # @return [Duraclound::Content] the content # @raise [Duracloud::NotFoundError] the space, content, or store does not exist. - def self.find(*args) - new(*args) { |content| content.load_properties } + # @raise [Duracloud::MessageDigestError] the provided digest in the :md5 attribute + # does not match the stored value + def self.find(params={}) + new(params).tap do |content| + content.load_properties + end end - attr_reader :space_id, :content_id, :store_id + attr_accessor :space_id, :content_id, :store_id alias_method :id, :content_id + validates_presence_of :space_id, :content_id - define_attribute_methods :content_type, :body + define_attribute_methods :content_type, :body, :md5 - # @param space_id [String] The space ID (required) - # @param content_id [String] The content ID (required) - # @param store_id [String] the store ID (optional) - # @example - # new("myspace", "mycontent.txt") - def initialize(space_id, content_id, store_id = nil) - @content_id = content_id - @space_id = space_id - @store_id = store_id - @body, @content_type = nil, nil - yield self if block_given? - end - # Return the space associated with this content. # @return [Duracloud::Space] the space. # @raise [Duracloud::NotFoundError] the space or store does not exist. def space Space.find(space_id, store_id) @@ -64,17 +56,19 @@ # @api private # @raise [Duracloud::NotFoundError] the content does not exist in DuraCloud. def load_body response = Client.get_content(*args, **query) + set_md5!(response) @body = response.body # don't use setter b/c marks as dirty persisted! end def load_properties super do |response| - # don't mark content_type as changed + # don't mark content_type or md5 as changed + set_md5!(response) @content_type = response.content_type end end def body=(str_or_io) @@ -102,12 +96,32 @@ def content_type @content_type end + def md5=(val) + md5_will_change! unless val == @md5 + @md5 = val + end + + def md5 + @md5 + end + private + def set_md5!(response) + if md5 + if md5 != response.md5 + raise MessageDigestError, + "Expected MD5 digest (#{md5}) does not match response header: #{response.md5}" + end + else + @md5 = response.md5 + end + end + def io_like? body.respond_to?(:read) && body.respond_to?(:rewind) end def set_properties @@ -117,18 +131,18 @@ Client.set_content_properties(*args, **options) end def store headers = { - "Content-MD5" => md5, + "Content-MD5" => md5 || calculate_md5, "Content-Type" => content_type || "application/octet-stream" } headers.merge!(properties) options = { body: body, headers: headers, query: query } Client.store_content(*args, **options) end - def md5 + def calculate_md5 digest = Digest::MD5.new if io_like? body.rewind while chunk = body.read(CHUNK_SIZE) do digest << chunk