now it's possible to import cms fixtures into database
Oleg
committed Nov 08, 2010
commit 494cb98fd1a2012751ed0e8406230b97118ace9e
Showing 9
changed files with
301 additions
and 7 deletions
app/models/cms_page.rb
+19
-1
| @@ | @@ -15,7 +15,8 @@ class CmsPage < ActiveRecord::Base |
| accepts_nested_attributes_for :cms_blocks | |
| # -- Callbacks ------------------------------------------------------------ | |
| - | before_validation :assign_full_path |
| + | before_validation :assign_parent, |
| + | :assign_full_path |
| after_save :sync_child_pages | |
| # -- Validations ---------------------------------------------------------- | |
| @@ | @@ -78,6 +79,19 @@ class CmsPage < ActiveRecord::Base |
| end | |
| # -- Instance Methods ----------------------------------------------------- | |
| + | # Transforms existing cms_block information into a hash that can be used |
| + | # during form processing. That's the only way to modify cms_blocks. |
| + | def cms_blocks_attributes |
| + | self.cms_blocks.inject([]) do |arr, block| |
| + | block_attr = {} |
| + | block_attr[:type] = block.class.name |
| + | block_attr[:label] = block.label |
| + | block_attr[:content] = block.content |
| + | block_attr[:id] = block.id |
| + | arr << block_attr |
| + | end |
| + | end |
| + | |
| # Processing content will return rendered content and will populate | |
| # self.cms_tags with instances of CmsTag | |
| def content | |
| @@ | @@ -93,6 +107,10 @@ class CmsPage < ActiveRecord::Base |
| protected | |
| + | def assign_parent |
| + | self.parent ||= CmsPage.root unless self == CmsPage.root || CmsPage.count == 0 |
| + | end |
| + | |
| def assign_full_path | |
| self.full_path = self.parent ? "#{self.parent.full_path}/#{self.slug}".squeeze('/') : '/' | |
| end | |
app/models/cms_snippet.rb
+21
-5
| @@ | @@ -19,11 +19,7 @@ class CmsSnippet < ActiveRecord::Base |
| end | |
| def self.initialize_or_find(cms_page, slug) | |
| - | if ComfortableMexicanSofa.configuration.seed_data_path |
| - | CmsTag::Snippet.load_from_file(cms_page.cms_site, slug) |
| - | else |
| - | find_by_slug(slug) |
| - | end || new(:slug => slug) |
| + | load_for_slug(cms_page.cms_site, slug) || new(:slug => slug) |
| end | |
| # Attempting to initialize snippet object from yaml file that is found in config.seed_data_path | |
| @@ | @@ -35,4 +31,24 @@ class CmsSnippet < ActiveRecord::Base |
| new(attributes) | |
| end | |
| + | # Wrapper around load_from_file and find_by_slug |
| + | # returns layout object if loaded / found |
| + | def self.load_for_slug!(site, slug) |
| + | if ComfortableMexicanSofa.configuration.seed_data_path |
| + | load_from_file(site, slug) |
| + | else |
| + | # FIX: This a bit odd... Snippet is used as a tag, so sometimes there's no site scope |
| + | # being passed. So we're enforcing this only if it's found. Need to review. |
| + | conditions = site ? {:conditions => {:cms_site_id => site.id}} : {} |
| + | find_by_slug(slug, conditions) |
| + | end || raise(ActiveRecord::RecordNotFound, "CmsSnippet with slug: #{slug} cannot be found") |
| + | end |
| + | |
| + | # Non-blowing-up version of the method above |
| + | def self.load_for_slug(site, slug) |
| + | load_for_slug!(site, slug) |
| + | rescue ActiveRecord::RecordNotFound |
| + | nil |
| + | end |
| + | |
| end | |
tasks/comfortable_mexican_sofa.rake b/lib/tasks/comfortable_mexican_sofa.rake
+157
-0
| @@ | @@ -0,0 +1,157 @@ |
| + | namespace :comfortable_mexican_sofa do |
| + | |
| + | namespace :import do |
| + | |
| + | task :check_for_requirements => :environment do |task, args| |
| + | if !(@seed_path = ComfortableMexicanSofa.config.seed_data_path) |
| + | abort('ComfortableMexicanSofa.config.seed_data_path is not set. Where are those yaml files?') |
| + | end |
| + | if !(@site = CmsSite.find_by_hostname(args[:hostname])) |
| + | abort("Can't find site with HOSTNAME '#{args[:site]}'") |
| + | end |
| + | puts "Starting import into #{@site.label} (#{@site.hostname})..." |
| + | end |
| + | |
| + | desc 'Import layouts into database' |
| + | task :layouts => [:environment, :check_for_requirements] do |task, args| |
| + | puts 'Importing Layouts...' |
| + | layouts = Dir.glob(File.expand_path("#{@site.hostname}/layouts/**/*.yml", @seed_path)).collect do |layout_file_path| |
| + | attributes = YAML.load_file(layout_file_path).symbolize_keys! |
| + | @site.cms_layouts.load_for_slug!(@site, attributes[:slug]) |
| + | end |
| + | |
| + | CmsPage.connection.transaction do |
| + | # Fixtures are not ordered in any particular way. Saving order matters, |
| + | # so we cycle them until there nothing left to save |
| + | while layouts.present? |
| + | layout = layouts.shift |
| + | if !layout.parent || layout.parent && parent = @site.cms_layouts.find_by_slug(layout.parent.slug) |
| + | layout.parent = (parent rescue nil) |
| + | should_write = true |
| + | existing_layout = nil |
| + | |
| + | if existing_layout = @site.cms_layouts.find_by_slug(layout.slug) |
| + | print "Found layout in database with slug: #{layout.slug}. Overwrite? (yN): " |
| + | should_write = ($stdin.gets.to_s.strip.downcase == 'y') |
| + | end |
| + | if should_write |
| + | if existing_layout |
| + | existing_layout.attributes = layout.attributes.slice('label', 'content', 'css', 'js') |
| + | layout = existing_layout |
| + | end |
| + | layout.save! |
| + | puts "Saved layout: #{layout.label} (#{layout.slug})" |
| + | else |
| + | puts "Skipping layout: #{layout.label} (#{layout.slug})" |
| + | end |
| + | else |
| + | layouts.push layout |
| + | end |
| + | end |
| + | end |
| + | end |
| + | |
| + | desc 'Import pages into database' |
| + | task :pages => [:environment, :check_for_requirements] do |task, args| |
| + | puts 'Importing Pages...' |
| + | pages = Dir.glob(File.expand_path("#{@site.hostname}/pages/**/*.yml", @seed_path)).collect do |page_file_path| |
| + | attributes = YAML.load_file(page_file_path).symbolize_keys! |
| + | @site.cms_pages.load_for_full_path!(@site, attributes[:full_path]) |
| + | end |
| + | CmsPage.connection.transaction do |
| + | # Fixtures are not ordered in any particular way. Saving order matters, |
| + | # so we cycle them until there nothing left to save |
| + | while pages.present? |
| + | page = pages.shift |
| + | if !page.parent || page.parent && parent = @site.cms_pages.find_by_full_path(page.parent.full_path) |
| + | page.parent = (parent rescue nil) |
| + | page.cms_layout = @site.cms_layouts.find_by_slug(page.cms_layout.slug) |
| + | should_write = true |
| + | existing_page = nil |
| + | |
| + | if existing_page = @site.cms_pages.find_by_full_path(page.full_path) |
| + | print "Found page in database with full_path: #{page.full_path}. Overwrite? (yN): " |
| + | should_write = ($stdin.gets.to_s.strip.downcase == 'y') |
| + | end |
| + | |
| + | if should_write |
| + | if existing_page |
| + | # merging cms_blocks_attributes with the existing page |
| + | attrs = page.cms_blocks_attributes.collect do |block_attrs| |
| + | existing_block = existing_page.cms_blocks_attributes.find{|b| b[:label] == block_attrs[:label]} |
| + | block_attrs[:id] = existing_block[:id] if existing_block |
| + | block_attrs.stringify_keys |
| + | end |
| + | |
| + | existing_page.attributes = page.attributes.slice('label') |
| + | existing_page.cms_blocks_attributes = attrs |
| + | page = existing_page |
| + | end |
| + | page.save! |
| + | puts "Saved page: #{page.label} (#{page.full_path})" |
| + | else |
| + | puts "Skipping page: #{page.label} (#{page.full_path})" |
| + | end |
| + | else |
| + | pages.push page |
| + | end |
| + | end |
| + | end |
| + | end |
| + | |
| + | desc 'Import snippets into database' |
| + | task :snippets => [:environment, :check_for_requirements] do |task, args| |
| + | puts 'Importing Snippets...' |
| + | snippets = Dir.glob(File.expand_path("#{@site.hostname}/snippets/**/*.yml", @seed_path)).collect do |snippet_file_path| |
| + | attributes = YAML.load_file(snippet_file_path).symbolize_keys! |
| + | @site.cms_snippets.load_for_slug!(@site, attributes[:slug]) |
| + | end |
| + | CmsSnippet.connection.transaction do |
| + | snippets.each do |snippet| |
| + | should_write = true |
| + | existing_snippet = nil |
| + | if existing_snippet = @site.cms_snippets.find_by_slug(snippet.slug) |
| + | print "Found snippet in database with slug: #{snippet.slug}. Overwrite? (yN): " |
| + | should_write = ($stdin.gets.to_s.strip.downcase == 'y') |
| + | end |
| + | if should_write |
| + | if existing_snippet |
| + | existing_snippet.attributes = snippet.attributes.slice('label', 'content') |
| + | snippet = existing_snippet |
| + | end |
| + | snippet.save! |
| + | puts "Saved snippet: #{snippet.label} (#{snippet.slug})" |
| + | else |
| + | puts "Skipping snippet: #{snippet.label} (#{snippet.slug})" |
| + | end |
| + | end |
| + | end |
| + | end |
| + | |
| + | desc 'Import layouts, pages and snippets all in one go' |
| + | task :all => [:layouts, :pages, :snippets] |
| + | |
| + | end |
| + | |
| + | namespace :export do |
| + | |
| + | desc 'Export layouts to yaml files' |
| + | task :layouts => [:environment, :check_for_requirements] do |task, args| |
| + | |
| + | end |
| + | |
| + | desc 'Export pages to yaml files' |
| + | task :pages => [:environment, :check_for_requirements] do |task, args| |
| + | |
| + | end |
| + | |
| + | desc 'Export snippets to yaml files' |
| + | task :snippets => [:environment, :check_for_requirements] do |task, args| |
| + | |
| + | end |
| + | |
| + | desc 'Export layouts, pages and snippets all in one go' |
| + | task :all => [:layouts, :pages, :snippets] |
| + | |
| + | end |
| + | end |
| \ No newline at end of file | |
test/cms_seeds/test.host/pages/child.yml
+1
-0
| @@ | @@ -1,6 +1,7 @@ |
| label: Child Page | |
| parent: / | |
| cms_layout: default | |
| + | full_path: /child |
| slug: child | |
| cms_blocks_attributes: | |
| - | |
test/cms_seeds/test.host/pages/child/subchild.yml
+1
-0
| @@ | @@ -1,6 +1,7 @@ |
| label: Child Page | |
| parent: /child | |
| cms_layout: nested | |
| + | full_path: /child/subchild |
| slug: subchild | |
| cms_blocks_attributes: | |
| - | |
test/cms_seeds/test.host/pages/index.yml
+2
-1
| @@ | @@ -1,7 +1,8 @@ |
| label: Default Page | |
| parent: | |
| cms_layout: default | |
| - | slug: |
| + | full_path: / |
| + | slug: |
| cms_blocks_attributes: | |
| - | |
| label: content | |
test/integration/rake_tasks_test.rb
+59
-0
| @@ | @@ -0,0 +1,59 @@ |
| + | require File.dirname(__FILE__) + '/../test_helper' |
| + | |
| + | require 'rake' |
| + | require 'rake/rdoctask' |
| + | require 'rake/testtask' |
| + | |
| + | Rake.application.rake_require '../lib/tasks/comfortable_mexican_sofa' |
| + | |
| + | class RakeTasksTest < ActionDispatch::IntegrationTest |
| + | |
| + | def test_layouts_import |
| + | CmsLayout.destroy_all |
| + | ComfortableMexicanSofa.configuration.seed_data_path = File.expand_path('../cms_seeds', File.dirname(__FILE__)) |
| + | |
| + | assert_difference 'CmsLayout.count', 2 do |
| + | capture_rake_output{ |
| + | Rake.application['comfortable_mexican_sofa:import:check_for_requirements'].execute(:hostname => 'test.host') |
| + | Rake.application['comfortable_mexican_sofa:import:layouts'].execute(:hostname => 'test.host') |
| + | } |
| + | end |
| + | end |
| + | |
| + | def test_pages_import |
| + | CmsPage.destroy_all |
| + | ComfortableMexicanSofa.configuration.seed_data_path = File.expand_path('../cms_seeds', File.dirname(__FILE__)) |
| + | |
| + | assert_difference ['CmsPage.count', 'CmsBlock.count'], 3 do |
| + | capture_rake_output{ |
| + | Rake.application['comfortable_mexican_sofa:import:check_for_requirements'].execute(:hostname => 'test.host') |
| + | Rake.application['comfortable_mexican_sofa:import:pages'].execute(:hostname => 'test.host') |
| + | } |
| + | end |
| + | end |
| + | |
| + | def test_snippets_import |
| + | CmsSnippet.destroy_all |
| + | ComfortableMexicanSofa.configuration.seed_data_path = File.expand_path('../cms_seeds', File.dirname(__FILE__)) |
| + | |
| + | assert_difference 'CmsSnippet.count', 1 do |
| + | capture_rake_output{ |
| + | Rake.application['comfortable_mexican_sofa:import:check_for_requirements'].execute(:hostname => 'test.host') |
| + | Rake.application['comfortable_mexican_sofa:import:snippets'].execute(:hostname => 'test.host') |
| + | } |
| + | end |
| + | end |
| + | |
| + | protected |
| + | |
| + | def capture_rake_output |
| + | s = StringIO.new |
| + | oldstdout = $stdout |
| + | $stdout = s |
| + | yield |
| + | s.string |
| + | ensure |
| + | $stdout = oldstdout |
| + | end |
| + | |
| + | end |
| \ No newline at end of file | |
test/unit/cms_page_test.rb
+16
-0
| @@ | @@ -15,6 +15,13 @@ class CmsPageTest < ActiveSupport::TestCase |
| assert_has_errors_on page, [:cms_layout, :slug, :label] | |
| end | |
| + | def test_validation_of_parent_presence |
| + | page = cms_sites(:default).cms_pages.new(new_params) |
| + | assert !page.parent |
| + | assert page.valid?, page.errors.full_messages |
| + | assert_equal cms_pages(:default), page.parent |
| + | end |
| + | |
| def test_validation_of_parent_relationship | |
| page = cms_pages(:default) | |
| assert !page.parent | |
| @@ | @@ -174,6 +181,15 @@ class CmsPageTest < ActiveSupport::TestCase |
| assert !CmsPage.load_for_full_path(cms_sites(:default), '/invalid_page') | |
| end | |
| + | def test_cms_blocks_attributes_accessor |
| + | page = cms_pages(:default) |
| + | assert_equal page.cms_blocks.count, page.cms_blocks_attributes.size |
| + | assert_equal 'CmsTag::FieldText', page.cms_blocks_attributes.first[:type] |
| + | assert_equal 'default_field_text', page.cms_blocks_attributes.first[:label] |
| + | assert_equal 'default_field_text_content', page.cms_blocks_attributes.first[:content] |
| + | assert page.cms_blocks_attributes.first[:id] |
| + | end |
| + | |
| protected | |
| def new_params(options = {}) | |
test/unit/cms_snippet_test.rb
+25
-0
| @@ | @@ -32,4 +32,29 @@ class CmsSnippetTest < ActiveSupport::TestCase |
| assert_equal 'Content for Default Snippet', snippet.content | |
| end | |
| + | def test_load_for_slug |
| + | assert snippet = CmsSnippet.load_for_slug!(cms_sites(:default), 'default') |
| + | assert !snippet.new_record? |
| + | db_content = snippet.content |
| + | |
| + | ComfortableMexicanSofa.configuration.seed_data_path = File.expand_path('../cms_seeds', File.dirname(__FILE__)) |
| + | assert snippet = CmsSnippet.load_for_slug!(cms_sites(:default), 'default') |
| + | assert snippet.new_record? |
| + | file_content = snippet.content |
| + | assert_not_equal db_content, file_content |
| + | end |
| + | |
| + | def test_load_for_slug_exceptions |
| + | assert_exception_raised ActiveRecord::RecordNotFound, 'CmsSnippet with slug: not_found cannot be found' do |
| + | CmsSnippet.load_for_slug!(cms_sites(:default), 'not_found') |
| + | end |
| + | assert !CmsSnippet.load_for_slug(cms_sites(:default), 'not_found') |
| + | |
| + | ComfortableMexicanSofa.configuration.seed_data_path = File.expand_path('../cms_seeds', File.dirname(__FILE__)) |
| + | assert_exception_raised ActiveRecord::RecordNotFound, 'CmsSnippet with slug: not_found cannot be found' do |
| + | CmsSnippet.load_for_slug!(cms_sites(:default), 'not_found') |
| + | end |
| + | assert !CmsSnippet.load_for_slug(cms_sites(:default), 'not_found') |
| + | end |
| + | |
| end | |