Class: Refinery::Page

Inherits:
Core::BaseModel
  • Object
show all
Extended by:
FriendlyId
Defined in:
app/models/refinery/page.rb

Defined Under Namespace

Classes: Translation

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.by_slug(slug, conditions = {}) ⇒ Object

Finds pages by their slug. This method is necessary because pages are translated which means the slug attribute does not exist on the pages table thus requiring us to find the attribute on the translations table and then join to the pages table again to return the associated record.



115
116
117
118
119
120
# File 'app/models/refinery/page.rb', line 115

def by_slug(slug, conditions={})
  with_globalize({
    :locale => Refinery::I18n.frontend_locales.map(&:to_s),
    :slug => slug
  }.merge(conditions))
end

.by_title(title) ⇒ Object

Finds pages by their title. This method is necessary because pages are translated which means the title attribute does not exist on the pages table thus requiring us to find the attribute on the translations table and then join to the pages table again to return the associated record.



107
108
109
# File 'app/models/refinery/page.rb', line 107

def by_title(title)
  with_globalize(:title => title)
end

.fast_menuObject

An optimised scope containing only live pages ordered for display in a menu.



131
132
133
# File 'app/models/refinery/page.rb', line 131

def fast_menu
  live.in_menu.order(arel_table[:lft]).includes(:parent, :translations)
end

.find_by_path(path) ⇒ Object

Find page by path, checking for scoping rules



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'app/models/refinery/page.rb', line 70

def find_by_path(path)
  if ::Refinery::Pages.scope_slug_by_parent
    # With slugs scoped to the parent page we need to find a page by its full path.
    # For example with about/example we would need to find 'about' and then its child
    # called 'example' otherwise it may clash with another page called /example.
    path = path.split('/').select(&:present?)
    page = by_slug(path.shift, :parent_id => nil).first
    while page && path.any? do
      slug_or_id = path.shift
      page = page.children.by_slug(slug_or_id).first || page.children.find(slug_or_id)
    end
  else
    page = by_slug(path).first
  end

  page
end

.find_by_path_or_id(path, id) ⇒ Object

Helps to resolve the situation where you have a path and an id and if the path is unfriendly then a different finder method is required than find_by_path.



91
92
93
94
95
96
97
98
99
100
101
# File 'app/models/refinery/page.rb', line 91

def find_by_path_or_id(path, id)
  if path.present?
    if path.friendly_id?
      find_by_path(path)
    else
      find(path)
    end
  elsif id.present?
    find(id)
  end
end

.in_menuObject

Shows all pages with :show_in_menu set to true, but it also rejects any page that has not been translated to the current locale. This works using a query against the translated content first and then using all of the page_ids we further filter against this model’s table.



126
127
128
# File 'app/models/refinery/page.rb', line 126

def in_menu
  where(:show_in_menu => true).with_globalize
end

.liveObject

Live pages are ‘allowed’ to be shown in the frontend of your website. By default, this is all pages that are not set as ‘draft’.



65
66
67
# File 'app/models/refinery/page.rb', line 65

def live
  where(:draft => false)
end

.per_page(dialog = false) ⇒ Object

Returns how many pages per page should there be when paginating pages



153
154
155
# File 'app/models/refinery/page.rb', line 153

def per_page(dialog = false)
  dialog ? Pages.pages_per_dialog : Pages.pages_per_admin_index
end

.rebuild_with_slug_nullification!Object



157
158
159
160
# File 'app/models/refinery/page.rb', line 157

def rebuild_with_slug_nullification!
  rebuild_without_slug_nullification!
  nullify_duplicate_slugs_under_the_same_parent!
end

.with_globalize(conditions = {}) ⇒ Object

Wrap up the logic of finding the pages based on the translations table.



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'app/models/refinery/page.rb', line 136

