Module: Scrivito::AttributeContent::ClassMethods

Included in:
BasicObj, BasicWidget
Defined in:
app/cms/scrivito/attribute_content.rb

Instance Method Summary collapse

Instance Method Details

#attribute(name, type, options = {}) ⇒ Object

Defines an attribute.

For the purpose of persisting model data in the CMS, the attributes of the model need to be defined. When defining an attribute, you specify the name under which Scrivito should persist its value as well as the type of content it is meant to contain, and, for the enum and multienum types, the selectable values.

Attributes are inherited. If, for example, the Page model defines a title attribute of the string type, the SpecialPage model, which inherits from Page, is also equipped with title. Inherited attributes can be overridden, i.e. you may redefine title in SpecialPage if you want its type to be html, for example.

Examples:

Defining attributes:

class Page < Obj
  attribute :my_string, :string
  attribute 'my_html', 'my_html'
  attribute :my_enum, :enum, values: %w[a b c], default: 'a'
  attribute :my_multienum, :multienum
end

Page.attribute_definitions
#=> #<Scrivito::AttributeDefinitionCollection>

Page.attribute_definitions[:my_string]
#=> #<Scrivito::AttributeDefinition>

Page.attribute_definitions[:my_string].type
#=> "string"

Page.attribute_definitions[:my_html].type
#=> "html"

Page.attribute_definitions[:my_enum].type
#=> "enum"
Page.attribute_definitions[:my_enum].values
#=> ["a", "b", "c"]

Page.attribute_definitions[:my_multienum].type
#=> "multienum"
Page.attribute_definitions[:my_multienum].values
#=> []

Inheriting attributes:

class Page < Obj
  attribute :title, :string
end

class SpecialPage < Page
end

SpecialPage.attribute_definitions[:title].type
#=> "string"

Overriding inherited attributes:

class Page < Obj
  attribute :title, :string
end

class SpecialPage < Page
  attribute :title, :html
end

Page.attribute_definitions[:title].type
#=> "string"

SpecialPage.attribute_definitions[:title].type
#=> "html"

Specifying valid classes for reference attributes:

class Page < Obj
  attribute :my_reference1, :reference, only: Image
  attribute :my_reference2, :reference, only: [Image, Video]
end

ImageWidget.attribute_definitions[:my_reference1].valid_classes
#=> [Image]

ImageWidget.attribute_definitions[:my_reference2].valid_classes
#=> [Image, Video]

Parameters:

  • name (Symbol, String)

    name of the attribute. The first character must be an ASCII lowercase letter, subsequent characters may also be digits or underscores. Also, the name must not be longer than 50 characters and must not be “id”.

  • type (Symbol, String)

    type of the attribute. Scrivito supports the following types: string, stringlist, html, enum, multienum, widgetlist, reference, referencelist, link, linklist, integer, float and binary.

  • options (Hash) (defaults to: {})

    definition options.

Options Hash (options):

  • :values (Array<Symbol>, Array<String>)

    selectable values for enum and multienum attributes. If no values are provided for attributes of these types, the resulting array of selectable values is empty. Empty string is not allowed as value.

  • :default (Symbol, String)

    custom default value. See DEFAULT_ATTRIBUTE_VALUES for factory defaults. See #default_for for more advanced defaults.

  • :only (Class, Array<Class>)

    specifies (for use in the UI) the valid classes of the values in a reference or a referencelist attribute, e.g. Image or Video. Raises an error if the attribute type is neither reference nor referencelist. If not specified, the UI assumes that any class is valid.

Returns:

  • nil

Raises:

See Also:


459
460
461
462
463
464
465
466
467
468
469
470
# File 'app/cms/scrivito/attribute_content.rb', line 459

def attribute(name, type, options = {})
  name, type, options = name.to_s, type.to_s, options
  assert_valid_attribute_name(name)
  assert_valid_attribute_type(type)
  default = options.delete(:default) || options.delete('default')
  if default
    assert_valid_attribute_default(name, type, default)
    default_for(name) { default }
  end
  own_attribute_definitions[name] = AttributeDefinition.new(name, type, options)
  nil
end

#attribute_definitionsScrivito::AttributeDefinitionCollection

Returns the attribute definitions.


605
606
607
# File 'app/cms/scrivito/attribute_content.rb', line 605

