Class: Thoth::Page

Inherits:
Sequel::Model show all
Includes:
Helper::Wiki
Defined in:
lib/thoth/model/page.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.name_unique?(name) ⇒ Boolean

Returns true if the specified page name is already taken or is a reserved name.

Returns:

  • (Boolean)


58
59
60
61
62
# File 'lib/thoth/model/page.rb', line 58

def self.name_unique?(name)
  !PageController.methods.include?(name) &&
      !PageController.instance_methods.include?(name) &&
      !Page[:name => name.to_s.downcase]
end

.name_valid?(name) ⇒ Boolean

Returns true if the specified page name consists of valid characters and is not too long or too short.

Returns:

  • (Boolean)


66
67
68
# File 'lib/thoth/model/page.rb', line 66

def self.name_valid?(name)
  !!(name =~ /^[0-9a-z_-]{1,64}$/i)
end

.normalize_positionsObject

Adjusts the position values of all pages, resolving duplicate positions and eliminating gaps.



72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/thoth/model/page.rb', line 72

def self.normalize_positions
  db.transaction do
    i = 1

    order(:position).all do |page|
      unless page.position == i
        filter(:id => page.id).update(:position => i)
      end

      i += 1
    end
  end
end

.set_position(page, pos) ⇒ Object

Sets the display position of the specified page, adjusting the position of other pages as necessary.



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/thoth/model/page.rb', line 88

def self.set_position(page, pos)
  unless page.is_a?(Page) || page = Page[page.to_i]
    raise ArgumentError, "Invalid page id: #{page}"
  end

  pos     = pos.to_i
  cur_pos = page.position

  unless pos > 0
    raise ArgumentError, "Invalid position: #{pos}"
  end

  db.transaction do
    if pos < cur_pos
      filter{:position >= pos && :position < cur_pos}.
          update(:position => 'position + 1'.lit)
    elsif pos > cur_pos
      filter{:position > cur_pos && :position <= pos}.
          update(:position => 'position - 1'.lit)
    end

    filter(:id => page.id).update(:position => pos)
  end
end

.suggest_name(title) ⇒ Object

Returns a valid, unique page name based on the specified title. If the title is empty or cannot be converted into a valid name, an empty string will be returned.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/thoth/model/page.rb', line 116

def self.suggest_name(title)
  index = 1

  # Remove HTML entities and non-alphanumeric characters, replace spaces
  # with hyphens, and truncate the name at 64 characters.
  name = title.to_s.strip.downcase.gsub(/&[^\s;]+;/, '_').
      gsub(/[^\s0-9a-z-]/, '').gsub(/\s+/, '-')[0..63]

  # Strip off any trailing non-alphanumeric characters.
  name.gsub!(/[_-]+$/, '')

  return '' if name.empty?

  # Ensure that the name doesn't conflict with any methods on the Page
  # controller and that no two pages have the same name.
  until self.name_unique?(name)
    if name[-1] == index
      name[-1] = (index += 1).to_s
    else
      name = name[0..62] if name.size >= 64
      name += (index += 1).to_s
    end
  end

  return name
end

Instance Method Details

#body=(body) ⇒ Object

– Instance Methods ++



147
148
149
150
# File 'lib/thoth/model/page.rb', line 147

def body=(body)
  self[:body]          = body.strip
  self[:body_rendered] = RedCloth.new(wiki_to_html(body.dup.strip)).to_html
end

#created_at(format = nil) ⇒ Object

Gets the creation time of this page. If format is provided, the time will be returned as a formatted String. See Time.strftime for details.



154
155
156
157
158
159
160
# File 'lib/thoth/model/page.rb', line 154

def created_at(format = nil)
  if new?
    format ? Time.now.strftime(format) : Time.now
  else
    format ? self[:created_at].strftime(format) : self[:created_at]
  end
end

#name=(name) ⇒ Object



162
163
164
# File 'lib/thoth/model/page.rb', line 162

def name=(name)
  self[:name] = name.strip.downcase unless name.nil?
end

#title=(title) ⇒ Object



166
167
168
169
170
171
172
173
174
175
# File 'lib/thoth/model/page.rb', line 166

def title=(title)
  title.strip!

  # Set the page name if it isn't already set.
  if self[:name].nil? || self[:name].empty?
    self[:name] = Page.suggest_name(title)
  end

  self[:title] = title
end

#updated_at(format = nil) ⇒ Object

Gets the time this page was last updated. If format is provided, the time will be returned as a formatted String. See Time.strftime for details.



179
180
181
182
183
184
185
# File 'lib/thoth/model/page.rb', line 179

def updated_at(format = nil)
  if new?
    format ? Time.now.strftime(format) : Time.now
  else
    format ? self[:updated_at].strftime(format) : self[:updated_at]
  end
end

#urlObject

URL for this page.



188
189
190
# File 'lib/thoth/model/page.rb', line 188

def url
  Config.site['url'].chomp('/') + PageController.r(:/, name).to_s
end

#validateObject



192
193
194
195
196
197
198
199
200
201
# File 'lib/thoth/model/page.rb', line 192

def validate
  validates_presence(:name,  :message => 'Please enter a name for this page.')
  validates_presence(:title, :message => 'Please enter a title for this page.')
  validates_presence(:body,  :message => "Come on, I'm sure you can think of something to write.")

  validates_max_length(255, :title, :message => 'Please enter a title under 255 characters.')
  validates_max_length(64,  :name,  :message => 'Please enter a name under 64 characters.')

  validates_format(/^[0-9a-z_-]+$/i, :name, :message => 'Page names may only contain letters, numbers, underscores, and dashes.')
end