Class: Refinery::Page
- Inherits:
-
Core::BaseModel
- Object
- Core::BaseModel
- Refinery::Page
- Extended by:
- FriendlyId
- Defined in:
- app/models/refinery/page.rb
Defined Under Namespace
Classes: Translation
Constant Summary collapse
- PATH_SEPARATOR =
when collecting the pages path how is each of the pages seperated?
" - "
Instance Attribute Summary collapse
-
#locale ⇒ Object
to hold temporarily.
-
#page_menu_title ⇒ Object
to hold temporarily.
-
#page_title ⇒ Object
to hold temporarily.
Class Method Summary collapse
-
.by_slug(slug, conditions = {}) ⇒ Object
Finds pages by their slug.
-
.by_title(title) ⇒ Object
Finds pages by their title.
-
.different_frontend_locale? ⇒ Boolean
Wraps up all the checks that we need to do to figure out whether the current frontend locale is different to the current one set by ::I18n.locale.
- .expire_page_caching ⇒ Object
-
.fast_menu(columns = []) ⇒ Object
Because pages are translated this can have a negative performance impact on your website and can introduce scaling issues.
-
.find_by_path(path) ⇒ Object
With slugs scoped to the parent page we need to find a page by its full path.
-
.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.
-
.in_menu ⇒ Object
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.
-
.live ⇒ Object
Live pages are ‘allowed’ to be shown in the frontend of your website.
-
.menu_columns ⇒ Object
Override this method to change which columns you want to select to render your menu.
-
.per_page(dialog = false) ⇒ Object
Returns how many pages per page should there be when paginating pages.
- .rebuild_with_invalidate_cached_urls! ⇒ Object
-
.with_globalize(conditions = {}) ⇒ Object
Wrap up the logic of finding the pages based on the translations table.
Instance Method Summary collapse
-
#all_page_part_content ⇒ Object
Used to index all the content on this page so it can be easily searched.
- #cache_key(locale) ⇒ Object
-
#canonical ⇒ Object
The canonical page for this particular page.
-
#canonical_slug ⇒ Object
The canonical slug for this particular page.
-
#content_for(part_title) ⇒ Object
Accessor method to get a page part from a page.
-
#custom_slug_or_title ⇒ Object
Returns in cascading order: custom_slug or menu_title or title depending on which attribute is first found to be present for this page.
-
#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.
-
#destroy ⇒ Object
Before destroying a page we check to see if it’s a deletable page or not Refinery system pages are not deletable.
-
#destroy! ⇒ Object
If you want to destroy a page that is set to be not deletable this is the way to do it.
-
#home? ⇒ Boolean
Returns true if this page is the home page or links to it.
-
#in_menu? ⇒ Boolean
Return true if this page can be shown in the navigation.
-
#link_url_localised? ⇒ Boolean
Adds the locale key into the URI for this page’s link_url attribute, unless the current locale is set as the default locale.
-
#live? ⇒ Boolean
Returns true if this page is “published”.
-
#nested_path ⇒ Object
Returns the string version of nested_url, i.e., the path that should be generated by the router.
-
#normalize_friendly_id_with_marketable_urls(slug_string) ⇒ Object
Protects generated slugs from title if they are in the list of reserved words This applies mostly to plugin-generated pages.
- #not_in_menu? ⇒ Boolean
-
#part_with_title(part_title) ⇒ Object
Accessor method to get a page part object from a page.
-
#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.
- #path_cache_key(locale = Globalize.locale) ⇒ Object
- #refinery_menu_title ⇒ Object
-
#reposition_parts! ⇒ Object
Repositions the child page_parts that belong to this page.
-
#shown_siblings ⇒ Object
Returns all visible sibling pages that can be rendered for the menu.
- #to_refinery_menu_item ⇒ Object
- #uncached_nested_url ⇒ Object (also: #nested_url)
-
#url ⇒ Object
When this page is rendered in the navigation, where should it link? If a custom “link_url” is set, it uses that otherwise it defaults to a normal page URL.
- #url_cache_key(locale = Globalize.locale) ⇒ Object
-
#url_marketable ⇒ Object
Add ‘marketable url’ attributes into this page’s url.
-
#url_normal ⇒ Object
Returns a url suitable to be used in url_for in Rails (such as link_to).
-
#with_locale_param(url_hash, locale = nil) ⇒ Object
If the current locale is set to something other than the default locale then the :locale attribute will be set on the url hash, otherwise it won’t be.
Instance Attribute Details
#locale ⇒ Object
to hold temporarily
32 33 34 |
# File 'app/models/refinery/page.rb', line 32 def locale @locale end |
#page_menu_title ⇒ Object
to hold temporarily
32 33 34 |
# File 'app/models/refinery/page.rb', line 32 def @page_menu_title end |
#page_title ⇒ Object
to hold temporarily
32 33 34 |
# File 'app/models/refinery/page.rb', line 32 def page_title @page_title end |
Class Method Details
.by_slug(slug, conditions = {}) ⇒ Object
Finds pages by their slug. See by_title
107 108 109 110 |
# File 'app/models/refinery/page.rb', line 107 def by_slug(slug, conditions={}) locales = Refinery.i18n_enabled? ? Refinery::I18n.frontend_locales.map(&:to_s) : ::I18n.locale.to_s with_globalize({ :locale => locales, :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.
102 103 104 |
# File 'app/models/refinery/page.rb', line 102 def by_title(title) with_globalize(:title => title) end |
.different_frontend_locale? ⇒ Boolean
Wraps up all the checks that we need to do to figure out whether the current frontend locale is different to the current one set by ::I18n.locale. This terminates in a false if i18n extension is not defined or enabled.
165 166 167 |
# File 'app/models/refinery/page.rb', line 165 def different_frontend_locale? ::Refinery.i18n_enabled? && ::Refinery::I18n.current_frontend_locale != ::I18n.locale end |
.expire_page_caching ⇒ Object
180 181 182 183 184 185 186 187 188 189 |
# File 'app/models/refinery/page.rb', line 180 def expire_page_caching begin Rails.cache.delete_matched(/.*pages.*/) rescue NotImplementedError Rails.cache.clear warn "**** [REFINERY] The cache store you are using is not compatible with Rails.cache#delete_matched - clearing entire cache instead ***" ensure return true # so that other callbacks process. end end |
.fast_menu(columns = []) ⇒ Object
Because pages are translated this can have a negative performance impact on your website and can introduce scaling issues. What fast_menu does is finds all of the columns necessary to render a Refinery::Menu
structure using only one SQL query. This has limitations, including not being able to access any other attributes of the pages but you can specify more columns by passing in an array e.g. fast_menu([:column1, :column2])
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'app/models/refinery/page.rb', line 126 def (columns = []) # First, apply a filter to determine which pages to show. pages = live..order('lft ASC').includes(:translations) # Now we only want to select particular columns to avoid any further queries. # Title and menu_title are retrieved in the next block below so they are not here. ( | columns).each do |column| pages = pages.select(arel_table[column.to_sym]) end # We have to get title and menu_title from the translations table. # To avoid calling globalize3 an extra time, we get title as page_title # and we get menu_title as page_menu_title. # These is used in 'to_refinery_menu_item' in the Page model. %w(title menu_title).each do |column| pages = pages.joins(:translations).select( "#{translation_class.table_name}.#{column} as page_#{column}" ) end pages end |
.find_by_path(path) ⇒ Object
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.
75 76 77 78 79 80 81 |
# File 'app/models/refinery/page.rb', line 75 def find_by_path(path) split_path = path.to_s.split('/').reject(&:blank?) page = ::Refinery::Page.by_slug(split_path.shift, :parent_id => nil).first page = page.children.by_slug(split_path.shift).first until page.nil? || split_path.empty? 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.
86 87 88 89 90 91 92 93 94 95 96 |
# File 'app/models/refinery/page.rb', line 86 def find_by_path_or_id(path, id) if Refinery::Pages.marketable_urls && path.present? if path.friendly_id? find_by_path(path) else find(path) end elsif id.present? find(id) end end |
.in_menu ⇒ Object
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.
116 117 118 |
# File 'app/models/refinery/page.rb', line 116 def where(:show_in_menu => true).with_globalize end |
.live ⇒ Object
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’.
68 69 70 |
# File 'app/models/refinery/page.rb', line 68 def live where(:draft => false) end |
.menu_columns ⇒ Object
Override this method to change which columns you want to select to render your menu. title and menu_title are always retrieved so omit these.
171 172 173 |
# File 'app/models/refinery/page.rb', line 171 def %w(id depth parent_id lft rgt link_url menu_match slug) end |
.per_page(dialog = false) ⇒ Object
Returns how many pages per page should there be when paginating pages
176 177 178 |
# File 'app/models/refinery/page.rb', line 176 def per_page(dialog = false) dialog ? Pages.pages_per_dialog : Pages.pages_per_admin_index end |
.rebuild_with_invalidate_cached_urls! ⇒ Object
191 192 193 194 |
# File 'app/models/refinery/page.rb', line 191 def rebuild_with_invalidate_cached_urls! rebuild_without_invalidate_cached_urls! find_each { |page| page.send :invalidate_cached_urls } end |
.with_globalize(conditions = {}) ⇒ Object
Wrap up the logic of finding the pages based on the translations table.
150 151 152 153 154 155 156 157 158 159 160 |
# File 'app/models/refinery/page.rb', line 150 def with_globalize(conditions = {}) conditions = {:locale => ::Globalize.locale.to_s}.merge(conditions) globalized_conditions = {} conditions.keys.each do |key| if (translated_attribute_names.map(&:to_s) | %w(locale)).include?(key.to_s) globalized_conditions["#{self.translation_class.table_name}.#{key}"] = conditions.delete(key) end end # A join implies readonly which we don't really want. joins(:translations).where(globalized_conditions).where(conditions).readonly(false) end |
Instance Method Details
#all_page_part_content ⇒ Object
Used to index all the content on this page so it can be easily searched.
424 425 426 |
# File 'app/models/refinery/page.rb', line 424 def all_page_part_content parts.map(&:body).join(" ") end |
#cache_key(locale) ⇒ Object
351 352 353 |
# File 'app/models/refinery/page.rb', line 351 def cache_key(locale) [Refinery::Core.base_cache_key, 'page', locale, id].compact.join('/') end |
#canonical ⇒ Object
The canonical page for this particular page. Consists of:
* The default locale's translated slug
201 202 203 |
# File 'app/models/refinery/page.rb', line 201 def canonical Globalize.with_locale(Refinery.i18n_enabled? && Refinery::I18n.default_frontend_locale || ::I18n.locale) { url } end |
#canonical_slug ⇒ Object
The canonical slug for this particular page. This is the slug for the default frontend locale.
207 208 209 |
# File 'app/models/refinery/page.rb', line 207 def canonical_slug Globalize.with_locale(Refinery.i18n_enabled? && Refinery::I18n.default_frontend_locale || ::I18n.locale) { slug } end |
#content_for(part_title) ⇒ Object
403 404 405 |
# File 'app/models/refinery/page.rb', line 403 def content_for(part_title) part_with_title(part_title).try(:body) end |
#custom_slug_or_title ⇒ Object
Returns in cascading order: custom_slug or menu_title or title depending on which attribute is first found to be present for this page.
213 214 215 |
# File 'app/models/refinery/page.rb', line 213 def custom_slug_or_title custom_slug.presence || .presence || title 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
220 221 222 |
# File 'app/models/refinery/page.rb', line 220 def deletable? deletable && link_url.blank? and .blank? end |
#destroy ⇒ Object
Before destroying a page we check to see if it’s a deletable page or not Refinery system pages are not deletable.
234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'app/models/refinery/page.rb', line 234 def destroy return super if deletable? unless Rails.env.test? # give useful feedback when trying to delete from console puts "This page is not deletable. Please use .destroy! if you really want it deleted " puts "unset .link_url," if link_url.present? puts "unset .menu_match," if .present? puts "set .deletable to true" unless deletable end 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.
249 250 251 252 253 254 255 |
# File 'app/models/refinery/page.rb', line 249 def destroy! self. = nil self.link_url = nil self.deletable = true destroy end |
#home? ⇒ Boolean
Returns true if this page is the home page or links to it.
371 372 373 |
# File 'app/models/refinery/page.rb', line 371 def home? link_url == '/' 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.
362 363 364 |
# File 'app/models/refinery/page.rb', line 362 def live? && end |
#link_url_localised? ⇒ Boolean
Adds the locale key into the URI for this page’s link_url attribute, unless the current locale is set as the default locale.
291 292 293 294 295 296 297 298 299 300 301 |
# File 'app/models/refinery/page.rb', line 291 def link_url_localised? return link_url unless ::Refinery.i18n_enabled? current_url = link_url if current_url =~ %r{^/} && ::Refinery::I18n.current_frontend_locale != ::Refinery::I18n.default_frontend_locale current_url = "/#{::Refinery::I18n.current_frontend_locale}#{current_url}" end current_url end |
#live? ⇒ Boolean
Returns true if this page is “published”
356 357 358 |
# File 'app/models/refinery/page.rb', line 356 def live? not draft? end |
#nested_path ⇒ Object
Returns the string version of nested_url, i.e., the path that should be generated by the router
339 340 341 |
# File 'app/models/refinery/page.rb', line 339 def nested_path Rails.cache.fetch(path_cache_key) { ['', nested_url].join('/') } end |
#normalize_friendly_id_with_marketable_urls(slug_string) ⇒ Object
Protects generated slugs from title if they are in the list of reserved words This applies mostly to plugin-generated pages. This only kicks in when Refinery::Pages.marketable_urls is enabled.
Returns the sluggified string
434 435 436 437 438 439 440 |
# File 'app/models/refinery/page.rb', line 434 def normalize_friendly_id_with_marketable_urls(slug_string) sluggified = slug_string.to_slug.normalize! if Refinery::Pages.marketable_urls && self.class.friendly_id_config.reserved_words.include?(sluggified) sluggified << "-page" end sluggified end |
#not_in_menu? ⇒ Boolean
366 367 368 |
# File 'app/models/refinery/page.rb', line 366 def not end |
#part_with_title(part_title) ⇒ Object
413 414 415 416 417 418 419 420 421 |
# File 'app/models/refinery/page.rb', line 413 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
259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'app/models/refinery/page.rb', line 259 def path( = {}) # Override default options with any supplied. = {:reversed => true}.merge() unless parent_id.nil? parts = [title, parent.path()] parts.reverse! if [:reversed] parts.join(PATH_SEPARATOR) else title end end |
#path_cache_key(locale = Globalize.locale) ⇒ Object
343 344 345 |
# File 'app/models/refinery/page.rb', line 343 def path_cache_key(locale = Globalize.locale) [cache_key(locale), 'nested_path'].join('#') end |
#refinery_menu_title ⇒ Object
380 381 382 |
# File 'app/models/refinery/page.rb', line 380 def [, page_title, , title].detect(&:present?) 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.
226 227 228 229 230 |
# File 'app/models/refinery/page.rb', line 226 def reposition_parts! reload.parts.each_with_index do |part, index| part.update_attributes :position => index end end |
#shown_siblings ⇒ Object
Returns all visible sibling pages that can be rendered for the menu
376 377 378 |
# File 'app/models/refinery/page.rb', line 376 def shown_siblings siblings.reject(&:not_in_menu?) end |
#to_refinery_menu_item ⇒ Object
384 385 386 387 388 389 390 391 392 393 394 395 |
# File 'app/models/refinery/page.rb', line 384 def { :id => id, :lft => lft, :menu_match => , :parent_id => parent_id, :rgt => rgt, :title => , :type => self.class.name, :url => url } end |
#uncached_nested_url ⇒ Object Also known as: nested_url
325 326 327 |
# File 'app/models/refinery/page.rb', line 325 def uncached_nested_url [parent.try(:uncached_nested_url), to_param.to_s].compact.flatten end |
#url ⇒ Object
When this page is rendered in the navigation, where should it link? If a custom “link_url” is set, it uses that otherwise it defaults to a normal page URL. The “link_url” is often used to link to a plugin rather than a page.
For example if I had a “Contact” page I don’t want it to just render a contact us page I want it to show the Inquiries form so I can collect inquiries. So I would set the “link_url” to “/contact”
279 280 281 282 283 284 285 286 287 |
# File 'app/models/refinery/page.rb', line 279 def url if link_url.present? link_url_localised? elsif Refinery::Pages.marketable_urls with_locale_param url_marketable elsif to_param.present? with_locale_param url_normal end end |
#url_cache_key(locale = Globalize.locale) ⇒ Object
347 348 349 |
# File 'app/models/refinery/page.rb', line 347 def url_cache_key(locale = Globalize.locale) [cache_key(locale), 'nested_url'].join('#') end |
#url_marketable ⇒ Object
Add ‘marketable url’ attributes into this page’s url. This sets ‘path’ as the nested_url value and sets ‘id’ to nil. For example, this might evaluate to /about for the “About” page.
306 307 308 309 |
# File 'app/models/refinery/page.rb', line 306 def url_marketable # :id => nil is important to prevent any other params[:id] from interfering with this route. url_normal.merge :path => nested_url, :id => nil end |
#url_normal ⇒ Object
Returns a url suitable to be used in url_for in Rails (such as link_to). For example, this might evaluate to /pages/about for the “About” page.
313 314 315 |
# File 'app/models/refinery/page.rb', line 313 def url_normal {:controller => '/refinery/pages', :action => 'show', :path => nil, :id => to_param, :only_path => true} end |
#with_locale_param(url_hash, locale = nil) ⇒ Object
If the current locale is set to something other than the default locale then the :locale attribute will be set on the url hash, otherwise it won’t be.
319 320 321 322 323 |
# File 'app/models/refinery/page.rb', line 319 def with_locale_param(url_hash, locale = nil) locale ||= ::Refinery::I18n.current_frontend_locale if self.class.different_frontend_locale? url_hash.update :locale => locale if locale url_hash end |