lib/scrivito/workspace.rb in scrivito_sdk-0.66.0 vs lib/scrivito/workspace.rb in scrivito_sdk-0.70.0.rc1

- old
+ new

@@ -1,41 +1,45 @@ require 'active_model/naming' module Scrivito -# This class represents a CMS workspace # @api public +# This class represents a CMS workspace, called "working copy" in the UI. A working copy lets +# editors create and modify content independently of the published content or other working copies. +# On creation, a working copy is based on the currently published content. +# @see http://scrivito.com/about-working-copies About working copies + class Workspace extend ActiveModel::Naming include ModelIdentity PublishPreventedDueToContentChange = Class.new(ScrivitoError) - # Set the currently used workspace + # Set the workspace to use for subsequent workspace operations. # @api public # @param [Scrivito::Workspace] workspace def self.current=(workspace) @current = workspace end def self.current_using_proc=(workspace_proc) @current = workspace_proc end - # Returns the currently used workspace + # Returns the currently used workspace. # @api public # @return [Scrivito::Workspace] def self.current if @current.respond_to? :call @current = @current.call else @current ||= published end end - # Returns all the workspaces + # Returns all workspaces. # @api public # @return [Array<Scrivito::Workspace>] def self.all result_json = CmsRestApi.get('/workspaces') @@ -46,30 +50,43 @@ def self.published find("published") end - # Find a workspace by its id + def self.published_with_fallback + cached_workspace_data = CmsBackend.instance.find_workspace_data_from_cache('published') + + if cached_workspace_data + workspace_data = begin + CmsBackend.instance.find_workspace_data_by_id('published', 0.5) + rescue => e + warn_backend_not_available(e.message) + cached_workspace_data + end + + from_workspace_data('published', workspace_data) + else + published + end + end + + # Find a workspace by its id. # @api public # @param [String] id # @return [Scrivito::Workspace] # @raise [Scrivito::ResourceNotFound] def self.find(id) cache.fetch(id) do workspace_data = CmsBackend.instance.find_workspace_data_by_id(id) - unless workspace_data - raise ResourceNotFound, "Could not find #{self} with id #{id}" - end - - cache[id] = Workspace.new(workspace_data) + from_workspace_data(id, workspace_data) end end # Find a workspace by its title. # If multiple workspaces share the same title, one of them is returned. - # If no workspace with the given title can be found, nil is returned. + # If no workspace with the given title can be found, +nil+ is returned. # @api public # @param [String] title # @return [Scrivito::Workspace] def self.find_by_title(title) all.detect { |workspace| workspace.title == title } @@ -106,45 +123,47 @@ end delegate :content_state_id, :base_content_state_id, :content_state, :base_revision_id, :base_content_state, to: :data - # Create a new workspace + # Create a new workspace. + # @example Create a workspace, providing its title: + # Scrivito::Workspace.create(title: "Jane") # @api public # @param [Hash] attributes # @return [Scrivito::Workspace] def self.create(attributes) workspace_json = CmsRestApi.post("/workspaces", workspace: attributes) self.find(workspace_json["id"]) end - # reloads the current workspace to reflect any changes to it that may have happened concurrently - # since it was loaded + # Reloads the current workspace to reflect the changes that were made to it concurrently + # since it was loaded. # @api public def self.reload current.reload end def self.cache @cache ||= {} end def initialize(workspace_data) - @workspace_data = workspace_data + update_data(workspace_data) + @id = data.id end - # Reloads this workspace to reflect any changes to it that may have happened concurrently since - # it was loaded + # Reloads this workspace to reflect the changes that were made to it concurrently since + # it was loaded. # @api public def reload - @workspace_data = CmsBackend.instance.find_workspace_data_by_id(self.id) + update_data(method(:fetch_workspace_data)) + end - # Clear all cached instance variables. - @base_revision = nil - @memberships = nil - @revision = nil + def eager_reload + update_data(fetch_workspace_data) end def api_request(verb, path, payload = nil) response = CmsRestApi.public_send(verb, "#{backend_url}#{path}", payload) reload if [:post, :put, :delete].include?(verb) @@ -153,73 +172,78 @@ def task_unaware_api_request(verb, path, payload = nil) CmsRestApi.task_unaware_request(verb, "#{backend_url}#{path}", payload) end - # Updates this workspace's attributes + # Updates the attributes of this workspace. # @api public # @param [Hash] attributes # @return [Scrivito::Workspace] def update(attributes) raise ScrivitoError, 'published workspace is not modifiable' if published? CmsRestApi.put(backend_url, workspace: attributes) reload end - # Destroy this workspace + # Destroy this workspace. # @api public def destroy reset_workspace_if_current CmsRestApi.delete(backend_url) end - # Publish the changes of this workspace + # Publish the changes that were made to this workspace. # @api public def publish CmsRestApi.put("#{backend_url}/publish", {}) Workspace.published.reload reset_workspace_if_current end - # Rebases the current workspace on the published content + # Rebases the current workspace from the published content in order to integrate the changes + # that were published in the meantime. # @api public def rebase CmsRestApi.put("#{backend_url}/rebase", {}) reload end - # Returns the id of the workspace + # Returns the id of the workspace. # @api public # @return [String] def id - @workspace_data.id + @id end def revision_id - @workspace_data.revision_id + data.revision_id end - # Returns the title of the workspace or an empty +String+ + # Returns the title of the workspace if present. Otherwise, and for the published content, + # an empty +String+ is returned. # @api public # @return [String] def title return '' if published? - @workspace_data.title || '' + data.title || '' end # @api public - # Returns the members of this workspace and their roles - # + # Returns the memberships (users and their roles) of this workspace. # @return [MembershipCollection] def memberships @memberships ||= MembershipCollection.new(self) end def data - @workspace_data + if @workspace_data.respond_to?(:call) + @workspace_data = @workspace_data.call + else + @workspace_data + end end def published? self.id == 'published' end @@ -263,11 +287,11 @@ def assert_revertable raise ScrivitoError, 'published workspace is not modifiable' if published? end - # {ObjCollection} for this working copy + # Returns an {ObjCollection} of this working copy for accessing its CMS objects. # @api public # @return {ObjCollection} def objs @objs ||= ObjCollection.new(self) end @@ -292,18 +316,52 @@ self.class.all_with_modification_for(obj_id) - [self] end private + def update_data(new_data) + @workspace_data = new_data + + # Clear all cached instance variables. + @base_revision = nil + @memberships = nil + @revision = nil + end + + def fetch_workspace_data + CmsBackend.instance.find_workspace_data_by_id(id) + end + def backend_url "/workspaces/#{id}" end def reset_workspace_if_current Workspace.cache.delete(id) if Workspace.current == self Workspace.current = Workspace.published + end + end + + class << self + private + + def from_workspace_data(id, data) + unless data + raise ResourceNotFound, "Could not find #{self} with id #{id}" + end + + cache[id] = Workspace.new(data) + end + + def warn_backend_not_available(error_message) + message = <<-EOS + Couldn't connect to backend to fetch published workspace. + #{error_message} + Serving from cache. + EOS + Rails.logger.warn(message) end end end end