lib/scrivito/basic_obj.rb in scrivito_sdk-0.17.0 vs lib/scrivito/basic_obj.rb in scrivito_sdk-0.18.0
- old
+ new
@@ -4,10 +4,24 @@
module Scrivito
# The CMS file class
# @api public
class BasicObj
+ UNIQ_ATTRIBUTES = %w[
+ _id
+ _path
+ _permalink
+ ].freeze
+
+ GENERATED_ATTRIBUTES = %w[
+ _conflicts
+ _last_changed
+ _modification
+ _obj_type
+ _text_links
+ ].freeze
+
extend ActiveModel::Naming
include AttributeContent
include ModelIdentity
@@ -75,14 +89,13 @@
# @param [Hash] attributes
# @return [Obj] the newly created {BasicObj Obj}
def self.create(attributes)
attributes = with_default_obj_class(attributes)
api_attributes, widget_properties = prepare_attributes_for_rest_api(attributes, nil)
- json = CmsRestApi.post(cms_rest_api_path, obj: api_attributes)
- obj = find(json['id'] || json['_id'])
+ json = Workspace.current.api_request(:post, '/objs', obj: api_attributes)
+ obj = find(json['_id'])
CmsRestApi::WidgetExtractor.notify_persisted_widgets(obj, widget_properties)
- Workspace.current.reload
obj
end
# Create a new {BasicObj Obj} instance with the given values and attributes.
# Normally this method should not be used.
@@ -261,27 +274,40 @@
# }
# }
# )
def update(attributes)
api_attributes, widget_properties = prepare_attributes_for_rest_api(attributes)
- CmsRestApi.put(cms_rest_api_path, obj: api_attributes)
- workspace.reload
- reload
+ workspace.api_request(:put, "/objs/#{id}", obj: api_attributes)
+ reload_data
CmsRestApi::WidgetExtractor.notify_persisted_widgets(self, widget_properties)
self
end
+ # Copies itself to a given path.
+ # @api public
+ # @param [Hash] options
+ # @option options [String,Symbol] :_path (nil) the path of the copy.
+ # @option options [String,Symbol] :_id (nil) the id of the copy.
+ # @option options [String,Symbol] :_permalink (nil) the permalink of the copy.
+ # @raise [ArgumentError] if +options+ includes invalid keys.
+ # @return [Obj] the created copy
+ # @example Copy a blog post.
+ # blog_post = Obj.find_by_path('/blog/first_post')
+ # blog_post.copy(_path: '/blog/second_post')
+ def copy(options)
+ options = options.stringify_keys.assert_valid_keys('_path', '_id', '_permalink')
+ json = workspace.api_request(:post, '/objs', obj: copyable_attributes.merge(options))
+ self.class.find(json['_id'])
+ end
+
# Destroys the {BasicObj Obj} in the current {Workspace}
# @api public
def destroy
if children.any?
raise ClientError.new(I18n.t('scrivito.errors.models.basic_obj.has_children'), 412)
end
-
- CmsRestApi.delete(cms_rest_api_path)
-
- workspace.reload
+ workspace.api_request(:delete, "/objs/#{id}")
end
def to_param
id
end
@@ -484,33 +510,22 @@
# Reloads the attributes of this object from the database.
# Notice that the ruby class of this Obj instance will NOT change,
# even if the obj_class in the database has changed.
# @api public
def reload
- id = self.id.to_s
+ workspace.reload
+ reload_data
+ end
- reload_data = Proc.new do
+ def reload_data
+ id = self.id.to_s
+ update_data -> {
CmsBackend.instance.find_obj_data_by(workspace.revision, :id, [id]).first.first
- end
-
- update_data(reload_data)
+ }
end
- # @return [String]
# @api public
- def obj_class_name
- read_attribute('_obj_class')
- end
-
- # Returns the {Scrivito::ObjClass} of this object.
- # @return [Scrivito::ObjClass]
- # @api public
- def obj_class
- ObjClass.find(obj_class_name)
- end
-
- # @api public
def last_changed
read_attribute('_last_changed')
end
def new?(revision=Workspace.current.base_revision)
@@ -663,39 +678,27 @@
# Reverts changes of this object.
# After calling this method it's as if this object has been never modified in the current working copy.
# This method does not work with +new+ or +deleted+ objects.
# This method also does also not work for the +published+ workspace or the +rtc+ working copy.
def revert
- workspace.assert_revertable
+ assert_revertable
- if binary?
- raise "revert not supported for binary objs"
- else
- case modification
- when Modification::UNMODIFIED
- # don't do anything
- when Modification::EDITED
- previous_content = CmsRestApi.get(
- "revisions/#{workspace.base_revision_id}/objs/#{id}")
- updated_content = previous_content.except('id', '_id')
+ if modification == Modification::EDITED
+ base_revision_path = "revisions/#{workspace.base_revision_id}/objs/#{id}"
+ previous_attributes = CmsRestApi.get(base_revision_path).except('_id')
+ previous_widget_pool = previous_attributes['_widget_pool']
- added_widget_ids = read_widget_pool.keys - previous_content['_widget_pool'].keys
- added_widget_ids.each do |added_widget_id|
- updated_content['_widget_pool'][added_widget_id] = nil
- end
+ ids_of_new_widgets = read_widget_pool.keys - previous_widget_pool.keys
+ ids_of_new_widgets.each { |widget_id| previous_widget_pool[widget_id] = nil }
- CmsRestApi.put(cms_rest_api_path, obj: updated_content)
-
- reload
- else
- raise ScrivitoError, "cannot revert changes, since obj is #{modification}."
- end
+ workspace.api_request(:put, "/objs/#{id}", obj: previous_attributes)
+ reload
end
end
def mark_resolved
- CmsRestApi.put(cms_rest_api_path, obj: {_conflicts: nil})
+ workspace.api_request(:put, "/objs/#{id}", obj: {_conflicts: nil})
reload
end
def container_and_field_name_for_widget(widget_id)
if field_name = field_name_in_data_for_widget(data_from_cms, widget_id)
@@ -716,10 +719,14 @@
def has_conflict?
read_attribute('_conflicts') != nil
end
+ def publishable?
+ !has_conflict?
+ end
+
def all_widgets_from_pool
read_widget_pool.keys.map do |widget_id|
widget_from_pool(widget_id)
end
end
@@ -732,10 +739,28 @@
end
raise ScrivitoError.new('Could not generate a new unused widget id')
end
+ # Generates a +Hash+ containing all public attributes. The hash will _not_ include attributes,
+ # which are read-only or used for internal purpose.
+ # @api public
+ # @return [Hash] a hash containing all public attributes.
+ # @example
+ # old_obj = Obj.homepage
+ # attrs = old_obj.to_h
+ # puts attrs
+ # #=> {"_obj_class"=>"Publication", "_path"=>"/", "_id"=>"f64a68258ca15faf", "_widget_pool"=>{}}
+ # old_obj.destroy
+ #
+ # new_obj = Obj.create(attrs)
+ # puts new_obj == old_obj
+ # #=> true
+ def to_h
+ data_from_cms.to_h.except(*GENERATED_ATTRIBUTES)
+ end
+
private
def cms_data_for_revision(revision)
if revision
CmsBackend.instance.find_obj_data_by(revision, "id", [id]).first.first
@@ -772,14 +797,10 @@
def find_blob
blob_spec = read_attribute('blob')
Blob.find(blob_spec["id"]) if blob_spec
end
- def cms_rest_api_path(obj_id = id)
- "#{self.class.cms_rest_api_path(workspace)}/#{obj_id}"
- end
-
def workspace
if revision.workspace
revision.workspace
else
raise ScrivitoError, "No workspace set for this obj"
@@ -792,20 +813,29 @@
def prepare_attributes_for_rest_api(attributes)
self.class.prepare_attributes_for_rest_api(attributes, self)
end
+ def copyable_attributes
+ workspace.api_request(:get, "/objs/#{id}")
+ .except(*GENERATED_ATTRIBUTES)
+ .except(*UNIQ_ATTRIBUTES)
+ end
+
+ def assert_revertable
+ workspace.assert_revertable
+ raise "revert not supported for binary objs" if binary?
+ if modification == Modification::NEW || modification == Modification::DELETED
+ raise ScrivitoError, "cannot revert changes, since obj is #{modification}."
+ end
+ end
+
class << self
def restore(obj_id)
Workspace.current.assert_revertable
-
base_revision_path = "revisions/#{Workspace.current.base_revision_id}/objs/#{obj_id}"
- obj_attributes = CmsRestApi.get(base_revision_path).except('id').merge('_id' => obj_id)
- CmsRestApi.post(cms_rest_api_path, obj: obj_attributes)
- end
-
- def cms_rest_api_path(workspace = Workspace.current)
- "workspaces/#{workspace.id}/objs"
+ obj_attributes = CmsRestApi.get(base_revision_path).merge('_id' => obj_id)
+ Workspace.current.api_request(:post, '/objs', obj: obj_attributes)
end
def prepare_attributes_for_rest_api(attributes, obj)
widget_properties = CmsRestApi::WidgetExtractor.call(attributes, obj)
api_attributes = CmsRestApi::AttributeSerializer.convert(attributes)