def attribute_definitions
  AttributeDefinitionCollection.new(all_attribute_definitions)
end

#default_for(attribute_name, &block) ⇒ Object

Sets the default value of an attribute defined by #attribute or for the built-in attributes _path and _permalink.

If Obj.create or Widget.new are called without providing a value for a specific custom attribute, the block is called, and its return value is used as the initial value of this attribute.

The block is called with two parameters.

The first parameter is an ActiveSupport::HashWithIndifferentAccess containing the attributes that were passed to Obj.create or Widget.new.

The second parameter, context, is a hash. If the default_for callback is triggered by a UI user creating a CMS object or a Widget, Scrivito places the :scrivito_user and the :current_page (originating from the UI calling the creation method) into this hash. :current_page won't be present in the context if the user creates the object or widget while viewing a page which isn't a CMS object. The context hash is empty if the object or widget is not created using the UI but, for example, via the console.

Examples:

Setting a simple default:

class MyPage < Obj
  attribute :title, :string
  default_for(:title) { 'Spam' }
end

my_page = MyPage.create
my_page.title # => 'Spam'

A default depending on the given attributes:

class MyPage < Obj
  attribute :title, :string

  default_for :title do |attributes|
    if (path = attributes[:_path]) && path.starts_with('/de')
      'Hier den Titel eingeben'
    else
      'Your title here'
    end
  end
end

my_page = MyPage.create(_path: '/en/test')
my_page.title # => 'Your title here'

my_page = MyPage.create(_path: '/de/test')
my_page.title # => 'Hier den Titel eingeben'

A more complex default, depending on the given attributes and the current user:

class MyPage < Obj
  attribute :title, :string

  default_for :title do |attributes, context|
    if use_german_title?(context[:scrivito_user], attributes[:_path])
      'Hier den Titel eingeben'
    else
      'Your title here'
    end
  end

  private

  #
  # Assuming there is a +MyUser+ model equipped with a +preferences+ method which
  # returns the preferences of the current user.
  # The +email+ of a +MyUser+ is the +id+ of the corresponding +Scrivito::User+ as set in
  # +Scrivito::Configuration.editing_auth+.
  #
  def use_german_title?(scrivito_user, path)
    scrivito_user && MyUser.find_by(email: scrivito_user.id).preferences[:locale] == 'de' ||
      path && path.starts_with?('/de')
  end
end

MyUser.find_by(email: '[email protected]').preferences[:locale] # => 'en'
alice = Scrivito::User.define('[email protected]')

my_page = MyPage.create({_path: '/de/test'}, alice)
my_page.title # => 'Your title here'

MyUser.find_by(email: '[email protected]').preferences[:locale] # => 'de'
bob = Scrivito::User.define('[email protected]')

my_page = MyPage.create({_path: '/en/test'}, bob)
my_page.title # => 'Hier den Titel eingeben'

Parameters:

  • attribute_name (Symbol, String)

    the name of the attribute.

  • block (Proc)

    that returns the default value.

Returns:

  • nil

Raises:

See Also:


573
574
575
576
577
578
# File 'app/cms/scrivito/attribute_content.rb', line 573

def default_for(attribute_name, &block)
  attribute_name = attribute_name.to_s
  raise ScrivitoError, 'No block given' unless block_given?
  attribute_default_definitions[attribute_name] = block
  nil
end

#description_for_editorString

Short description of a CMS object or widget type for the UI.

The description is displayed when adding new pages or widgets, for example. As a general rule, it is used whenever no widget or object instance is available. If there is, the BasicObj#description_for_editor and, respectively, BasicWidget#description_for_editor instance methods are used instead.

This method can be overridden to customize the description displayed to editors.

Returns:

  • (String)

    short description of a CMS object or widget type for the UI


594
595
596
# File 'app/cms/scrivito/attribute_content.rb', line 594

def description_for_editor
  name.titleize
end

#hide_from_editorObject

This method prevents UI users from creating Objs or Widgets of the given type. It does not prevent adding such objects programatically.

By default, hide_from_editor is false.

Examples:

Hiding error pages:

class ErrorPage < Obj
  hide_from_editor
end

Hiding admin widgets:

class AdminWidget < Widget
  hide_from_editor
end

650
651
652
# File 'app/cms/scrivito/attribute_content.rb', line 650

def hide_from_editor
  @hide_from_editor = true
end