Class: Valkyrie::Resource

Inherits:
Dry::Struct
  • Object
show all
Includes:
Draper::Decoratable
Defined in:
lib/valkyrie/resource.rb,
lib/valkyrie/resource/access_controls.rb

Overview

The base resource class for all Valkyrie metadata objects. rubocop:disable Metrics/ClassLength

Examples:

Define a resource

class Book < Valkyrie::Resource
  attribute :member_ids, Valkyrie::Types::Array
  attribute :author
end

See Also:

Defined Under Namespace

Modules: AccessControls Classes: ReservedAttributeError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.allow_nonexistent_keysObject

Allows a Valkyrie::Resource to be instantiated without providing every available key, and makes sure the defaults are set up if no value is given.



22
23
24
# File 'lib/valkyrie/resource.rb', line 22

def self.allow_nonexistent_keys
  transform_types(&:omittable)
end

.attribute(name, type = Valkyrie::Types::Set.optional, internal: false) ⇒ Object

Note:

Overridden from Dry::Struct to make the default type Types::Set

Define an attribute. Attributes are used to describe resources.

Parameters:

  • name (Symbol)
  • type (Dry::Types::Type) (defaults to: Valkyrie::Types::Set.optional)

Raises:



48
49
50
51
52
53
54
# File 'lib/valkyrie/resource.rb', line 48

def self.attribute(name, type = Valkyrie::Types::Set.optional, internal: false)
  raise ReservedAttributeError, "#{name} is a reserved attribute and defined by Valkyrie::Resource, do not redefine it." if reserved_attributes.include?(name.to_sym) &&
                                                                                                                            attribute_names.include?(name.to_sym) &&
                                                                                                                            !internal

  super(name, type)
end

.attributes(new_schema) ⇒ Dry::Struct

Note:

extends Dry::Struct by adding ‘#attr=` style setters

Parameters:

  • new_schema (Hash{Symbol => Dry::Types::Type})

Returns:

  • (Dry::Struct)

Raises:

  • (RepeatedAttributeError)

    when trying to define attribute with the same name as previously defined one

  • (ReservedAttributeError)

    when trying to define an attribute reserved by Valkyrie

See Also:

  • #attribute


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/valkyrie/resource.rb', line 64

def self.attributes(new_schema)
  new_schema[:member_ids] = new_schema[:member_ids].meta(ordered: true) if
    new_schema.key?(:member_ids)

  super

  new_schema.each_key do |key|
    key = key.to_s.chomp('?')
    next if instance_methods.include?("#{key}=".to_sym)

    class_eval(<<-RUBY)
      def #{key}=(value)
        set_value("#{key}".to_sym, value)
      end
    RUBY
  end

  self
end

.enable_optimistic_lockingObject



104
105
106
# File 'lib/valkyrie/resource.rb', line 104

def self.enable_optimistic_locking
  attribute(Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK, Valkyrie::Types::Set.of(Valkyrie::Types::OptimisticLockToken))
end

.fieldsArray<Symbol>

Returns Array of fields defined for this class.

Returns:

  • (Array<Symbol>)

    Array of fields defined for this class.



39
40
41
# File 'lib/valkyrie/resource.rb', line 39

def self.fields
  attribute_names.without(:new_record)
end

.human_readable_typeObject



96
97
98
# File 'lib/valkyrie/resource.rb', line 96

def self.human_readable_type
  @_human_readable_type ||= name.demodulize.titleize
end

.human_readable_type=(val) ⇒ Object



100
101
102
# File 'lib/valkyrie/resource.rb', line 100

def self.human_readable_type=(val)
  @_human_readable_type = val
end

.inherited(subclass) ⇒ Object

Note:

The current theory is that we should use this sparingly.

Overridden to provide default attributes.



28
29
30
31
32
33
34
35
36
# File 'lib/valkyrie/resource.rb', line 28

def self.inherited(subclass)
  super(subclass)
  subclass.allow_nonexistent_keys
  subclass.attribute :id, Valkyrie::Types::ID.optional, internal: true
  subclass.attribute :internal_resource, Valkyrie::Types::Any.default(subclass.to_s.freeze), internal: true
  subclass.attribute :created_at, Valkyrie::Types::DateTime.optional, internal: true
  subclass.attribute :updated_at, Valkyrie::Types::DateTime.optional, internal: true
  subclass.attribute :new_record, Types::Bool.default(true), internal: true
