add first entities and repository business logic
arnaud sellenet
committed Jun 03, 2014
commit 54b6727fc8837a3e89be602368250c8c0a036c8b
Showing 9
changed files with
361 additions
and 4 deletions
locomotive/steam/entities/content_type.rb b/lib/locomotive/steam/entities/content_type.rb
+11
-0
| @@ | @@ -0,0 +1,11 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Entities |
| + | class ContentType |
| + | include Locomotive::Entity |
| + | ## fields ## |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/entities/page.rb b/lib/locomotive/steam/entities/page.rb
+147
-0
| @@ | @@ -0,0 +1,147 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Entities |
| + | class Page |
| + | include Locomotive::Entity |
| + | |
| + | ## fields ## |
| + | attributes :parent, :title, :slug, :fullpath, :redirect_url, :redirect_type, |
| + | :template, :handle, :listed, :searchable, :templatized, :content_type, |
| + | :published, :cache_strategy, :response_type, :position, :seo_title, |
| + | :meta_keywords, :meta_description, :editable_elements, :site |
| + | |
| + | ## aliases ## |
| + | alias :listed? :listed |
| + | alias :published? :published |
| + | alias :templatized? :templatized |
| + | alias :searchable? :searchable |
| + | |
| + | attr_accessor :templatized_from_parent |
| + | |
| + | |
| + | # Tell if the page is either the index page. |
| + | # |
| + | # @return [ Boolean ] True if index page. |
| + | # |
| + | def index? |
| + | 'index' == fullpath |
| + | end |
| + | |
| + | # Tell if the page is either the index or the 404 page. |
| + | # |
| + | # @return [ Boolean ] True if index or 404 page. |
| + | # |
| + | def index_or_404? |
| + | %w(index 404).include?(fullpath) |
| + | end |
| + | |
| + | alias :index_or_not_found? :index_or_404? |
| + | |
| + | def with_cache? |
| + | self.cache_strategy != 'none' |
| + | end |
| + | |
| + | def default_response_type? |
| + | self.response_type == 'text/html' |
| + | end |
| + | |
| + | # Is it a redirect page ? |
| + | # |
| + | # @return [ Boolean ] True if the redirect_url property is set |
| + | # |
| + | def redirect? |
| + | !self.redirect_url.blank? |
| + | end |
| + | |
| + | # Depth of the page in the site tree. |
| + | # Both the index and 404 pages are 0-depth. |
| + | # |
| + | # @return [ Integer ] The depth |
| + | # |
| + | def depth |
| + | return 0 if %w(index 404).include?(self.fullpath) |
| + | fullpath.split('/').size |
| + | end |
| + | |
| + | def unpublished? |
| + | !self.published? |
| + | end |
| + | |
| + | # Modified setter in order to set correctly the slug |
| + | # |
| + | # @param [ String ] fullpath The fullpath |
| + | # |
| + | def fullpath_with_setting_slug=(fullpath) |
| + | if fullpath && self.slug.nil? |
| + | self.slug = File.basename(fullpath) |
| + | end |
| + | |
| + | self.fullpath_without_setting_slug = fullpath |
| + | end |
| + | |
| + | alias_method_chain :fullpath=, :setting_slug |
| + | |
| + | # Modified setter in order to set inheritance fields from parent |
| + | # |
| + | # @param [ String ] fullpath The fullpath |
| + | # |
| + | def parent_with_inheritance=(parent) |
| + | self.templatized_from_parent = parent.templatized? |
| + | |
| + | # copy properties from the parent |
| + | %w(templatized content_type).each do |name| |
| + | self.send(:"#{name}=", parent.send(name.to_sym)) |
| + | end |
| + | |
| + | self.parent_without_inheritance = parent |
| + | end |
| + | alias_method_chain :parent=, :inheritance |
| + | |
| + | # Return the fullpath dasherized and with the "*" character |
| + | # for the slug of templatized page. |
| + | # |
| + | # @return [ String ] The safe full path or nil if the page is not translated in the current locale |
| + | # |
| + | def safe_fullpath |
| + | if index_or_404? |
| + | slug |
| + | else |
| + | base = parent.safe_fullpath |
| + | _slug = if templatized? && !templatized_from_parent |
| + | '*' |
| + | else |
| + | slug |
| + | end |
| + | (base == 'index' ? _slug : File.join(base, _slug)).dasherize |
| + | end |
| + | end |
| + | # Set the source of the page without any pre-rendering. Used by the API reader. |
| + | # |
| + | # @param [ String ] content The HTML raw template |
| + | # |
| + | def raw_template=(content) |
| + | @source ||= {} |
| + | @source[:en] = content |
| + | end |
| + | |
| + | # Return the Liquid template based on the raw_template property |
| + | # of the page. If the template is HAML or SLIM, then a pre-rendering to Liquid is done. |
| + | # |
| + | # @return [ String ] The liquid template or nil if not template has been provided |
| + | # |
| + | def source |
| + | @source ||= {} |
| + | |
| + | if @source[:en] |
| + | @source[:en] # memoization |
| + | elsif self.template |
| + | @source[:en] = self.template.source |
| + | else |
| + | nil |
| + | end |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/entities/site.rb b/lib/locomotive/steam/entities/site.rb
+30
-0
| @@ | @@ -0,0 +1,30 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Entities |
| + | class Site |
| + | class NullObject |
| + | def method_missing *args |
| + | nil |
| + | end |
| + | end |
| + | include Locomotive::Entity |
| + | |
| + | attributes :name, :locales, :subdomain, :domains, :seo_title, |
| + | :meta_keywords, :meta_description, :robots_txt, :timezone |
| + | ## methods ## |
| + | |
| + | def default_locale |
| + | locales.first |
| + | end |
| + | |
| + | def to_s |
| + | self.name |
| + | end |
| + | |
| + | def to_liquid |
| + | NullObject.new |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/mapper.rb b/lib/locomotive/steam/mapper.rb
+27
-4
| @@ | @@ -1,14 +1,37 @@ |
| + | Dir[File.dirname(__FILE__) + '/entities/*.rb'].each { |file| require file } |
| + | Dir[File.dirname(__FILE__) + '/repositories/*.rb'].each { |file| require file } |
| + | |
| collection :sites do | |
| - | entity Locomotive::Entities::Site |
| - | repository Locomotive::Repositories::SitesRepository |
| + | entity Locomotive::Steam::Entities::Site |
| + | repository Locomotive::Steam::Repositories::SitesRepository |
| + | |
| + | attribute :name |
| + | attribute :locales |
| + | attribute :subdomain |
| + | attribute :domains |
| + | attribute :seo_title, localized: true |
| + | attribute :meta_keywords, localized: true |
| + | attribute :meta_description, localized: true |
| + | attribute :robots_txt |
| + | attribute :timezone |
| + | |
| + | |
| end | |
| collection :pages do | |
| - | |
| + | entity Locomotive::Steam::Entities::Page |
| + | repository Locomotive::Steam::Repositories::PagesRepository |
| + | attribute :fullpath |
| + | attribute :position |
| + | attribute :site, association: :sites |
| + | attribute :content_type, association: :content_types |
| end | |
| collection :content_types do | |
| - | |
| + | entity Locomotive::Steam::Entities::ContentType |
| + | repository Locomotive::Steam::Repositories::ContentTypesRepository |
| + | attribute :slug |
| + | attribute :site, association: :sites |
| end | |
| collection :content_entries do | |
locomotive/steam/repositories/content_types_repository.rb b/lib/locomotive/steam/repositories/content_types_repository.rb
+14
-0
| @@ | @@ -0,0 +1,14 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Repositories |
| + | class ContentTypesRepository |
| + | include Repository |
| + | def [](slug) |
| + | query(:en) do |
| + | where('slug.eq' => slug.to_s) |
| + | end.first |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/repositories/pages_repository.rb b/lib/locomotive/steam/repositories/pages_repository.rb
+21
-0
| @@ | @@ -0,0 +1,21 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Repositories |
| + | class PagesRepository |
| + | include Repository |
| + | |
| + | def [](path) |
| + | matching_paths([paths]) |
| + | end |
| + | |
| + | def matching_paths(paths) |
| + | # TODO multilocales |
| + | query(:en) do |
| + | where('fullpath.in' => paths) |
| + | order_by('position ASC') |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/repositories/sites_repository.rb b/lib/locomotive/steam/repositories/sites_repository.rb
+16
-0
| @@ | @@ -0,0 +1,16 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Repositories |
| + | class SitesRepository |
| + | include Repository |
| + | |
| + | def find_by_host(host) |
| + | # TODO multilocales |
| + | query(:en) do |
| + | where('domains.in' => host) |
| + | end.first |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
spec/unit/entities/page_spec.rb
+83
-0
| @@ | @@ -0,0 +1,83 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe 'Locomotive::Steam::Entities::Page' do |
| + | |
| + | it 'builds an empty page' do |
| + | build_page.should_not be_nil |
| + | end |
| + | |
| + | describe '#index?' do |
| + | it { build_page(fullpath: 'index').should be_index } |
| + | it { build_page(fullpath: 'about').should_not be_index } |
| + | it { build_page(fullpath: 'products/index').should_not be_index } |
| + | end |
| + | |
| + | describe '#index_or_404?' do |
| + | it { build_page(fullpath: 'index').should be_index_or_404 } |
| + | it { build_page(fullpath: 'about').should_not be_index_or_404 } |
| + | it { build_page(fullpath: 'products/index').should_not be_index_or_404 } |
| + | it { build_page(fullpath: 'products/404').should_not be_index_or_404 } |
| + | it { build_page(fullpath: '404').should be_index_or_404 } |
| + | end |
| + | |
| + | describe '#depth' do |
| + | it { build_page(fullpath: 'index').depth.should eq 0 } |
| + | it { build_page(fullpath: '404').depth.should eq 0 } |
| + | it { build_page(fullpath: 'about').depth.should eq 1 } |
| + | it { build_page(fullpath: 'about/me').depth.should eq 2 } |
| + | it { build_page(fullpath: 'about/index').depth.should eq 2 } |
| + | it { build_page(fullpath: 'about/the/team').depth.should eq 3 } |
| + | end |
| + | |
| + | describe '#fullpath=' do |
| + | context 'when the page has no slug yet' do |
| + | it 'also sets the slug' do |
| + | build_page(fullpath: 'this/is/the/page_full_path').slug.should eq 'page_full_path' |
| + | end |
| + | end |
| + | |
| + | context 'when the slug is already set' do |
| + | it 'keeps the original slug' do |
| + | build_page(fullpath: 'this/is/the/page_full_path', slug: 'the_slug').slug.should eq 'the_slug' |
| + | end |
| + | end |
| + | end |
| + | |
| + | describe '#safe_fullpath' do |
| + | let(:index_page) { build_page(fullpath: 'index') } |
| + | let(:not_found_page) { build_page(fullpath: '404') } |
| + | let(:about_page) { build_page(fullpath: 'about_me', parent: index_page) } |
| + | let(:products_page) { build_page(fullpath: 'products', parent: index_page, templatized: true) } |
| + | |
| + | context 'not templatized' do |
| + | context 'index or 404' do |
| + | it { index_page.safe_fullpath.should eq 'index' } |
| + | it { not_found_page.safe_fullpath.should eq '404' } |
| + | end |
| + | |
| + | context 'other' do |
| + | it { about_page.safe_fullpath.should eq 'about-me' } |
| + | end |
| + | end |
| + | |
| + | context 'templatized' do |
| + | subject { build_page(fullpath: 'products', parent: index_page, templatized: true) } |
| + | its(:safe_fullpath) { should eq '*' } |
| + | end |
| + | |
| + | context 'templatized with not templatized parent' do |
| + | subject { build_page(fullpath: 'about_me/contact', parent: about_page, templatized: true) } |
| + | its(:safe_fullpath) { should eq 'about-me/*' } |
| + | end |
| + | |
| + | context 'templatized parent' do |
| + | subject { build_page(fullpath: 'products/detail', parent: products_page) } |
| + | its(:safe_fullpath) { should eq '*/detail' } |
| + | end |
| + | end |
| + | |
| + | def build_page(attributes = {}) |
| + | Locomotive::Steam::Entities::Page.new(attributes) |
| + | end |
| + | |
| + | end |
spec/unit/entities/site_spec.rb
+12
-0
| @@ | @@ -0,0 +1,12 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe 'Locomotive::Steam::Entities::Site' do |
| + | |
| + | describe '#default_locale' do |
| + | subject { Locomotive::Steam::Entities::Site.new attributes } |
| + | let(:attributes) { { locales: [:wk, :fr, :es] } } |
| + | it 'uses the first locale as default locale' do |
| + | expect(subject.default_locale).to eq :wk |
| + | end |
| + | end |
| + | end |