Module: Draftsman::Model::ClassMethods

Defined in:
lib/draftsman/model.rb

Instance Method Summary collapse

Instance Method Details

#draft_classObject

Returns draft class.



114
115
116
# File 'lib/draftsman/model.rb', line 114

def draft_class
  @draft_class ||= draft_class_name.constantize
end

#draftable?Boolean

Returns whether or not ‘has_drafts` has been called on this model.

Returns:

  • (Boolean)


119
120
121
# File 'lib/draftsman/model.rb', line 119

def draftable?
  method_defined?(:draftsman_options)
end

#has_drafts(options = {}) ⇒ Object

Declare this in your model to enable the Draftsman API for it. A draft of the model is available in the ‘draft` association (if one exists).

Options:

:class_name The name of a custom ‘Draft` class. This class should inherit from `Draftsman::Draft`. A global default can be set for this using `Draftsman.draft_class_name=` if the default of `Draftsman::Draft` needs to be overridden.

:ignore An array of attributes for which an update to a ‘Draft` will not be stored if they are the only ones changed.

:only Inverse of ‘ignore` - a new `Draft` will be created only for these attributes if supplied. It’s recommended that you only specify optional attributes for this (that can be empty).

:skip Fields to ignore completely. As with ‘ignore`, updates to these fields will not create a new `Draft`. In addition, these fields will not be included in the serialized versions of the object whenever a new `Draft` is created.

:meta A hash of extra data to store. You must add a column to the ‘drafts` table for each key. Values are objects or `procs` (which are called with `self`, i.e. the model with the `has_drafts`). See `Draftsman::Controller.info_for_draftsman` for an example of how to store data from the controller.

:draft The name to use for the ‘draft` association shortcut method. Default is `:draft`.

:published_at The name to use for the method which returns the published timestamp. Default is ‘published_at`.

:trashed_at The name to use for the method which returns the soft delete timestamp. Default is ‘trashed_at`.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/draftsman/model.rb', line 43

def has_drafts(options = {})
  # Lazily include the instance methods so we don't clutter up
  # any more ActiveRecord models than we need to.
  send :include, InstanceMethods

  class_attribute :draftsman_options
  self.draftsman_options = options.dup

  class_attribute :draft_association_name
  self.draft_association_name = options[:draft] || :draft

  class_attribute :draft_class_name
  self.draft_class_name = options[:class_name] || Draftsman.draft_class_name

  [:ignore, :skip, :only].each do |key|
    draftsman_options[key] = ([draftsman_options[key]].flatten.compact || []).map(&:to_s)
  end

  draftsman_options[:ignore] << "#{self.draft_association_name}_id"

  draftsman_options[:meta] ||= {}

  attr_accessor :draftsman_event

  class_attribute :published_at_attribute_name
  self.published_at_attribute_name = options[:published_at] || :published_at

  class_attribute :trashed_at_attribute_name
  self.trashed_at_attribute_name = options[:trashed_at] || :trashed_at

  # `belongs_to :draft` association
  belongs_to self.draft_association_name, :class_name => self.draft_class_name, :dependent => :destroy

  # Scopes
  scope :drafted, (lambda do |referenced_table_name = nil|
    referenced_table_name = referenced_table_name.present? ? referenced_table_name : table_name

    if where_not?
      where.not(referenced_table_name => { "#{self.draft_association_name}_id" => nil })
    else
      where("#{referenced_table_name}.#{self.draft_association_name}_id IS NOT NULL")
    end
  end)

  scope :published, (lambda do |referenced_table_name = nil|
    referenced_table_name = referenced_table_name.present? ? referenced_table_name : table_name

    if where_not?
      where.not(referenced_table_name => { self.published_at_attribute_name => nil })
    else
      where("#{self.published_at_attribute_name} IS NOT NULL")
    end
  end)

  scope :trashed, (lambda do |referenced_table_name = nil|
    referenced_table_name = referenced_table_name.present? ? referenced_table_name : table_name

    if where_not?
      where.not(referenced_table_name => { self.trashed_at_attribute_name => nil })
    else
      where("#{self.trashed_at_attribute_name} IS NOT NULL")
    end
  end)

  scope :live, (lambda do |referenced_table_name = nil|
    referenced_table_name = referenced_table_name.present? ? referenced_table_name : table_name
    where(referenced_table_name => { self.trashed_at_attribute_name => nil })
  end)
end

#serialize_attributes_for_draftsman(attributes) ⇒ Object

Used for ‘Draft#object` attribute



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/draftsman/model.rb', line 138

def serialize_attributes_for_draftsman(attributes)
  # Don't serialize values before inserting into columns of type `JSON` on PostgreSQL databases.
  return attributes if self.draft_class.object_col_is_json?

  serialized_attributes.each do |key, coder|
    if attributes.key?(key)
      coder = Draftsman::Serializers::Yaml unless coder.respond_to?(:dump) # Fall back to YAML if `coder` has no `dump` method
      attributes[key] = coder.dump(attributes[key])
    end
  end
end

#serialize_draft_attribute_changes(changes) ⇒ Object

Serializes attribute changes for ‘Draft#object_changes` attribute.



124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/draftsman/model.rb', line 124

def serialize_draft_attribute_changes(changes)
  # Don't serialize values before inserting into columns of type `JSON` on PostgreSQL databases.
  return changes if self.draft_class.object_changes_col_is_json?

  serialized_attributes.each do |key, coder|
    if changes.key?(key)
      coder = Draftsman::Serializers::Yaml unless coder.respond_to?(:dump) # Fall back to YAML if `coder` has no `dump` method
      old_value, new_value = changes[key]
      changes[key] = [coder.dump(old_value), coder.dump(new_value)]
    end
  end
end

#trashable?Boolean

Returns whether or not a ‘trashed_at` timestamp is set up on this model.

Returns:

  • (Boolean)


151
152
153
# File 'lib/draftsman/model.rb', line 151

def trashable?
  draftable? && method_defined?(self.trashed_at_attribute_name)
end

#unserialize_attributes_for_draftsman(attributes) ⇒ Object

Used for ‘Draft#object` attribute



170
171
172
173
174
175
176
177
178
179
180
# File 'lib/draftsman/model.rb', line 170

def unserialize_attributes_for_draftsman(attributes)
  # Don't serialize values before inserting into columns of type `JSON` on PostgreSQL databases.
  return attributes if self.draft_class.object_col_is_json?

  serialized_attributes.each do |key, coder|
    if attributes.key?(key)
      coder = Draftsman::Serializers::Yaml unless coder.respond_to?(:dump)
      attributes[key] = coder.load(attributes[key])
    end
  end
end

#unserialize_draft_attribute_changes(changes) ⇒ Object

Unserializes attribute changes for ‘Draft#object_changes` attribute.



156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/draftsman/model.rb', line 156

def unserialize_draft_attribute_changes(changes)
  # Don't serialize values before inserting into columns of type `JSON` on PostgreSQL databases.
  return changes if self.draft_class.object_changes_col_is_json?

  serialized_attributes.each do |key, coder|
    if changes.key?(key)
      coder = Draftsman::Serializers::Yaml unless coder.respond_to?(:dump)
      old_value, new_value = changes[key]
      changes[key] = [coder.load(old_value), coder.load(new_value)]
    end
  end
end

#where_not?Boolean

Returns whether or not the included ActiveRecord can do ‘where.not(…)` style queries.

Returns:

  • (Boolean)


183
184
185
# File 'lib/draftsman/model.rb', line 183

def where_not?
  ActiveRecord::VERSION::STRING.to_f >= 4.0
end