end

.model_nameActiveModel::Name

Note:

Added for ActiveModel compatibility.

Returns:

  • (ActiveModel::Name)


90
91
92
# File 'lib/valkyrie/resource.rb', line 90

def self.model_name
  @model_name ||= ::ActiveModel::Name.new(self)
end

.optimistic_locking_enabled?Boolean

Returns:

  • (Boolean)


108
109
110
# File 'lib/valkyrie/resource.rb', line 108

def self.optimistic_locking_enabled?
  schema.key?(Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK)
end

.reserved_attributesObject



84
85
86
# File 'lib/valkyrie/resource.rb', line 84

def self.reserved_attributes
  [:id, :internal_resource, :created_at, :updated_at, :new_record]
end

Instance Method Details

#[](name) ⇒ Object

Return an attribute’s value.

Parameters:

  • name (#to_sym)

    the name of the attribute to read



178
179
180
181
182
# File 'lib/valkyrie/resource.rb', line 178

def [](name)
  super(name.to_sym)
rescue Dry::Struct::MissingAttributeError
  nil
end

#__attributes__Object



124
125
126
# File 'lib/valkyrie/resource.rb', line 124

def __attributes__
  Hash[@attributes].freeze
end

#attributesObject



120
121
122
# File 'lib/valkyrie/resource.rb', line 120

def attributes
  Hash[self.class.attribute_names.map { |x| [x, nil] }].merge(super).freeze
end

#clear_optimistic_lock_token!Object



116
117
118
# File 'lib/valkyrie/resource.rb', line 116

def clear_optimistic_lock_token!
  send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", []) if optimistic_locking_enabled?
end

#column_for_attribute(name) ⇒ Symbol

Note:

Added for ActiveModel compatibility.

Parameters:

  • name (Symbol)

Returns:

  • (Symbol)


141
142
143
# File 'lib/valkyrie/resource.rb', line 141

def column_for_attribute(name)
  name
end

#dupObject



128
129
130
# File 'lib/valkyrie/resource.rb', line 128

def dup
  new({})
end

#has_attribute?(name) ⇒ Boolean

Parameters:

  • name (Symbol)

    Attribute name

Returns:

  • (Boolean)


134
135
136
# File 'lib/valkyrie/resource.rb', line 134

def has_attribute?(name)
  respond_to?(name)
end

#human_readable_typeString

Provide a human readable name for the resource

Returns:

  • (String)


171
172
173
# File 'lib/valkyrie/resource.rb', line 171

def human_readable_type
  self.class.human_readable_type
end

#optimistic_locking_enabled?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'lib/valkyrie/resource.rb', line 112

def optimistic_locking_enabled?
  self.class.optimistic_locking_enabled?
end

#ordered_attribute?(key) ⇒ Boolean

Returns if an attribute is set as ordered.

Returns:

  • (Boolean)


193
194
195
# File 'lib/valkyrie/resource.rb', line 193

def ordered_attribute?(key)
  self.class.schema.key(key.to_sym).type.meta.try(:[], :ordered)
end

#persisted?Boolean

Returns:

  • (Boolean)


146
147
148
# File 'lib/valkyrie/resource.rb', line 146

def persisted?
  new_record == false
end

#set_value(key, value) ⇒ Object

Set an attribute’s value.

Parameters:

  • key (#to_sym)

    the name of the attribute to set

  • value

    the value to set key to.



188
189
190
# File 'lib/valkyrie/resource.rb', line 188

def set_value(key, value)
  @attributes[key.to_sym] = self.class.schema.key(key.to_sym).type.call(value)
end

#to_keyObject



150
151
152
# File 'lib/valkyrie/resource.rb', line 150

def to_key
  [id]
end

#to_modelObject

Note:

Added for ActiveModel compatibility



159
160
161
# File 'lib/valkyrie/resource.rb', line 159

def to_model
  self
end

#to_paramObject



154
155
156
# File 'lib/valkyrie/resource.rb', line 154

def to_param
  to_key.map(&:to_s).join('-')
end

#to_sString

Returns:

  • (String)


164
165
166
# File 'lib/valkyrie/resource.rb', line 164

def to_s
  "#{self.class}: #{id}"
end