lib/scrivito/basic_obj.rb in scrivito_sdk-0.70.2 vs lib/scrivito/basic_obj.rb in scrivito_sdk-0.71.0.rc1
- old
+ new
@@ -130,12 +130,16 @@
obj_class.create(attributes, context)
else
attributes = build_attributes_with_defaults(attributes, context)
attributes = prepare_attributes_for_instantiation(attributes)
api_attributes, widget_properties = prepare_attributes_for_rest_api(attributes)
- json = Workspace.current.api_request(:post, '/objs', obj: api_attributes)
- obj = find(json['_id'])
+
+ workspace = Workspace.current
+ obj_data = workspace.create_obj(obj: api_attributes)
+ obj = BasicObj.instantiate(obj_data)
+ obj.revision = workspace.revision
+
CmsRestApi::WidgetExtractor.notify_persisted_widgets(obj, widget_properties)
obj
end
end
@@ -185,18 +189,21 @@
# @api public
def self.find_including_deleted(id_or_list)
Workspace.current.objs.find_including_deleted(id_or_list)
end
- # Returns an {ObjSearchEnumerator} with the given initial subquery consisting of the four arguments.
+ # Returns an {Scrivito::ObjSearchEnumerator} with the given initial subquery consisting of the
+ # four arguments.
#
- # Note that +field+ and +value+ can also be arrays for searching several fields or searching for several values.
+ # Note that +field+ and +value+ can also be arrays for searching several fields or searching for
+ # several values.
#
- # @note If invoked on a subclass of Obj, the result will be restricted to instances of this subclass.
+ # @note If invoked on a subclass of Obj, the result will be restricted to instances of this
+ # subclass.
#
- # {ObjSearchEnumerator}s can be chained using one of the chainable methods
- # (e.g. {ObjSearchEnumerator#and} and {ObjSearchEnumerator#and_not}).
+ # {Scrivito::ObjSearchEnumerator}s can be chained using one of the chainable methods
+ # (e.g. {Scrivito::ObjSearchEnumerator#and} and {Scrivito::ObjSearchEnumerator#and_not}).
#
# @example Look for objects containing "Lorem", boosting headline matches:
# Obj.where(:*, :contains, 'Lorem', headline: 2).to_a
#
# @example Look for the first 10 objects whose object class is "Pressrelease" and whose title contains "quarterly":
@@ -205,16 +212,17 @@
# @example Look for all objects whose class is "Item". The path should start with a defined location. Furthermore, select only items of a particular category:
# Obj.where(:_obj_class, :equals, 'Item').and(:_path, :starts_with, '/en/items/').select do |item|
# item.categories.include?(category)
# end
#
- # @param [Symbol, String, Array<Symbol, String>] field See {ObjSearchEnumerator#and} for details
- # @param [Symbol, String] operator See {ObjSearchEnumerator#and} for details
- # @param [String, Array<String>] value See {ObjSearchEnumerator#and} for details
- # @param [Hash] boost See {ObjSearchEnumerator#and} for details
- # @raise [ScrivitoError] if called directly on +BasicObj+. Use +Obj.where+ instead.
- # @return [ObjSearchEnumerator]
+ # @param [Symbol, String, Array<Symbol, String>] field See {Scrivito::ObjSearchEnumerator#and}
+ # for details
+ # @param [Symbol, String] operator See {Scrivito::ObjSearchEnumerator#and} for details
+ # @param [String, Array<String>] value See {Scrivito::ObjSearchEnumerator#and} for details
+ # @param [Hash] boost See {Scrivito::ObjSearchEnumerator#and} for details
+ # @raise [ScrivitoError] if called directly on {Scrivito::BasicObj}. Use +Obj.where+ instead.
+ # @return [Scrivito::ObjSearchEnumerator]
# @api public
def self.where(field, operator, value, boost = nil)
assert_not_basic_obj('.where')
if self == ::Obj
Workspace.current.objs.where(field, operator, value, boost)
@@ -222,27 +230,27 @@
Workspace.current.objs.where(:_obj_class, :equals, name)
.and(field, operator, value, boost)
end
end
- # Returns an {ObjSearchEnumerator} of all {Scrivito::BasicObj Obj}s.
+ # Returns an {Scrivito::ObjSearchEnumerator} of all {Scrivito::BasicObj Obj}s.
# If invoked on a subclass of Obj, the result is restricted to instances of this subclass.
- # @return [ObjSearchEnumerator]
- # @raise [ScrivitoError] if called directly on +BasicObj+. Use +Obj.all+ instead.
+ # @return [Scrivito::ObjSearchEnumerator]
+ # @raise [ScrivitoError] if called directly on +Scrivito::BasicObj+. Use +Obj.all+ instead.
# @api public
def self.all
assert_not_basic_obj('.all')
if self == ::Obj
Workspace.current.objs.all
else
find_all_by_obj_class(name)
end
end
- # Returns an {ObjSearchEnumerator} of all CMS objects with the given +obj_class+.
+ # Returns an {Scrivito::ObjSearchEnumerator} of all CMS objects with the given +obj_class+.
# @param [String] obj_class name of the object class.
- # @return [ObjSearchEnumerator]
+ # @return [Scrivito::ObjSearchEnumerator]
# @api public
def self.find_all_by_obj_class(obj_class)
Workspace.current.objs.find_all_by_obj_class(obj_class)
end
@@ -263,13 +271,13 @@
# @api public
def self.find_by_name(name)
where(:_name, :equals, name).batch_size(1).first
end
- # Returns an {ObjSearchEnumerator} of all CMS objects with the given name.
+ # Returns an {Scrivito::ObjSearchEnumerator} of all CMS objects with the given name.
# @param [String] name Name of the {Scrivito::BasicObj Obj}.
- # @return [ObjSearchEnumerator]
+ # @return [Scrivito::ObjSearchEnumerator]
# @api public
def self.find_all_by_name(name)
where(:_name, :equals, name)
end
@@ -280,12 +288,13 @@
# @api public
def self.find_by_permalink(permalink)
Workspace.current.objs.find_by_permalink(permalink)
end
- # Returns the {Scrivito::BasicObj Obj} with the given permalink, or raises ResourceNotFound if
- # no matching Obj exists.
+ # Returns the {Scrivito::BasicObj Obj} with the given permalink, or raises
+ # {Scrivito::ResourceNotFound} if no matching Obj exists.
+ #
# @param [String] permalink The permalink of the {Scrivito::BasicObj Obj}.
# @return [Obj]
# @api public
def self.find_by_permalink!(permalink)
find_by_permalink(permalink) or
@@ -311,12 +320,12 @@
# @api public
def self.valid_page_classes_beneath(parent_path)
end
def self.valid_page_ruby_classes_beneath(parent_path)
- assert_classes(valid_page_classes_beneath(parent_path), '.valid_page_classes_beneath') ||
- Scrivito.models.pages.to_a
+ result = assert_classes(valid_page_classes_beneath(parent_path), '.valid_page_classes_beneath')
+ (result || Scrivito.models.pages.to_a).uniq
end
# Update the {Scrivito::BasicObj Obj} using the attributes provided.
#
# For an overview of the values you can set via this method, see the
@@ -360,12 +369,11 @@
# }
# }
# )
def update(attributes)
api_attributes, widget_properties = prepare_attributes_for_rest_api(attributes)
- workspace.api_request(:put, "/objs/#{id}", obj: api_attributes)
- reload_data
+ update_data(workspace.update_obj(id, obj: api_attributes))
CmsRestApi::WidgetExtractor.notify_persisted_widgets(self, widget_properties)
self
end
# Creates a copy of the {Scrivito::BasicObj Obj}.
@@ -386,11 +394,11 @@
json = workspace.api_request(:post, '/objs', obj: attributes_for_copy.merge(options))
self.class.find(json['_id'])
end
- # Destroys the {Scrivito::BasicObj Obj} in the current {Workspace}.
+ # Destroys the {Scrivito::BasicObj Obj} in the current {Scrivito::Workspace}.
# @api public
def destroy
if children.any?
raise ClientError.new(I18n.t('scrivito.errors.models.basic_obj.has_children'), 412)
end
@@ -475,11 +483,11 @@
# If the controller does not exist, the CmsController is used as a fallback.
# Override this method to force a different controller to be used.
# @return [String]
# @api public
def controller_name
- obj_class_name
+ obj_class
end
# This method determines the action to be invoked when the +Obj+ is requested.
# The default action is 'index'.
# Override this method to force a different action to be used.
@@ -778,11 +786,11 @@
# @api public
# This method returns the URL under which the content of this binary is
# available to the public if the binary is set.
#
- # See {Binary#url} for details
+ # See {Scrivito::Binary#url} for details
# @return [String, nil]
def binary_url
binary.try(:url)
end
@@ -803,18 +811,10 @@
def inspect
"<#{self.class} id=\"#{id}\" path=\"#{path}\">"
end
- def details_view_path
- view_path('details')
- end
-
- def embed_view_path
- view_path('embed')
- end
-
def widget_from_pool(widget_id)
widget_data = widget_data_from_pool(widget_id)
instantiate_widget(widget_id, widget_data) if widget_data
end
@@ -857,10 +857,12 @@
previous_widget_pool = previous_attributes['_widget_pool']
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 }
+ previous_attributes = reset_blank_attributes(previous_attributes)
+
workspace.api_request(:put, "/objs/#{id}", obj: previous_attributes)
reload
end
end
@@ -951,12 +953,17 @@
cms_data_for_revision(base_revision) != cms_data_for_revision(published_revision)
end
def transfer_modifications_to(target_workspace)
return unless modification
+ if has_conflict? || future_conflict?(target_workspace)
+ raise TransferModificationsConflictError, "Transfer will result in a conflict. " \
+ "Please update the current and target workspace and ensure they are conflict free."
+ end
if in_revision(target_workspace.revision).try(:modification)
- raise TransferModificationsError, "Already modified in workspace #{target_workspace.id}"
+ raise TransferModificationsModifiedError,
+ "Already modified in workspace #{target_workspace.id}"
end
copy_modifications_to(target_workspace)
reset_modifications
end
@@ -968,41 +975,31 @@
when deleted? then destroy_in(target_workspace)
else update_in(target_workspace)
end
end
+ def future_conflict?(target_workspace)
+ base_revision = workspace.base_revision
+ target_base_revision = target_workspace.base_revision
+
+ base_revision != target_base_revision &&
+ cms_data_for_revision(base_revision) != cms_data_for_revision(target_base_revision)
+ end
+
def create_in(target_workspace)
target_workspace.api_request(:post, '/objs', obj: get_attributes)
end
def update_in(target_workspace)
- update_attributes = fill_in_missing_attributes_as_nil(copyable_attributes)
+ update_attributes = reset_blank_attributes(copyable_attributes)
target_workspace.api_request(:put, "/objs/#{id}", obj: update_attributes)
end
def destroy_in(target_workspace)
target_workspace.api_request(:delete, "/objs/#{id}")
end
- def fill_in_missing_attributes_as_nil(attributes, type_computer=Obj.type_computer)
- obj_class = type_computer.compute_type_without_fallback(attributes['_obj_class'])
- missing_attributes = obj_class.attribute_definitions.map(&:name) - attributes.keys
-
- if attributes['_widget_pool']
- attributes['_widget_pool'].each do |id, widget_attributes|
- attributes['_widget_pool'][id] = fill_in_missing_attributes_as_nil(
- widget_attributes, Widget.type_computer)
- end
- end
-
- missing_attributes.each do |attribute_name|
- attributes[attribute_name] = nil
- end
-
- attributes
- end
-
def reset_modifications
case
when new? then destroy
when deleted? then self.class.restore(id)
else revert
@@ -1030,11 +1027,11 @@
widget.obj = self
end
end
def as_date(value)
- DateAttribute.deserialize_from_backend(value) unless value.nil?
+ DateAttribute.parse(value) unless value.nil?
end
def find_blob
read_attribute('blob')
end
@@ -1062,11 +1059,11 @@
def get_attributes
workspace.api_request(:get, "/objs/#{id}")
end
def copy_binaries(attributes)
- attribute_defintions = self.class.find_attribute_definitions(obj_class_name)
+ attribute_defintions = self.class.find_attribute_definitions(obj_class)
destination_obj_id = attributes.fetch(:_id)
Hash[attributes.map do |name, value|
if value && attribute_defintions[name].try(:type) == 'binary'
binary = self[name]
@@ -1095,14 +1092,10 @@
def binary_title
binary.filename if binary? && binary
end
- def view_path(view_name)
- "#{obj_class_name.underscore}/#{view_name}"
- end
-
def has_system_attribute?(attribute_name)
!!SYSTEM_ATTRIBUTES[attribute_name]
end
def has_public_system_attribute?(attribute_name)
@@ -1113,14 +1106,21 @@
SYSTEM_ATTRIBUTES[attribute_name].try(:type)
end
def value_of_system_attribute(attribute_name)
attribute_value = data_from_cms.value_of(attribute_name)
- if attribute_name == '_last_changed'
- DateAttribute.deserialize_from_backend(attribute_value)
- else
- attribute_value
+ attribute_name == '_last_changed' ? DateAttribute.parse(attribute_value) : attribute_value
+ end
+
+ def reset_blank_attributes(attributes)
+ widget_pool = attributes['_widget_pool']
+ widget_pool.each do |id, widget_attributes|
+ if widget_attributes
+ widget_pool[id] = Widget.reset_blank_attributes(widget_attributes)
+ end
end
+
+ self.class.reset_blank_attributes(attributes)
end
class << self
def assert_not_basic_obj(method_name)
if self == Scrivito::BasicObj