class Cms::Layout < ActiveRecord::Base ComfortableMexicanSofa.establish_connection(self) self.table_name = 'cms_layouts' cms_acts_as_tree cms_is_mirrored cms_has_revisions_for :content, :css, :js attr_accessible :label, :identifier, :content, :css, :js, :parent, :parent_id, :app_layout # -- Relationships -------------------------------------------------------- belongs_to :site has_many :pages, :dependent => :nullify # -- Callbacks ------------------------------------------------------------ before_validation :assign_label before_create :assign_position after_save :clear_cached_page_content after_destroy :clear_cached_page_content # -- Validations ---------------------------------------------------------- validates :site_id, :presence => true validates :label, :presence => true validates :identifier, :presence => true, :uniqueness => { :scope => :site_id }, :format => { :with => /^\w[a-z0-9_-]*$/i } # -- Scopes --------------------------------------------------------------- default_scope order('cms_layouts.position') # -- Class Methods -------------------------------------------------------- # Tree-like structure for layouts def self.options_for_select(site, layout = nil, current_layout = nil, depth = 0, spacer = '. . ') out = [] [current_layout || site.layouts.roots].flatten.each do |l| next if layout == l out << [ "#{spacer*depth}#{l.label}", l.id ] l.children.each do |child| out += options_for_select(site, layout, child, depth + 1, spacer) end end return out.compact end # List of available application layouts def self.app_layouts_for_select Dir.glob(File.expand_path('app/views/layouts/**/*.html.*', Rails.root)).collect do |filename| filename.gsub!("#{File.expand_path('app/views/layouts', Rails.root)}/", '') filename.split('/').last[0...1] == '_' ? nil : filename.split('.').first end.compact.sort end # -- Instance Methods ----------------------------------------------------- # magical merging tag is {cms:page:content} If parent layout has this tag # defined its content will be merged. If no such tag found, parent content # is ignored. def merged_content if parent regex = /\{\{\s*cms:page:content:?(?:(?::text)|(?::rich_text))?\s*\}\}/ if parent.merged_content.match(regex) parent.merged_content.gsub(regex, content.to_s) else content.to_s end else content.to_s end end protected def assign_label self.label = self.label.blank?? self.identifier.try(:titleize) : self.label end def assign_position return if self.position.to_i > 0 max = self.site.layouts.where(:parent_id => self.parent_id).maximum(:position) self.position = max ? max + 1 : 0 end # Forcing page content reload def clear_cached_page_content self.pages.each{ |page| page.save! } self.children.each{ |child_layout| child_layout.clear_cached_page_content } end end