def with_globalize(conditions = {})
  conditions = {:locale => ::Globalize.locale.to_s}.merge(conditions)
  translations_conditions = {}
  translated_attrs = translated_attribute_names.map(&:to_s) | %w(locale)

  conditions.keys.each do |key|
    if translated_attrs.include? key.to_s
      translations_conditions["#{self.translation_class.table_name}.#{key}"] = conditions.delete(key)
    end
  end

  # A join implies readonly which we don't really want.
  where(conditions).joins(:translations).where(translations_conditions).
                                         readonly(false)
end

Instance Method Details

#canonicalObject

The canonical page for this particular page. Consists of:

* The default locale's translated slug


183
184
185
# File 'app/models/refinery/page.rb', line 183

def canonical
  Globalize.with_locale(::Refinery::I18n.default_frontend_locale) { url }
end

#canonical_slugObject

The canonical slug for this particular page. This is the slug for the default frontend locale.



189
190
191
# File 'app/models/refinery/page.rb', line 189

def canonical_slug
  Globalize.with_locale(::Refinery::I18n.default_frontend_locale) { slug }
end

#content_for(part_title) ⇒ Object

Accessor method to get a page part from a page. Example:

::Refinery::Page.first.content_for(:body)

Will return the body page part of the first page.



333
334
335
# File 'app/models/refinery/page.rb', line 333

def content_for(part_title)
  part_with_title(part_title).try(:body)
end

#content_for?(part_title) ⇒ Boolean

Accessor method to test whether a page part exists and has content for this page. Example:

::Refinery::Page.first.content_for?(:body)

Will return true if the page has a body page part and it is not blank.

Returns:

  • (Boolean)


344
345
346
# File 'app/models/refinery/page.rb', line 344

def content_for?(part_title)
  content_for(part_title).present?
end

#custom_slug_or_titleObject

Returns in cascading order: custom_slug or menu_title or title depending on which attribute is first found to be present for this page.



195
196
197
# File 'app/models/refinery/page.rb', line 195

def custom_slug_or_title
  custom_slug.presence || menu_title.presence || title.presence
end

#deletable?Boolean

Am I allowed to delete this page? If a link_url is set we don’t want to break the link so we don’t allow them to delete If deletable is set to false then we don’t allow this page to be deleted. These are often Refinery system pages

Returns:

  • (Boolean)


202
203
204
# File 'app/models/refinery/page.rb', line 202

def deletable?
  deletable && link_url.blank? && menu_match.blank?
end

#destroyObject

Before destroying a page we check to see if it’s a deletable page or not Refinery system pages are not deletable.



216
217
218
219
220
221
222
# File 'app/models/refinery/page.rb', line 216

def destroy
  return super if deletable?

  puts_destroy_help

  false
end

#destroy!Object

If you want to destroy a page that is set to be not deletable this is the way to do it.



225
226
227
228
229
230
231
# File 'app/models/refinery/page.rb', line 225

def destroy!
  self.menu_match = nil
  self.link_url = nil
  self.deletable = true

  destroy
end

#in_menu?Boolean

Return true if this page can be shown in the navigation. If it’s a draft or is set to not show in the menu it will return false.

Returns:

  • (Boolean)


300
301
302
# File 'app/models/refinery/page.rb', line 300

def in_menu?
  live? && show_in_menu?
end

Returns:

  • (Boolean)


252
253
254
255
256
# File 'app/models/refinery/page.rb', line 252

def link_url_localised?
  Refinery.deprecate "Refinery::Page#link_url_localised?", :when => '2.2',
                     :replacement => "Refinery::Pages::Url::Localised#url"
  Pages::Url::Localised.new(self).url
end

#live?Boolean

Returns true if this page is “published”

Returns:

  • (Boolean)


294
295
296
# File 'app/models/refinery/page.rb', line 294

def live?
  !draft?
end

#nested_pathObject

Returns the string version of nested_url, i.e., the path that should be generated by the router



289
290
291
# File 'app/models/refinery/page.rb', line 289

