diff options
-rw-r--r-- | app/models/wiki_page.rb | 29 | ||||
-rw-r--r-- | spec/models/wiki_page_spec.rb | 30 |
2 files changed, 54 insertions, 5 deletions
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index a563b0b7a72..a84f84c67cd 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -12,10 +12,17 @@ class WikiPage ActiveModel::Name.new(self, nil, 'wiki') end + # Sorts and groups pages by directory. + # + # pages - an array of WikiPage objects. + # + # Returns a hash whose keys are directories and whose values are WikiPage + # arrays. See WikiPage.sort_by_directory for more info about the ordering. def self.group_by_directory(pages) return {} if pages.blank? - directories = { '/' => [] } + pages = sort_by_directory(pages) + directories = {} pages.each do |page| directories[page.directory] ||= [] directories[page.directory] << page @@ -199,6 +206,26 @@ class WikiPage private + # Sorts an array of pages by directory and file alphabetical order. + # Pages at the root directory will come first. The next pages will be + # sorted by their directories. Within directories, pages are sorted by + # filename alphabetical order. Pages are sorted in such a fashion that + # nested directories will always follow their parents (e.g. pages in + # dir_1/nested_dir_1 will follow pages inside dir_1). + # + # pages - an array of WikiPage objects. + # + # Returns a sorted array of WikiPage objects. + def self.sort_by_directory(pages) + pages.sort do |page, next_page| + if page.directory == next_page.directory + page.slug <=> next_page.slug + else + page.directory <=> next_page.directory + end + end + end + def set_attributes attributes[:slug] = @page.url_path attributes[:title] = @page.title diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index 91d5fccce60..374849e1932 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -17,17 +17,22 @@ describe WikiPage, models: true do context 'when there are pages' do before do - create_page('page_1', 'content') + create_page('dir_1/dir_1_1/page_3', 'content') create_page('dir_1/page_2', 'content') - create_page('dir_1/dir_2/page_3', 'content') + create_page('dir_2/page_5', 'content') + create_page('dir_2/page_4', 'content') + create_page('page_1', 'content') end it 'returns a hash in which keys are directories and values are their pages' do page_1 = wiki.find_page('page_1') page_2 = wiki.find_page('dir_1/page_2') - page_3 = wiki.find_page('dir_1/dir_2/page_3') + page_3 = wiki.find_page('dir_1/dir_1_1/page_3') + page_4 = wiki.find_page('dir_2/page_4') + page_5 = wiki.find_page('dir_2/page_5') expected_grouped_pages = { - '/' => [page_1], '/dir_1' => [page_2], '/dir_1/dir_2' => [page_3] + '/' => [page_1], '/dir_1' => [page_2], '/dir_1/dir_1_1' => [page_3], + '/dir_2' => [page_4, page_5] } grouped_pages = WikiPage.group_by_directory(wiki.pages) @@ -39,6 +44,23 @@ describe WikiPage, models: true do expect(slugs).to match_array(expected_slugs) end end + + it 'returns a hash in which keys (directories) are sorted by alphabetical position' do + expected_ordered_directories = ['/', '/dir_1', '/dir_1/dir_1_1', '/dir_2'] + + grouped_pages = WikiPage.group_by_directory(wiki.pages) + + expect(grouped_pages.keys).to eq(expected_ordered_directories) + end + + it 'returns a hash in which values (pages) are sorted by alphabetical position' do + expected_ordered_page_slugs = ['dir_2/page_4', 'dir_2/page_5'] + + grouped_pages = WikiPage.group_by_directory(wiki.pages) + + dir_2_page_slugs = grouped_pages.fetch('/dir_2').map(&:slug) + expect(dir_2_page_slugs).to eq(expected_ordered_page_slugs) + end end end |