def nested_path
  ['', nested_url].join('/')
end

#nested_urlObject Also known as: uncached_nested_url



270
271
272
273
274
275
276
277
# File 'app/models/refinery/page.rb', line 270

def nested_url
  globalized_slug = Globalize.with_locale(slug_locale) { to_param.to_s }
  if ::Refinery::Pages.scope_slug_by_parent
    [parent.try(:nested_url), globalized_slug].compact.flatten
  else
    [globalized_slug]
  end
end

#not_in_menu?Boolean

Returns:

  • (Boolean)


304
305
306
# File 'app/models/refinery/page.rb', line 304

def not_in_menu?
  !in_menu?
end

#part_with_title(part_title) ⇒ Object

Accessor method to get a page part object from a page. Example:

::Refinery::Page.first.part_with_title(:body)

Will return the Refinery::PagePart object with that title using the first page.



354
355
356
357
358
359
360
361
362
# File 'app/models/refinery/page.rb', line 354

def part_with_title(part_title)
  # self.parts is usually already eager loaded so we can now just grab
  # the first element matching the title we specified.
  self.parts.detect do |part|
    part.title.present? and # protecting against the problem that occurs when have nil title
    part.title == part_title.to_s or
    part.title.downcase.gsub(" ", "_") == part_title.to_s.downcase.gsub(" ", "_")
  end
end

#path(options = {}) ⇒ Object

Used for the browser title to get the full path to this page It automatically prints out this page title and all of it’s parent page titles joined by a PATH_SEPARATOR



235
236
237
238
239
240
241
242
243
244
245
246
# File 'app/models/refinery/page.rb', line 235

def path(options = {})
  # Override default options with any supplied.
  options = {:reversed => true}.merge(options)

  if parent_id
    parts = [title, parent.path(options)]
    parts.reverse! if options[:reversed]
    parts.join(' - ')
  else
    title
  end
end

#reposition_parts!Object

Repositions the child page_parts that belong to this page. This ensures that they are in the correct 0,1,2,3,4… etc order.



208
209
210
211
212
# File 'app/models/refinery/page.rb', line 208

def reposition_parts!
  reload.parts.each_with_index do |part, index|
    part.update_attributes :position => index
  end
end

#shown_siblingsObject

Returns all visible sibling pages that can be rendered for the menu



309
310
311
# File 'app/models/refinery/page.rb', line 309

def shown_siblings
  siblings.reject(&:not_in_menu?)
end

#to_refinery_menu_itemObject



313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'app/models/refinery/page.rb', line 313

def to_refinery_menu_item
  {
    :id => id,
    :lft => lft,
    :depth => depth,
    :menu_match => menu_match,
    :parent_id => parent_id,
    :rgt => rgt,
    :title => menu_title.presence || title.presence,
    :type => self.class.name,
    :url => url
  }
end

#translated_to_default_locale?Boolean

Returns:

  • (Boolean)


176
177
178
# File 'app/models/refinery/page.rb', line 176

def translated_to_default_locale?
  persisted? && translations.where(:locale => Refinery::I18n.default_frontend_locale).any?
end

#urlObject



248
249
250
# File 'app/models/refinery/page.rb', line 248

def url
  Pages::Url.build(self)
end

#url_marketableObject



264
265
266
267
268
# File 'app/models/refinery/page.rb', line 264

def url_marketable
  Refinery.deprecate "Refinery::Page#url_marketable", :when => '2.2',
                     :replacement => "Refinery::Pages::Url::Marketable#url"
  Pages::Url::Marketable.new(self).url
end

#url_normalObject



258
259
260
261
262
# File 'app/models/refinery/page.rb', line 258

def url_normal
  Refinery.deprecate "Refinery::Page#url_normal", :when => '2.2',
                     :replacement => "Refinery::Pages::Url::Normal#url"
  Pages::Url::Normal.new(self).url
end