intermediate commit: very simple MongoDB adapter, refactor each repository one by one. Tests are broken
did
committed Feb 21, 2015
commit 66ab7acb016c6b472294346876584192ae376585
Showing 38
changed files with
1529 additions
and 605 deletions
Gemfile.lock
+10
-0
| @@ | @@ -50,6 +50,7 @@ GEM |
| thread_safe (~> 0.3, >= 0.3.4) | |
| tzinfo (~> 1.1) | |
| addressable (2.3.7) | |
| + | bson (2.3.0) |
| builder (3.2.2) | |
| byebug (3.5.1) | |
| columnize (~> 0.8) | |
| @@ | @@ -78,6 +79,7 @@ GEM |
| sass (>= 3.3.0, < 3.5) | |
| compass-import-once (1.0.5) | |
| sass (>= 3.2, < 3.5) | |
| + | connection_pool (2.1.1) |
| coveralls (0.7.3) | |
| multi_json (~> 1.10) | |
| rest-client (~> 1.7) | |
| @@ | @@ -129,6 +131,10 @@ GEM |
| mini_portile (0.6.2) | |
| minitest (5.5.1) | |
| moneta (0.8.0) | |
| + | moped (2.0.4) |
| + | bson (~> 2.2) |
| + | connection_pool (~> 2.0) |
| + | optionable (~> 0.2.0) |
| morphine (0.1.1) | |
| multi_json (1.10.1) | |
| multi_xml (0.5.5) | |
| @@ | @@ -137,6 +143,8 @@ GEM |
| mini_portile (~> 0.6.0) | |
| nokogumbo (1.2.0) | |
| nokogiri | |
| + | optionable (0.2.0) |
| + | origin (1.0.11) |
| pry (0.10.1) | |
| coderay (~> 1.1.0) | |
| method_source (~> 0.8.1) | |
| @@ | @@ -223,6 +231,8 @@ DEPENDENCIES |
| i18n-spec (~> 0.6.0) | |
| json_spec (~> 1.1.4) | |
| locomotivecms_steam! | |
| + | moped (~> 2.0.4) |
| + | origin (~> 1.0.4) |
| pry-byebug | |
| rake (~> 10.4.2) | |
| rspec (~> 3.1.0) | |
Rakefile
+0
-4
| @@ | @@ -24,8 +24,4 @@ RSpec::Core::RakeTask.new('spec:unit') do |spec| |
| spec.pattern = 'spec/unit/**/*_spec.rb' | |
| end | |
| - | RSpec::Core::RakeTask.new('spec:adapters') do |spec| |
| - | spec.pattern = 'spec/unit/adapters/**/*_spec.rb' |
| - | end |
| - | |
| task default: :spec | |
locomotive/steam.rb b/lib/locomotive/steam.rb
+7
-3
| @@ | @@ -11,9 +11,13 @@ require_relative_all 'steam/monkey_patches' |
| require_relative_all 'steam/decorators' | |
| require_relative 'steam/liquid' | |
| - | require_relative 'steam/entities' |
| - | require_relative 'steam/mapper' |
| - | require_relative 'steam/repositories' |
| + | require_relative 'steam/models' |
| + | require_relative_all 'steam/entities' |
| + | |
| + | # TODO |
| + | require_relative 'steam/repositories/site_repository' |
| + | require_relative 'steam/repositories/page_repository' |
| + | |
| require_relative 'steam/services' | |
| module Locomotive | |
locomotive/steam/adapters/filesystem.rb b/lib/locomotive/steam/adapters/filesystem.rb
+11
-3
| @@ | @@ -1,4 +1,3 @@ |
| - | # require_relative_all 'yaml_loaders' |
| require_relative 'filesystem/dataset' | |
| require_relative 'filesystem/condition' | |
| require_relative 'filesystem/query' | |
| @@ | @@ -7,6 +6,7 @@ require_relative 'filesystem/simple_cache_store' |
| require_relative 'filesystem/yaml_loader' | |
| require_relative 'filesystem/yaml_loaders/site' | |
| + | require_relative 'filesystem/yaml_loaders/page' |
| module Locomotive::Steam | |
| @@ | @@ -27,12 +27,20 @@ module Locomotive::Steam |
| memoized_dataset(mapper) | |
| end | |
| - | def query(mapper, locale, &block) |
| - | Locomotive::Steam::Adapters::Filesystem::Query.new(all(mapper), locale, &block) |
| + | def query(mapper, scope, &block) |
| + | _query(mapper, scope.locale, &block).tap do |default| |
| + | if scope.site |
| + | default + _query(mapper) { where(site_id: scope.site.id) } |
| + | end |
| + | end |
| end | |
| private | |
| + | def _query(mapper, locale = nil, &block) |
| + | Locomotive::Steam::Adapters::Filesystem::Query.new(all(mapper), locale, &block) |
| + | end |
| + | |
| def memoized_dataset(mapper) | |
| return @datasets[mapper.name] if @datasets[mapper.name] | |
| dataset(mapper) | |
locomotive/steam/adapters/filesystem/condition.rb b/lib/locomotive/steam/adapters/filesystem/condition.rb
+74
-71
| @@ | @@ -1,100 +1,103 @@ |
| - | module Locomotive |
| - | module Steam |
| - | module Adapters |
| - | module Filesystem |
| + | module Locomotive::Steam |
| + | module Adapters |
| + | module Filesystem |
| - | class Condition |
| + | class Condition |
| - | class UnsupportedOperator < StandardError; end |
| + | class UnsupportedOperator < StandardError; end |
| - | OPERATORS = %i(== eq ne neq matches gt gte lt lte size all in nin).freeze |
| + | OPERATORS = %i(== eq ne neq matches gt gte lt lte size all in nin).freeze |
| - | attr_reader :field, :operator, :value |
| + | attr_reader :field, :operator, :value |
| - | def initialize(operator_and_field, value, locale) |
| - | @locale = locale.try(:to_sym) |
| - | @operator_and_field, @value = operator_and_field, value |
| - | @operator, @field = :==, operator_and_field |
| + | def initialize(operator_and_field, value, locale) |
| + | @locale = locale.try(:to_sym) |
| + | @operator_and_field, @value = operator_and_field, value |
| + | @operator, @field = :==, operator_and_field |
| - | decode_operator_and_field! |
| - | end |
| + | decode_operator_and_field! |
| + | end |
| - | def matches?(entry) |
| - | entry_value = entry_value(entry) |
| - | |
| - | adapt_operator!(entry_value) |
| - | case @operator |
| - | when :== then entry_value == @value |
| - | when :eq then entry_value == @value |
| - | when :ne then entry_value != @value |
| - | when :neq then entry_value != @value |
| - | when :matches then @value =~ entry_value |
| - | when :gt then entry_value > @value |
| - | when :gte then entry_value >= @value |
| - | when :lt then entry_value < @value |
| - | when :lte then entry_value <= @value |
| - | when :size then entry_value.size == @value |
| - | when :all then array_contains?([*@value], entry_value) |
| - | when :in, :nin then value_is_in_entry_value?(entry_value) |
| - | else |
| - | raise UnknownConditionInScope.new("#{@operator} is unknown or not implemented.") |
| - | end |
| + | def matches?(entry) |
| + | entry_value = entry_value(entry) |
| + | |
| + | adapt_operator!(entry_value) |
| + | case @operator |
| + | when :== then entry_value == @value |
| + | when :eq then entry_value == @value |
| + | when :ne then entry_value != @value |
| + | when :neq then entry_value != @value |
| + | when :matches then @value =~ entry_value |
| + | when :gt then entry_value > @value |
| + | when :gte then entry_value >= @value |
| + | when :lt then entry_value < @value |
| + | when :lte then entry_value <= @value |
| + | when :size then entry_value.size == @value |
| + | when :all then array_contains?([*@value], entry_value) |
| + | when :in, :nin then value_is_in_entry_value?(entry_value) |
| + | else |
| + | raise UnknownConditionInScope.new("#{@operator} is unknown or not implemented.") |
| end | |
| + | end |
| - | def to_s |
| - | "#{field} #{operator} #{@value.to_s}" |
| - | end |
| + | def to_s |
| + | "#{field} #{operator} #{@value.to_s}" |
| + | end |
| - | protected |
| + | protected |
| - | def entry_value(entry) |
| - | case (value = entry.send(@field)) |
| - | when Hash |
| - | value.fetch(@locale) { nil } |
| - | else |
| - | value |
| - | end |
| - | end |
| + | def entry_value(entry) |
| + | value = entry.send(@field) |
| - | def decode_operator_and_field! |
| - | if match = @operator_and_field.match(/^(?<field>[a-z0-9_-]+)\.(?<operator>.*)$/) |
| - | @field = match[:field].to_sym |
| - | @operator = match[:operator].to_sym |
| - | check_operator! |
| - | end |
| + | if value.respond_to?(:translations) |
| + | value[@locale] |
| + | else |
| + | value |
| + | end |
| + | end |
| - | @operator = :matches if @value.is_a?(Regexp) |
| + | def decode_operator_and_field! |
| + | if match = @operator_and_field.match(/^(?<field>[a-z0-9_-]+)\.(?<operator>.*)$/) |
| + | @field = match[:field].to_sym |
| + | @operator = match[:operator].to_sym |
| + | check_operator! |
| end | |
| - | def adapt_operator!(value) |
| - | case value |
| - | when Array |
| - | @operator = :in if @operator == :== |
| - | end |
| + | @operator = :matches if @value.is_a?(Regexp) |
| + | end |
| + | |
| + | def adapt_operator!(value) |
| + | case value |
| + | when Array |
| + | @operator = :in if @operator == :== |
| end | |
| + | end |
| - | def value_is_in_entry_value?(value) |
| - | _matches = if value.is_a?(Array) |
| - | array_contains?([*value], [*@value]) |
| - | else |
| - | [*@value].include?(value) |
| - | end |
| - | @operator == :in ? _matches : !_matches |
| + | def value_is_in_entry_value?(value) |
| + | _matches = if value.is_a?(Array) |
| + | array_contains?([*value], [*@value]) |
| + | else |
| + | [*@value].include?(value) |
| end | |
| + | @operator == :in ? _matches : !_matches |
| + | end |
| - | private |
| + | private |
| - | def check_operator! |
| - | raise UnsupportedOperator.new unless OPERATORS.include?(@operator) |
| - | end |
| + | def check_operator! |
| + | raise UnsupportedOperator.new unless OPERATORS.include?(@operator) |
| + | end |
| - | def array_contains?(source, target) |
| + | def array_contains?(source, target) |
| + | if target.size == 0 |
| + | source.size == 0 |
| + | else |
| source & target == target | |
| end | |
| - | |
| end | |
| end | |
| + | |
| end | |
| end | |
| end | |
locomotive/steam/adapters/filesystem/dataset.rb b/lib/locomotive/steam/adapters/filesystem/dataset.rb
+53
-55
| @@ | @@ -1,75 +1,73 @@ |
| - | module Locomotive |
| - | module Steam |
| - | module Adapters |
| - | module Filesystem |
| - | |
| - | class Dataset |
| - | |
| - | class PrimaryKey |
| - | def initialize |
| - | @current = 0 |
| - | end |
| - | |
| - | def increment! |
| - | yield(@current += 1) |
| - | @current |
| - | end |
| - | end |
| + | module Locomotive::Steam |
| + | module Adapters |
| + | module Filesystem |
| - | attr_reader :records, :name |
| + | class Dataset |
| - | def initialize(name) |
| - | @name = name |
| - | clear! |
| + | class PrimaryKey |
| + | def initialize |
| + | @current = 0 |
| end | |
| - | def insert(record) |
| - | @primary_key.increment! do |id| |
| - | record[identity] = id |
| - | records[id] = record |
| - | end |
| + | def increment! |
| + | yield(@current += 1) |
| + | @current |
| end | |
| + | end |
| - | def update(record) |
| - | records[record[identity]] = records[record[identity]].deep_merge(record) |
| - | end |
| + | attr_reader :records, :name |
| - | def delete(id) |
| - | records.delete(id) |
| - | end |
| + | def initialize(name) |
| + | @name = name |
| + | clear! |
| + | end |
| - | def size |
| - | records.size |
| + | def insert(record) |
| + | @primary_key.increment! do |id| |
| + | record[identity] = id |
| + | records[id] = record |
| end | |
| + | end |
| - | def all |
| - | records.values |
| - | end |
| + | def update(record) |
| + | records[record[identity]] = records[record[identity]].deep_merge(record) |
| + | end |
| - | def find(id) |
| - | records.fetch(id) do |
| - | raise Locomotive::Steam::Repository::RecordNotFound, "could not find #{name} with #{identity} = #{id}" |
| - | end |
| - | end |
| + | def delete(id) |
| + | records.delete(id) |
| + | end |
| - | def exists?(id) |
| - | !!id && records.has_key?(id) |
| - | end |
| + | def size |
| + | records.size |
| + | end |
| - | # def query |
| - | # Query.new(self) |
| - | # end |
| + | def all |
| + | records.values |
| + | end |
| - | def clear! |
| - | @records = {} |
| - | @primary_key = PrimaryKey.new |
| + | def find(id) |
| + | records.fetch(id) do |
| + | raise Locomotive::Steam::Repository::RecordNotFound, "could not find #{name} with #{identity} = #{id}" |
| end | |
| + | end |
| + | |
| + | def exists?(id) |
| + | !!id && records.has_key?(id) |
| + | end |
| - | private |
| + | # def query |
| + | # Query.new(self) |
| + | # end |
| - | def identity |
| - | @identity ||= :_id |
| - | end |
| + | def clear! |
| + | @records = {} |
| + | @primary_key = PrimaryKey.new |
| + | end |
| + | |
| + | private |
| + | |
| + | def identity |
| + | @identity ||= :_id |
| end | |
| end | |
| end | |
locomotive/steam/adapters/filesystem/query.rb b/lib/locomotive/steam/adapters/filesystem/query.rb
+77
-79
| @@ | @@ -1,110 +1,108 @@ |
| require 'forwardable' | |
| - | module Locomotive |
| - | module Steam |
| - | module Adapters |
| - | module Filesystem |
| + | module Locomotive::Steam |
| + | module Adapters |
| + | module Filesystem |
| - | class Query |
| + | class Query |
| - | include Enumerable |
| - | extend Forwardable |
| + | include Enumerable |
| + | extend Forwardable |
| - | def_delegators :all, :each, :to_s, :to_a, :empty?, :size |
| + | def_delegators :all, :each, :to_s, :to_a, :empty?, :size |
| - | alias :length :size |
| - | alias :count :size |
| + | alias :length :size |
| + | alias :count :size |
| - | attr_reader :conditions |
| + | attr_reader :conditions |
| - | def initialize(dataset, locale = nil, &block) |
| - | @dataset = dataset |
| - | @conditions = [] |
| - | @sorting = nil |
| - | @limit = nil |
| - | @offset = 0 |
| - | @locale = locale |
| - | instance_eval(&block) if block_given? |
| - | end |
| + | def initialize(dataset, locale = nil, &block) |
| + | @dataset = dataset |
| + | @conditions = [] |
| + | @sorting = nil |
| + | @limit = nil |
| + | @offset = 0 |
| + | @locale = locale |
| + | instance_eval(&block) if block_given? |
| + | end |
| - | def where(conditions = {}) |
| - | @conditions += conditions.map { |name, value| Condition.new(name, value, @locale) } |
| - | self |
| - | end |
| + | def where(conditions = {}) |
| + | @conditions += conditions.map { |name, value| Condition.new(name, value, @locale) } |
| + | self |
| + | end |
| - | def +(query) |
| - | @conditions += query.conditions |
| - | self |
| - | end |
| + | def +(query) |
| + | @conditions += query.conditions |
| + | self |
| + | end |
| - | def order_by(order_string) |
| - | unless order_string.blank? |
| - | pattern = order_string.include?('.') ? '.' : ' ' |
| - | @sorting = order_string.downcase.split(pattern).map(&:to_sym) |
| - | end |
| - | self |
| + | def order_by(order_string) |
| + | unless order_string.blank? |
| + | pattern = order_string.include?('.') ? '.' : ' ' |
| + | @sorting = order_string.downcase.split(pattern).map(&:to_sym) |
| end | |
| + | self |
| + | end |
| - | def limit(num) |
| - | @limit = num |
| - | self |
| - | end |
| + | def limit(num) |
| + | @limit = num |
| + | self |
| + | end |
| - | def offset(num) |
| - | @offset = num |
| - | self |
| - | end |
| + | def offset(num) |
| + | @offset = num |
| + | self |
| + | end |
| - | def ==(other) |
| - | if other.kind_of? Array |
| - | all == other |
| - | else |
| - | super |
| - | end |
| + | def ==(other) |
| + | if other.kind_of? Array |
| + | all == other |
| + | else |
| + | super |
| end | |
| + | end |
| - | def all |
| - | limited sorted(filtered) |
| - | end |
| + | def all |
| + | limited sorted(filtered) |
| + | end |
| - | def sorted(entries) |
| - | return entries if @sorting.nil? |
| + | def sorted(entries) |
| + | return entries if @sorting.nil? |
| - | name, direction = @sorting.first, (@sorting.last || :asc) |
| - | if direction == :asc |
| - | entries.sort { |a, b| a.send(name) <=> b.send(name) } |
| - | else |
| - | entries.sort { |a, b| b.send(name) <=> a.send(name) } |
| - | end |
| + | name, direction = @sorting.first, (@sorting.last || :asc) |
| + | if direction == :asc |
| + | entries.sort { |a, b| a.send(name) <=> b.send(name) } |
| + | else |
| + | entries.sort { |a, b| b.send(name) <=> a.send(name) } |
| end | |
| + | end |
| - | def limited(entries) |
| - | return [] if @limit == 0 |
| - | return entries if @offset == 0 && @limit.nil? |
| + | def limited(entries) |
| + | return [] if @limit == 0 |
| + | return entries if @offset == 0 && @limit.nil? |
| - | subentries = entries.drop(@offset || 0) |
| - | if @limit.kind_of? Integer |
| - | subentries.take(@limit) |
| - | else |
| - | subentries |
| - | end |
| + | subentries = entries.drop(@offset || 0) |
| + | if @limit.kind_of? Integer |
| + | subentries.take(@limit) |
| + | else |
| + | subentries |
| end | |
| + | end |
| - | def filtered |
| - | @dataset.all.dup.find_all do |entry| |
| - | accepted = true |
| + | def filtered |
| + | @dataset.all.dup.find_all do |entry| |
| + | accepted = true |
| - | @conditions.each do |_condition| |
| - | unless _condition.matches?(entry) |
| - | accepted = false |
| - | break # no to go further |
| - | end |
| + | @conditions.each do |_condition| |
| + | unless _condition.matches?(entry) |
| + | accepted = false |
| + | break # no to go further |
| end | |
| - | accepted |
| end | |
| - | end # filtered |
| + | accepted |
| + | end |
| + | end # filtered |
| - | end |
| end | |
| end | |
| end | |
locomotive/steam/adapters/filesystem/simple_cache_store.rb b/lib/locomotive/steam/adapters/filesystem/simple_cache_store.rb
+24
-26
| @@ | @@ -1,40 +1,38 @@ |
| - | module Locomotive |
| - | module Steam |
| - | module Adapters |
| - | module Filesystem |
| + | module Locomotive::Steam |
| + | module Adapters |
| + | module Filesystem |
| - | class SimpleCacheStore |
| + | class SimpleCacheStore |
| - | @@store = {} |
| + | @@store = {} |
| - | def fetch(name, options = nil, &block) |
| - | if block_given? |
| - | read(name) || write(name, yield) |
| - | else |
| - | read(name) |
| - | end |
| - | end |
| - | |
| - | def read(name, options = nil) |
| - | @@store[name] |
| + | def fetch(name, options = nil, &block) |
| + | if block_given? |
| + | read(name) || write(name, yield) |
| + | else |
| + | read(name) |
| end | |
| + | end |
| - | def write(name, value, options = nil) |
| - | @@store[name] = value |
| - | end |
| + | def read(name, options = nil) |
| + | @@store[name] |
| + | end |
| - | def clear |
| - | @@store.clear |
| - | end |
| + | def write(name, value, options = nil) |
| + | @@store[name] = value |
| + | end |
| - | #:nocov: |
| - | def _store |
| - | @@store |
| - | end |
| + | def clear |
| + | @@store.clear |
| + | end |
| + | #:nocov: |
| + | def _store |
| + | @@store |
| end | |
| end | |
| + | |
| end | |
| end | |
| end | |
locomotive/steam/adapters/filesystem/yaml_loader.rb b/lib/locomotive/steam/adapters/filesystem/yaml_loader.rb
+24
-26
| @@ | @@ -1,39 +1,37 @@ |
| - | module Locomotive |
| - | module Steam |
| - | module Adapters |
| - | module Filesystem |
| + | module Locomotive::Steam |
| + | module Adapters |
| + | module Filesystem |
| - | module YAMLLoader |
| + | module YAMLLoader |
| - | def fetch(key, &block) |
| - | cache.nil? ? yield : cache.fetch(key, &block) |
| - | end |
| + | def fetch(key, &block) |
| + | cache.nil? ? yield : cache.fetch(key, &block) |
| + | end |
| - | def _load(path, frontmatter = false, &block) |
| - | if File.exists?(path) |
| - | yaml = File.open(path).read.force_encoding('utf-8') |
| - | template = nil |
| - | |
| - | if frontmatter && match = yaml.match(FRONTMATTER_REGEXP) |
| - | yaml, template = match[:yaml], match[:template] |
| - | end |
| - | |
| - | HashConverter.to_sym(YAML.load(yaml)).tap do |attributes| |
| - | block.call(attributes, template) if block_given? |
| - | end |
| - | else |
| - | Locomotive::Common::Logger.error "No #{path} file found" |
| - | {} |
| + | def _load(path, frontmatter = false, &block) |
| + | if File.exists?(path) |
| + | yaml = File.open(path).read.force_encoding('utf-8') |
| + | template = nil |
| + | |
| + | if frontmatter && match = yaml.match(FRONTMATTER_REGEXP) |
| + | yaml, template = match[:yaml], match[:template] |
| end | |
| - | end |
| - | def template_extensions |
| - | @extensions ||= %w(liquid haml) |
| + | HashConverter.to_sym(YAML.load(yaml)).tap do |attributes| |
| + | block.call(attributes, template) if block_given? |
| + | end |
| + | else |
| + | Locomotive::Common::Logger.error "No #{path} file found" |
| + | {} |
| end | |
| + | end |
| + | def template_extensions |
| + | @extensions ||= %w(liquid haml) |
| end | |
| end | |
| + | |
| end | |
| end | |
| end | |
locomotive/steam/adapters/filesystem/yaml_loaders/page.rb b/lib/locomotive/steam/adapters/filesystem/yaml_loaders/page.rb
+109
-108
| @@ | @@ -1,108 +1,109 @@ |
| - | # module Locomotive |
| - | # module Steam |
| - | # module Repositories |
| - | # module Filesystem |
| - | # module YAMLLoaders |
| - | |
| - | # class Page < Struct.new(:root_path, :default_locale, :cache) |
| - | |
| - | # include YAMLLoaders::Concerns::Common |
| - | |
| - | # def list_of_attributes |
| - | # cache.fetch('app/views/pages') { load_tree } |
| - | # end |
| - | |
| - | # private |
| - | |
| - | # def path |
| - | # @path ||= File.join(root_path, 'app', 'views', 'pages') |
| - | # end |
| - | |
| - | # def load_tree |
| - | # {}.tap do |hash| |
| - | # each_file do |filepath, relative_path, fullpath, locale| |
| - | |
| - | # if leaf = hash[fullpath] |
| - | # update(leaf, filepath, fullpath, locale) |
| - | # else |
| - | # leaf = build(filepath, fullpath, locale) |
| - | # end |
| - | |
| - | # hash[fullpath] = leaf |
| - | # end |
| - | # end.values |
| - | # end |
| - | |
| - | # def build(filepath, fullpath, locale) |
| - | # slug = fullpath.split('/').last |
| - | # attributes = get_attributes(filepath, fullpath) |
| - | |
| - | # { |
| - | # title: { locale => attributes.delete(:title) || (default_locale == locale ? slug.humanize : nil) }, |
| - | # slug: { locale => attributes.delete(:slug) || slug }, |
| - | # editable_elements: { locale => attributes.delete(:editable_elements) }, |
| - | # template_path: { locale => template_path(filepath, attributes, locale) }, |
| - | # redirect_url: { locale => attributes.delete(:redirect_url) }, |
| - | # _fullpath: fullpath |
| - | # }.merge(attributes) |
| - | # end |
| - | |
| - | # def update(leaf, filepath, fullpath, locale) |
| - | # slug = fullpath.split('/').last |
| - | # attributes = get_attributes(filepath, fullpath) |
| - | |
| - | # leaf[:title][locale] = attributes.delete(:title) || slug.humanize |
| - | # leaf[:slug][locale] = attributes.delete(:slug) || slug |
| - | # leaf[:editable_elements][locale] = attributes.delete(:editable_elements) |
| - | # leaf[:template_path][locale] = template_path(filepath, attributes, locale) |
| - | # leaf[:redirect_url][locale] = attributes.delete(:redirect_url) |
| - | |
| - | # leaf.merge!(attributes) |
| - | # end |
| - | |
| - | # def get_attributes(filepath, fullpath) |
| - | # load(filepath, true) do |attributes, template| |
| - | # # make sure index/404 are the slugs of the index/404 pages |
| - | # attributes.delete(:slug) if %w(index 404).include?(fullpath) |
| - | |
| - | # # trick to use the template of the default locale (if available) |
| - | # attributes[:template_path] = false if template.blank? |
| - | # end |
| - | # end |
| - | |
| - | # def each_file(&block) |
| - | # Dir.glob(File.join(path, '**', '*')).each do |filepath| |
| - | # next unless is_liquid_file?(filepath) |
| - | |
| - | # relative_path = get_relative_path(filepath) |
| - | |
| - | # fullpath, locale = relative_path.split('.')[0..1] |
| - | # locale = default_locale if template_extensions.include?(locale) |
| - | |
| - | # yield(filepath, relative_path, fullpath, locale.to_sym) |
| - | # end |
| - | # end |
| - | |
| - | # def is_liquid_file?(filepath) |
| - | # filepath =~ /\.(#{template_extensions.join('|')})$/ |
| - | # end |
| - | |
| - | # def template_path(filepath, attributes, locale) |
| - | # if attributes.delete(:template_path) == false && locale != default_locale |
| - | # false |
| - | # else |
| - | # filepath |
| - | # end |
| - | # end |
| - | |
| - | # def get_relative_path(filepath) |
| - | # filepath.gsub(path, '').gsub(/^\//, '') |
| - | # end |
| - | |
| - | # end |
| - | |
| - | # end |
| - | # end |
| - | # end |
| - | # end |
| - | # end |
| + | module Locomotive |
| + | module Steam |
| + | module Adapters |
| + | module Filesystem |
| + | module YAMLLoaders |
| + | |
| + | # class Page < Struct.new(:root_path, :default_locale, :cache) |
| + | class Page < Struct.new(:site_path, :default_locale, :cache) |
| + | |
| + | include Adapters::Filesystem::YAMLLoader |
| + | |
| + | def load |
| + | fetch('app/views/pages') { load_tree } |
| + | end |
| + | |
| + | private |
| + | |
| + | def path |
| + | @path ||= File.join(root_path, 'app', 'views', 'pages') |
| + | end |
| + | |
| + | def load_tree |
| + | {}.tap do |hash| |
| + | each_file do |filepath, relative_path, fullpath, locale| |
| + | |
| + | if leaf = hash[fullpath] |
| + | update(leaf, filepath, fullpath, locale) |
| + | else |
| + | leaf = build(filepath, fullpath, locale) |
| + | end |
| + | |
| + | hash[fullpath] = leaf |
| + | end |
| + | end.values |
| + | end |
| + | |
| + | def build(filepath, fullpath, locale) |
| + | slug = fullpath.split('/').last |
| + | attributes = get_attributes(filepath, fullpath) |
| + | |
| + | { |
| + | title: { locale => attributes.delete(:title) || (default_locale == locale ? slug.humanize : nil) }, |
| + | slug: { locale => attributes.delete(:slug) || slug }, |
| + | editable_elements: { locale => attributes.delete(:editable_elements) }, |
| + | template_path: { locale => template_path(filepath, attributes, locale) }, |
| + | redirect_url: { locale => attributes.delete(:redirect_url) }, |
| + | _fullpath: fullpath |
| + | }.merge(attributes) |
| + | end |
| + | |
| + | def update(leaf, filepath, fullpath, locale) |
| + | slug = fullpath.split('/').last |
| + | attributes = get_attributes(filepath, fullpath) |
| + | |
| + | leaf[:title][locale] = attributes.delete(:title) || slug.humanize |
| + | leaf[:slug][locale] = attributes.delete(:slug) || slug |
| + | leaf[:editable_elements][locale] = attributes.delete(:editable_elements) |
| + | leaf[:template_path][locale] = template_path(filepath, attributes, locale) |
| + | leaf[:redirect_url][locale] = attributes.delete(:redirect_url) |
| + | |
| + | leaf.merge!(attributes) |
| + | end |
| + | |
| + | def get_attributes(filepath, fullpath) |
| + | _load(filepath, true) do |attributes, template| |
| + | # make sure index/404 are the slugs of the index/404 pages |
| + | attributes.delete(:slug) if %w(index 404).include?(fullpath) |
| + | |
| + | # trick to use the template of the default locale (if available) |
| + | attributes[:template_path] = false if template.blank? |
| + | end |
| + | end |
| + | |
| + | def each_file(&block) |
| + | Dir.glob(File.join(path, '**', '*')).each do |filepath| |
| + | next unless is_liquid_file?(filepath) |
| + | |
| + | relative_path = get_relative_path(filepath) |
| + | |
| + | fullpath, locale = relative_path.split('.')[0..1] |
| + | locale = default_locale if template_extensions.include?(locale) |
| + | |
| + | yield(filepath, relative_path, fullpath, locale.to_sym) |
| + | end |
| + | end |
| + | |
| + | def is_liquid_file?(filepath) |
| + | filepath =~ /\.(#{template_extensions.join('|')})$/ |
| + | end |
| + | |
| + | def template_path(filepath, attributes, locale) |
| + | if attributes.delete(:template_path) == false && locale != default_locale |
| + | false |
| + | else |
| + | filepath |
| + | end |
| + | end |
| + | |
| + | def get_relative_path(filepath) |
| + | filepath.gsub(path, '').gsub(/^\//, '') |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/adapters/mongodb.rb b/lib/locomotive/steam/adapters/mongodb.rb
+46
-0
| @@ | @@ -0,0 +1,46 @@ |
| + | require 'moped' |
| + | require 'origin' |
| + | |
| + | require_relative 'mongodb/origin' |
| + | require_relative 'mongodb/query' |
| + | |
| + | module Locomotive::Steam |
| + | |
| + | class MongoDBAdapter < Struct.new(:database, :hosts) |
| + | |
| + | def all(mapper, selector = nil) |
| + | dataset(mapper, selector) |
| + | end |
| + | |
| + | def query(mapper, scope, &block) |
| + | query = query_klass.new(scope, mapper.localized_attributes, &block) |
| + | all(mapper, query.selector) |
| + | end |
| + | |
| + | private |
| + | |
| + | def query_klass |
| + | Locomotive::Steam::Adapters::MongoDB::Query |
| + | end |
| + | |
| + | def dataset(mapper, selector = nil) |
| + | collection(mapper).find(selector).map do |attributes| |
| + | entity = mapper.to_entity(attributes) |
| + | end |
| + | end |
| + | |
| + | def collection(mapper) |
| + | session["locomotive_#{mapper.name}"] |
| + | end |
| + | |
| + | def session |
| + | Moped::Session.new([*hosts]).tap do |session| |
| + | session.use database |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | |
locomotive/steam/adapters/mongodb/origin.rb b/lib/locomotive/steam/adapters/mongodb/origin.rb
+3
-0
| @@ | @@ -0,0 +1,3 @@ |
| + | class Origin::Query |
| + | include Origin::Queryable |
| + | end |
locomotive/steam/adapters/mongodb/query.rb b/lib/locomotive/steam/adapters/mongodb/query.rb
+35
-0
| @@ | @@ -0,0 +1,35 @@ |
| + | module Locomotive::Steam |
| + | module Adapters |
| + | module MongoDB |
| + | |
| + | class Query |
| + | |
| + | def initialize(scope, localized_attributes, &block) |
| + | @query = ::Origin::Query.new |
| + | @scope = scope |
| + | @localized_attributes = localized_attributes |
| + | |
| + | apply_default_scope |
| + | |
| + | instance_eval(&block) if block_given? |
| + | end |
| + | |
| + | def where(criterion = nil) |
| + | @query = @query.where(criterion) |
| + | end |
| + | |
| + | def selector |
| + | @query.selector |
| + | end |
| + | |
| + | private |
| + | |
| + | def apply_default_scope |
| + | where(site_id: @scope.site.id) if @scope.site |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
locomotive/steam/entities.rb b/lib/locomotive/steam/entities.rb
+0
-49
| @@ | @@ -1,49 +0,0 @@ |
| - | require_relative 'entities/concerns/validation.rb' |
| - | |
| - | module Locomotive |
| - | module Steam |
| - | |
| - | module Entities; end |
| - | |
| - | module Entity |
| - | |
| - | include Steam::Entities::Concerns::Validation |
| - | |
| - | attr_accessor :attributes |
| - | |
| - | def initialize(attributes) |
| - | @attributes = attributes |
| - | end |
| - | |
| - | def method_missing(name, *args, &block) |
| - | if attributes.include?(name) |
| - | self[name] |
| - | else |
| - | super |
| - | end |
| - | end |
| - | |
| - | def []=(name, value) |
| - | attributes[name.to_sym] = value |
| - | end |
| - | |
| - | def [](name) |
| - | attributes[name.to_sym] |
| - | end |
| - | |
| - | def self.set_localized_attributes(list) |
| - | singleton = class << self; self; end |
| - | singleton.class_eval do |
| - | define_method(:localized_attributes) { list } |
| - | end |
| - | |
| - | class_eval do |
| - | define_method(:localized_attributes) { list } |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | |
| - | require_relative_all 'entities' |
locomotive/steam/entities/concerns/validation.rb b/lib/locomotive/steam/entities/concerns/validation.rb
+0
-58
| @@ | @@ -1,58 +0,0 @@ |
| - | require 'forwardable' |
| - | |
| - | module Locomotive |
| - | module Steam |
| - | module Entities |
| - | module Concerns |
| - | |
| - | module Validation |
| - | |
| - | def errors |
| - | @errors ||= Errors.new(self) |
| - | end |
| - | |
| - | def valid? |
| - | true |
| - | end |
| - | |
| - | class Errors |
| - | |
| - | include Enumerable |
| - | extend Forwardable |
| - | |
| - | attr_accessor :messages |
| - | |
| - | def_delegators :@messages, :[], :clear, :empty?, :each, :size |
| - | |
| - | alias_method :blank?, :empty? |
| - | |
| - | def initialize(base) |
| - | @base = base |
| - | @messages = HashWithIndifferentAccess.new({}) |
| - | end |
| - | |
| - | def add_on_blank(attribute) |
| - | value = @base.send(attribute) |
| - | add(attribute, :blank) if value.blank? |
| - | end |
| - | |
| - | def add(attribute, message) |
| - | (@messages[attribute] ||= []) << generate_message(message) |
| - | end |
| - | |
| - | def generate_message(message) |
| - | case message |
| - | when :blank, :unique then I18n.t(message, scope: 'errors.messages') |
| - | else |
| - | message |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
locomotive/steam/entities/page.rb b/lib/locomotive/steam/entities/page.rb
+44
-0
| @@ | @@ -0,0 +1,44 @@ |
| + | module Locomotive::Steam |
| + | |
| + | class Page |
| + | |
| + | include Locomotive::Steam::Models::Entity |
| + | |
| + | attr_accessor :depth, :_fullpath, :content_entry |
| + | |
| + | def initialize(attributes) |
| + | super({ |
| + | handle: nil, |
| + | listed: false, |
| + | published: true, |
| + | fullpath: {}, |
| + | content_type: nil, |
| + | position: 99, |
| + | template: {}, |
| + | editable_elements: {}, |
| + | redirect_url: {} |
| + | }.merge(attributes)) |
| + | end |
| + | |
| + | def listed?; !!listed; end |
| + | def published?; !!published; end |
| + | |
| + | def templatized? |
| + | !!content_type |
| + | end |
| + | |
| + | def index? |
| + | attributes[:fullpath].values.first == 'index' |
| + | end |
| + | |
| + | def not_found? |
| + | attributes[:fullpath].values.first == '404' |
| + | end |
| + | |
| + | def to_liquid |
| + | Steam::Liquid::Drops::Page.new(self) |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
locomotive/steam/entities/site.rb b/lib/locomotive/steam/entities/site.rb
+28
-21
| @@ | @@ -1,32 +1,39 @@ |
| - | module Locomotive |
| - | module Steam |
| - | module Entities |
| + | module Locomotive::Steam |
| - | class Site |
| + | class Site |
| - | include Steam::Entity |
| + | include Locomotive::Steam::Models::Entity |
| - | def initialize(attributes = {}) |
| - | super({ |
| - | timezone: 'UTC', |
| - | prefix_default_locale: false |
| - | }.merge(attributes)) |
| - | end |
| + | def initialize(attributes = {}) |
| + | super({ |
| + | prefix_default_locale: false |
| + | }.merge(attributes)) |
| + | end |
| - | def default_locale |
| - | self.locales.try(:first) || :en |
| - | end |
| + | def handle |
| + | self[:handle] || self[:subdomain] |
| + | end |
| - | def locales |
| - | attributes[:locales].map(&:to_sym) |
| - | end |
| + | def default_locale |
| + | locales.try(:first) || :en |
| + | end |
| - | def to_liquid |
| - | Steam::Liquid::Drops::Site.new(self) |
| - | end |
| + | def locales |
| + | self[:locales].map(&:to_sym) |
| + | end |
| - | end |
| + | def timezone_name |
| + | self[:timezone] || self[:timezone_name] || 'UTC' |
| + | end |
| + | def timezone |
| + | @timezone ||= ActiveSupport::TimeZone.new(timezone_name) |
| end | |
| + | |
| + | def to_liquid |
| + | Steam::Liquid::Drops::Site.new(self) |
| + | end |
| + | |
| end | |
| + | |
| end | |
locomotive/steam/mapper.rb b/lib/locomotive/steam/mapper.rb
+0
-30
| @@ | @@ -1,30 +0,0 @@ |
| - | module Locomotive |
| - | module Steam |
| - | |
| - | class Mapper |
| - | |
| - | attr_reader :name, :options, :localized_attributes |
| - | |
| - | def initialize(name, options, &block) |
| - | @name, @options = name, options |
| - | @localized_attributes = [] |
| - | |
| - | instance_eval(&block) if block_given? |
| - | end |
| - | |
| - | def set_localized_attributes(*args) |
| - | @localized_attributes += [*args] |
| - | end |
| - | |
| - | def to_entity(attributes) |
| - | entity_klass.new(attributes) |
| - | end |
| - | |
| - | def entity_klass |
| - | options[:entity] |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
locomotive/steam/models.rb b/lib/locomotive/steam/models.rb
+6
-0
| @@ | @@ -0,0 +1,6 @@ |
| + | require_relative 'models/concerns/validation' |
| + | require_relative 'models/i18n_field' |
| + | require_relative 'models/entity' |
| + | require_relative 'models/mapper' |
| + | require_relative 'models/scope' |
| + | require_relative 'models/repository' |
locomotive/steam/models/concerns/validation.rb b/lib/locomotive/steam/models/concerns/validation.rb
+58
-0
| @@ | @@ -0,0 +1,58 @@ |
| + | require 'forwardable' |
| + | |
| + | module Locomotive |
| + | module Steam |
| + | module Models |
| + | module Concerns |
| + | |
| + | module Validation |
| + | |
| + | def errors |
| + | @errors ||= Errors.new(self) |
| + | end |
| + | |
| + | def valid? |
| + | true |
| + | end |
| + | |
| + | class Errors |
| + | |
| + | include Enumerable |
| + | extend Forwardable |
| + | |
| + | attr_accessor :messages |
| + | |
| + | def_delegators :@messages, :[], :clear, :empty?, :each, :size |
| + | |
| + | alias_method :blank?, :empty? |
| + | |
| + | def initialize(base) |
| + | @base = base |
| + | @messages = HashWithIndifferentAccess.new({}) |
| + | end |
| + | |
| + | def add_on_blank(attribute) |
| + | value = @base.send(attribute) |
| + | add(attribute, :blank) if value.blank? |
| + | end |
| + | |
| + | def add(attribute, message) |
| + | (@messages[attribute] ||= []) << generate_message(message) |
| + | end |
| + | |
| + | def generate_message(message) |
| + | case message |
| + | when :blank, :unique then I18n.t(message, scope: 'errors.messages') |
| + | else |
| + | message |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/models/entity.rb b/lib/locomotive/steam/models/entity.rb
+32
-0
| @@ | @@ -0,0 +1,32 @@ |
| + | module Locomotive::Steam |
| + | module Models |
| + | |
| + | module Entity |
| + | |
| + | include Locomotive::Steam::Models::Concerns::Validation |
| + | |
| + | attr_accessor :attributes |
| + | |
| + | def initialize(attributes) |
| + | @attributes = attributes.with_indifferent_access |
| + | end |
| + | |
| + | def method_missing(name, *args, &block) |
| + | if attributes.include?(name) |
| + | self[name] |
| + | else |
| + | super |
| + | end |
| + | end |
| + | |
| + | def []=(name, value) |
| + | attributes[name.to_sym] = value |
| + | end |
| + | |
| + | def [](name) |
| + | attributes[name.to_sym] |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
locomotive/steam/models/i18n_field.rb b/lib/locomotive/steam/models/i18n_field.rb
+25
-0
| @@ | @@ -0,0 +1,25 @@ |
| + | module Locomotive::Steam |
| + | module Models |
| + | |
| + | class I18nField |
| + | |
| + | attr_reader :name, :translations |
| + | |
| + | def initialize(name, translations) |
| + | @name = name |
| + | |
| + | if translations.respond_to?(:fetch) |
| + | @translations = translations.with_indifferent_access |
| + | else |
| + | @translations = Hash.new { translations } |
| + | end |
| + | end |
| + | |
| + | def [](locale) |
| + | @translations[locale] |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
locomotive/steam/models/mapper.rb b/lib/locomotive/steam/models/mapper.rb
+37
-0
| @@ | @@ -0,0 +1,37 @@ |
| + | module Locomotive::Steam |
| + | module Models |
| + | |
| + | class Mapper |
| + | |
| + | attr_reader :name, :options, :localized_attributes |
| + | |
| + | def initialize(name, options, &block) |
| + | @name, @options = name, options |
| + | @localized_attributes = [] |
| + | |
| + | instance_eval(&block) if block_given? |
| + | end |
| + | |
| + | def set_localized_attributes(*args) |
| + | @localized_attributes += [*args] |
| + | end |
| + | |
| + | def to_entity(attributes) |
| + | entity_klass.new(serialize(attributes)) |
| + | end |
| + | |
| + | def serialize(attributes) |
| + | localized_attributes.each do |name| |
| + | attributes[name] = I18nField.new(name, attributes[name]) |
| + | end |
| + | attributes |
| + | end |
| + | |
| + | def entity_klass |
| + | options[:entity] |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
locomotive/steam/models/repository.rb b/lib/locomotive/steam/models/repository.rb
+70
-0
| @@ | @@ -0,0 +1,70 @@ |
| + | module Locomotive::Steam |
| + | module Models |
| + | |
| + | module Repository |
| + | |
| + | extend ActiveSupport::Concern |
| + | |
| + | class RecordNotFound < StandardError; end |
| + | |
| + | attr_accessor :adapter, :current_site, :current_locale |
| + | |
| + | def initialize(adapter, current_site = nil, current_locale = nil) |
| + | @adapter = adapter |
| + | @current_site = current_site |
| + | @current_locale = current_locale |
| + | end |
| + | |
| + | def find(id) |
| + | adapter.find(mapper, scope, id) |
| + | end |
| + | |
| + | def query(&block) |
| + | adapter.query(mapper, scope, &block) |
| + | end |
| + | |
| + | alias :all :query |
| + | |
| + | # def create(entity) |
| + | # entity.id = adapter.create(collection_name, entity) |
| + | # end |
| + | |
| + | # def persisted?(entity) |
| + | # !!entity.id && adapter.persisted?(collection_name, entity) |
| + | # end |
| + | |
| + | # def update(entity) |
| + | # adapter.update(collection_name, entity) |
| + | # end |
| + | |
| + | # def destroy(entity) |
| + | # adapter.destroy(collection_name, entity) |
| + | # end |
| + | |
| + | def mapper |
| + | name, options, block = mapper_options |
| + | @mapper ||= Mapper.new(name, options, &block) |
| + | end |
| + | |
| + | def scope |
| + | @scope ||= Scope.new(current_site, current_locale) |
| + | end |
| + | |
| + | # def collection_name |
| + | # mapper.name |
| + | # end |
| + | |
| + | module ClassMethods |
| + | |
| + | def mapping(name, options = {}, &block) |
| + | class_eval do |
| + | define_method(:mapper_options) { [name, options, block] } |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
locomotive/steam/models/scope.rb b/lib/locomotive/steam/models/scope.rb
+17
-0
| @@ | @@ -0,0 +1,17 @@ |
| + | module Locomotive::Steam |
| + | module Models |
| + | |
| + | class Scope < Struct.new(:site, :locale) |
| + | |
| + | def default_locale |
| + | site.try(:default_locale) |
| + | end |
| + | |
| + | def locales |
| + | site.try(:locales) |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
locomotive/steam/repositories.rb b/lib/locomotive/steam/repositories.rb
+62
-55
| @@ | @@ -1,75 +1,82 @@ |
| - | module Locomotive |
| - | module Steam |
| - | module Repository |
| + | raise 'NOT GOOD' |
| - | extend ActiveSupport::Concern |
| + | # module Locomotive |
| + | # module Steam |
| + | # module Repository |
| - | class RecordNotFound < StandardError; end |
| + | # extend ActiveSupport::Concern |
| - | attr_reader :adapter |
| + | # class RecordNotFound < StandardError; end |
| - | attr_accessor :current_locale |
| + | # attr_accessor :adapter, :current_site, :current_locale |
| - | def initialize(adapter) |
| - | @adapter = adapter |
| - | end |
| + | # def initialize(adapter, current_site = nil, current_locale = nil) |
| + | # @adapter = adapter |
| + | # @current_site = current_site |
| + | # @current_locale = current_locale |
| + | # end |
| - | def all |
| - | adapter.all(mapper) |
| - | end |
| + | # def all |
| + | # adapter.all(mapper) |
| + | # end |
| - | # def find(id) |
| - | # adapter.find(mapper, id) |
| - | # end |
| + | # # def find(id) |
| + | # # adapter.find(mapper, id) |
| + | # # end |
| - | def query(&block) |
| - | adapter.query(mapper, current_locale, &block) |
| - | end |
| + | # def query(&block) |
| + | # adapter.query(mapper, current_locale, &block) |
| + | # end |
| - | # def create(entity) |
| - | # entity.id = adapter.create(collection_name, entity) |
| - | # end |
| + | # # def create(entity) |
| + | # # entity.id = adapter.create(collection_name, entity) |
| + | # # end |
| - | # def persisted?(entity) |
| - | # !!entity.id && adapter.persisted?(collection_name, entity) |
| - | # end |
| + | # # def persisted?(entity) |
| + | # # !!entity.id && adapter.persisted?(collection_name, entity) |
| + | # # end |
| - | # def update(entity) |
| - | # adapter.update(collection_name, entity) |
| - | # end |
| + | # # def update(entity) |
| + | # # adapter.update(collection_name, entity) |
| + | # # end |
| - | # def destroy(entity) |
| - | # adapter.destroy(collection_name, entity) |
| - | # end |
| + | # # def destroy(entity) |
| + | # # adapter.destroy(collection_name, entity) |
| + | # # end |
| - | def mapper |
| - | name, options, block = mapper_options |
| - | @mapper ||= Steam::Mapper.new(name, options, &block) |
| - | end |
| + | # def mapper |
| + | # name, options, block = mapper_options |
| + | # @mapper ||= Steam::Mapper.new(name, options, &block) |
| + | # end |
| - | # def collection_name |
| - | # mapper.name |
| - | # end |
| + | # def scope |
| + | # Steam:: |
| + | # end |
| - | module ClassMethods |
| + | # # def collection_name |
| + | # # mapper.name |
| + | # # end |
| - | def mapping(name, options = {}, &block) |
| - | class_eval do |
| - | define_method(:mapper_options) { [name, options, block] } |
| - | end |
| - | end |
| + | # module ClassMethods |
| - | end |
| + | # def mapping(name, options = {}, &block) |
| + | # class_eval do |
| + | # define_method(:mapper_options) { [name, options, block] } |
| + | # end |
| + | # end |
| - | end |
| - | end |
| - | end |
| + | # end |
| - | module Locomotive |
| - | module Steam |
| - | module Repositories |
| - | end |
| - | end |
| - | end |
| + | # end |
| + | # end |
| + | # end |
| - | require_relative 'repositories/site_repository' |
| + | # module Locomotive |
| + | # module Steam |
| + | # module Repositories |
| + | # end |
| + | # end |
| + | # end |
| + | |
| + | # require_relative 'repositories/site_repository' |
| + | # require_relative 'repositories/page_repository' |
locomotive/steam/repositories/filesystem/page.rb b/lib/locomotive/steam/repositories/filesystem/page.rb
+1
-0
| @@ | @@ -47,6 +47,7 @@ module Locomotive |
| def parent_of(page) | |
| return nil if page.nil? || page.index? | |
| + | # TODO: parent_id property |
| segments = localized_attribute(page, :fullpath).split('/') | |
| path = segments[0..-2].join('/') | |
| path = 'index' if path.blank? | |
locomotive/steam/repositories/page_repository.rb b/lib/locomotive/steam/repositories/page_repository.rb
+104
-0
| @@ | @@ -0,0 +1,104 @@ |
| + | module Locomotive |
| + | module Steam |
| + | |
| + | class PageRepository < Struct.new(:adapter, :site, :current_locale) |
| + | |
| + | include Models::Repository |
| + | |
| + | mapping :pages, entity: Page do |
| + | set_localized_attributes :title, :slug, :permalink, :editable_elements, :template, :template_path, :redirect_url, :fullpath, :seo_title, :meta_description, :meta_keywords |
| + | end |
| + | |
| + | # Engine: site.pages.ordered_pages(conditions) |
| + | def all(conditions = {}) |
| + | default_order = 'depth_and_position asc' |
| + | query { where(conditions || {}).order_by(default_order) }.all |
| + | end |
| + | |
| + | # Engine: site.pages.where(handle: handle).first |
| + | def by_handle(handle) |
| + | query { where(handle: handle) }.first |
| + | end |
| + | |
| + | def by_fullpath(path) |
| + | query { where(fullpath: path) }.first |
| + | end |
| + | |
| + | def matching_fullpath(list) |
| + | all('fullpath.in' => list) |
| + | end |
| + | |
| + | # Engine: ??? |
| + | def template_for(entry, handle = nil) |
| + | conditions = { templatized?: true, content_type: entry.try(:content_type_slug) } |
| + | |
| + | conditions[:handle] = handle if handle |
| + | |
| + | query { where(conditions) }.first.tap do |page| |
| + | page.content_entry = entry if page |
| + | end |
| + | end |
| + | |
| + | def root |
| + | query { where(fullpath: 'index') }.first |
| + | end |
| + | |
| + | # Engine: page.parent |
| + | def parent_of(page) |
| + | return nil if page.nil? || page.index? |
| + | |
| + | # TODO: parent_id property |
| + | segments = localized_attribute(page, :fullpath).split('/') |
| + | path = segments[0..-2].join('/') |
| + | path = 'index' if path.blank? |
| + | |
| + | by_fullpath(path) |
| + | end |
| + | |
| + | # Engine: page.ancestors_and_self |
| + | def ancestors_of(page) |
| + | return [] if page.nil? |
| + | |
| + | # Example: foo/bar/test |
| + | # ['foo', 'foo/bar', 'foo/bar/test'] |
| + | segments = localized_attribute(page, :fullpath).split('/') |
| + | paths = 0.upto(segments.size - 1).map { |i| segments[0..i].join('/') } |
| + | |
| + | all('fullpath.in' => ['index'] + paths) |
| + | end |
| + | |
| + | # Engine: page.children |
| + | def children_of(page) |
| + | return [] if page.nil? |
| + | |
| + | conditions = { 'slug.ne' => nil, depth: page.depth + 1 } |
| + | |
| + | unless page.index? |
| + | conditions[:fullpath] = /^#{localized_attribute(page, :fullpath)}\// |
| + | end |
| + | |
| + | all(conditions) |
| + | end |
| + | |
| + | # Engine: page.editable_elements |
| + | def editable_elements_of(page) |
| + | return nil if page.nil? |
| + | localized_attribute(page, :editable_elements).values |
| + | end |
| + | |
| + | # Engine: page.editable_elements.where(block: block, slug: slug).first |
| + | def editable_element_for(page, block, slug) |
| + | return nil if page.nil? |
| + | |
| + | if elements = localized_attribute(page, :editable_elements) |
| + | name = [block, slug].compact.join('/') |
| + | elements[name] |
| + | else |
| + | nil |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
locomotive/steam/repositories/site_repository.rb b/lib/locomotive/steam/repositories/site_repository.rb
+4
-4
| @@ | @@ -3,17 +3,17 @@ module Locomotive |
| class SiteRepository | |
| - | include Steam::Repository |
| + | include Models::Repository |
| - | mapping :sites, entity: Steam::Entities::Site do |
| + | mapping :sites, entity: Site do |
| set_localized_attributes :seo_title, :meta_description, :meta_keywords | |
| end | |
| def by_handle_or_domain(handle, domain) | |
| if handle.nil? | |
| - | query { where(handle: handle) }.first |
| + | query { where('domains.in' => domain) }.first |
| else | |
| - | query { where('domains.in' => [*domain]) }.first |
| + | query { where(handle: handle) }.first |
| end | |
| end | |
locomotivecms_steam.gemspec
+3
-0
| @@ | @@ -19,6 +19,9 @@ Gem::Specification.new do |spec| |
| spec.add_development_dependency 'bundler', '~> 1.7' | |
| spec.add_development_dependency 'rake', '~> 10.4.2' | |
| + | spec.add_development_dependency 'moped', '~> 2.0.4' |
| + | spec.add_development_dependency 'origin', '~> 1.0.4' |
| + | |
| spec.add_dependency 'activesupport', '~> 4.2.0' | |
| spec.add_dependency 'stringex', '~> 2.5.2' | |
| spec.add_dependency 'sanitize', '~> 3.1.0' | |
spec/integration/repositories/site_repository_spec.rb
+42
-0
| @@ | @@ -0,0 +1,42 @@ |
| + | require 'spec_helper' |
| + | |
| + | require_relative '../../../lib/locomotive/steam/adapters/filesystem.rb' |
| + | require_relative '../../../lib/locomotive/steam/adapters/mongodb.rb' |
| + | |
| + | describe Locomotive::Steam::SiteRepository do |
| + | |
| + | let(:repository) { Locomotive::Steam::SiteRepository.new(adapter) } |
| + | |
| + | context 'MongoDB' do |
| + | |
| + | let(:adapter) { Locomotive::Steam::MongoDBAdapter.new('steam_test', ['127.0.0.1:27017']) } |
| + | |
| + | describe '#all' do |
| + | subject { repository.all } |
| + | it { expect(subject.size).to eq 1 } |
| + | end |
| + | |
| + | describe '#query' do |
| + | subject { repository.query { where(handle: 'acme') }.first } |
| + | it { expect(subject.name).to eq 'My portfolio' } |
| + | end |
| + | |
| + | end |
| + | |
| + | context 'Filesystem' do |
| + | |
| + | let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(default_fixture_site_path) } |
| + | |
| + | describe '#all' do |
| + | subject { repository.all } |
| + | it { expect(subject.size).to eq 1 } |
| + | end |
| + | |
| + | describe '#query' do |
| + | subject { repository.query { where(subdomain: 'sample') }.first } |
| + | it { expect(subject.name).to eq 'Sample website' } |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
spec/spec_helper.rb
+5
-4
| @@ | @@ -14,9 +14,9 @@ SimpleCov.start do |
| add_filter 'spec/' | |
| add_group "Middlewares", "lib/locomotive/steam/middlewares" | |
| - | add_group "Liquid Filters", "lib/locomotive/steam/liquid/filters" |
| - | add_group "Liquid Tags", "lib/locomotive/steam/liquid/tags" |
| - | add_group "Liquid Drops", "lib/locomotive/steam/liquid/drops" |
| + | add_group "Liquid", "lib/locomotive/steam/liquid" |
| + | add_group "Adapters", "lib/locomotive/steam/adapters" |
| + | add_group "Entities", "lib/locomotive/steam/entities" |
| add_group "Repositories", "lib/locomotive/steam/repositories" | |
| add_group "Services", "lib/locomotive/steam/services" | |
| end | |
| @@ | @@ -27,7 +27,8 @@ require 'bundler/setup' |
| require 'i18n-spec' | |
| require_relative '../lib/locomotive/steam' | |
| - | require_relative '../lib/locomotive/steam/repositories/filesystem' |
| + | # TODO |
| + | # require_relative '../lib/locomotive/steam/repositories/filesystem' |
| require_relative 'support' | |
| Locomotive::Steam.configure do |config| | |
spec/unit/adapters/filesystem_spec.rb
+45
-0
| @@ | @@ -0,0 +1,45 @@ |
| + | require 'spec_helper' |
| + | |
| + | require_relative '../../../lib/locomotive/steam/adapters/filesystem.rb' |
| + | |
| + | describe Locomotive::Steam::FilesystemAdapter do |
| + | |
| + | let(:mapper) { instance_double('Mapper', name: :test) } |
| + | let(:scope) { instance_double('Scope', site: site, locale: nil) } |
| + | let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(nil) } |
| + | |
| + | describe '#query' do |
| + | |
| + | let(:collection) { [OpenStruct.new(site_id: 42, name: 'Hello world')] } |
| + | |
| + | before do |
| + | allow(mapper).to receive(:to_entity) { |arg| arg } |
| + | allow(adapter).to receive(:collection).and_return(collection) |
| + | end |
| + | |
| + | subject { adapter.query(mapper, scope) { where(name: 'Hello world') } } |
| + | |
| + | context 'not scoped by a site' do |
| + | |
| + | let(:site) { nil } |
| + | it { expect(subject.first.name).to eq 'Hello world' } |
| + | |
| + | end |
| + | |
| + | context 'scoped by a site' do |
| + | |
| + | let(:site) { instance_double('Site', id: 42) } |
| + | it { expect(subject.first.name).to eq 'Hello world' } |
| + | |
| + | context 'unknown site id' do |
| + | |
| + | let(:site) { instance_double('Site', id: 1) } |
| + | it { expect(subject.first).to eq nil } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
spec/unit/entities/page_spec.rb
+43
-0
| @@ | @@ -0,0 +1,43 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Page do |
| + | |
| + | let(:attributes) { {} } |
| + | let(:page) { Locomotive::Steam::Page.new(attributes) } |
| + | |
| + | describe '#index?' do |
| + | |
| + | let(:attributes) { { fullpath: { en: 'foo/index' } } } |
| + | |
| + | subject { page.index? } |
| + | it { is_expected.to eq false } |
| + | |
| + | context 'true' do |
| + | let(:attributes) { { fullpath: { en: 'index' } } } |
| + | it { is_expected.to eq true } |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#not_found?' do |
| + | |
| + | let(:attributes) { { fullpath: { en: 'index' } } } |
| + | |
| + | subject { page.not_found? } |
| + | it { is_expected.to eq false } |
| + | |
| + | context 'true' do |
| + | let(:attributes) { { fullpath: { en: '404' } } } |
| + | it { is_expected.to eq true } |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#valid?' do |
| + | |
| + | subject { page.valid? } |
| + | it { is_expected.to eq true } |
| + | |
| + | end |
| + | |
| + | end |
spec/unit/entities/site_spec.rb
+63
-0
| @@ | @@ -0,0 +1,63 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Site do |
| + | |
| + | let(:attributes) { {} } |
| + | let(:site) { Locomotive::Steam::Site.new(attributes) } |
| + | |
| + | describe '#handle' do |
| + | |
| + | let(:attributes) { { handle: 'acme' } } |
| + | |
| + | subject { site.handle } |
| + | it { is_expected.to eq 'acme' } |
| + | |
| + | context 'from a subdomain if the handle property is nil' do |
| + | |
| + | let(:attributes) { { subdomain: 'acme' } } |
| + | it { is_expected.to eq 'acme' } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#locales' do |
| + | |
| + | let(:attributes) { { locales: %w(en fr) } } |
| + | |
| + | subject { site.locales } |
| + | it { is_expected.to eq [:en, :fr] } |
| + | |
| + | end |
| + | |
| + | describe '#default_locale' do |
| + | |
| + | let(:attributes) { { locales: %w(en fr) } } |
| + | |
| + | subject { site.default_locale } |
| + | it { is_expected.to eq :en } |
| + | |
| + | end |
| + | |
| + | describe '#timezone_name' do |
| + | |
| + | subject { site.timezone_name } |
| + | it { is_expected.to eq 'UTC' } |
| + | |
| + | context 'not blank' do |
| + | |
| + | let(:attributes) { { timezone: 'CDT' } } |
| + | it { is_expected.to eq 'CDT' } |
| + | |
| + | end |
| + | |
| + | context 'from the timezone_name attribute itself' do |
| + | |
| + | let(:attributes) { { timezone_name: 'CDT' } } |
| + | it { is_expected.to eq 'CDT' } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
spec/unit/models/mapper_spec.rb
+41
-0
| @@ | @@ -0,0 +1,41 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Models::Mapper do |
| + | |
| + | let(:name) { 'pages' } |
| + | let(:options) { { entity: MyPage } } |
| + | let(:block) { nil } |
| + | let(:mapper) { Locomotive::Steam::Models::Mapper.new(name, options, &block) } |
| + | |
| + | describe '#localized attributes' do |
| + | |
| + | let(:block) { ->(_) { set_localized_attributes(:foo, :bar) } } |
| + | |
| + | subject { mapper.localized_attributes } |
| + | it { is_expected.to eq [:foo, :bar] } |
| + | |
| + | end |
| + | |
| + | describe '#to_entity' do |
| + | |
| + | let(:block) { ->(_) { set_localized_attributes(:title) } } |
| + | let(:attributes) { { title: { 'en' => 'Hello world' } } } |
| + | |
| + | subject { mapper.to_entity(attributes) } |
| + | it { expect(subject.attributes[:title].class).to eq Locomotive::Steam::Models::I18nField } |
| + | it { expect(subject.attributes[:title][:en]).to eq('Hello world') } |
| + | |
| + | context 'string value for the localized field' do |
| + | |
| + | let(:attributes) { { title: 'Hello world' } } |
| + | |
| + | it { expect(subject.attributes[:title][:en]).to eq('Hello world') } |
| + | it { expect(subject.attributes[:title][:fr]).to eq('Hello world') } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | class MyPage < Struct.new(:attributes); end |
| + | |
| + | end |
spec/unit/repositories/page_repository_spec.rb
+307
-0
| @@ | @@ -0,0 +1,307 @@ |
| + | require 'spec_helper' |
| + | |
| + | require_relative '../../../lib/locomotive/steam/adapters/filesystem.rb' |
| + | |
| + | describe Locomotive::Steam::PageRepository do |
| + | |
| + | let(:locale) { :en } |
| + | let(:site) { instance_double('Site', _id: 1, default_locale: :en, locales: %i(en fr)) } |
| + | let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(nil) } |
| + | let(:repository) { Locomotive::Steam::PageRepository.new(adapter, site, locale) } |
| + | |
| + | # describe '#collection' do |
| + | |
| + | # subject { repository.send(:collection).first } |
| + | |
| + | # it { expect(subject.class).to eq Locomotive::Steam::Repositories::Filesystem::Models::Page } |
| + | |
| + | # it 'applies the sanitizer' do |
| + | # expect(subject[:fullpath]).to eq({ en: 'index' }) |
| + | # expect(subject.depth).to eq 0 |
| + | # end |
| + | |
| + | # end |
| + | |
| + | describe '#all' do |
| + | |
| + | let(:pages) do |
| + | [ |
| + | { title: { en: 'Contact' }, slug: { en: 'contact' }, _fullpath: 'contact', template_path: { en: 'contact.liquid' } }, |
| + | { title: { en: 'About us' }, position: 2, slug: { en: 'about-us' }, _fullpath: 'about-us', template_path: { en: 'about-us.liquid' } }, |
| + | { title: { en: 'Jane Doe' }, slug: { en: 'jane-doe' }, _fullpath: 'team/jane-doe', template_path: { en: 'team/jane-doe.liquid' } }, |
| + | { title: { en: 'John Doe' }, position: 1, slug: { en: 'john-doe' }, _fullpath: 'team/john-doe', template_path: { en: 'team/john-doe.liquid' } }, |
| + | { title: { en: 'Home' }, slug: { en: 'index' }, _fullpath: 'index', template_path: { en: 'index.liquid' } } |
| + | ] |
| + | end |
| + | |
| + | let(:conditions) { nil } |
| + | |
| + | subject { repository.all(conditions) } |
| + | |
| + | it { expect(subject.size).to eq 5 } |
| + | |
| + | describe 'default order' do |
| + | |
| + | subject { repository.all(conditions).map { |p| p.title.values.first } } |
| + | |
| + | it { is_expected.to eq ['Home', 'About us', 'Contact', 'John Doe', 'Jane Doe'] } |
| + | |
| + | end |
| + | |
| + | describe 'filter' do |
| + | |
| + | let(:conditions) { { slug: /-doe$/ } } |
| + | it { expect(subject.size).to eq 2 } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#by_fullpath' do |
| + | |
| + | let(:path) { nil } |
| + | subject { repository.by_fullpath(path) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | context 'existing page' do |
| + | |
| + | let(:path) { 'index' } |
| + | it { expect(subject.title).to eq({ en: 'Home' }) } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#by_handle' do |
| + | |
| + | let(:handle) { nil } |
| + | subject { repository.by_handle(handle) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | context 'existing page' do |
| + | |
| + | let(:handle) { 'home' } |
| + | it { expect(subject.title).to eq({ en: 'Home' }) } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#matching_fullpath' do |
| + | |
| + | let(:paths) { nil } |
| + | subject { repository.matching_fullpath(paths) } |
| + | |
| + | it { is_expected.to eq [] } |
| + | |
| + | context 'existing page' do |
| + | |
| + | let(:paths) { ['index', '404'] } |
| + | it { expect(subject.first.title).to eq({ en: 'Home' }) } |
| + | |
| + | end |
| + | |
| + | context 'templatized page' do |
| + | |
| + | let(:paths) { ['articles/content-type-template', 'content-type-template/hello-world', 'articles/hello-world'] } |
| + | |
| + | let(:pages) do |
| + | [{ title: { en: 'Templatized article' }, slug: { en: 'template' }, content_type: 'articles', _fullpath: 'articles/template', template_path: { en: 'articles/template.liquid' } }] |
| + | end |
| + | |
| + | it { expect(subject.first.title).to eq({ en: 'Templatized article' }) } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#template_for' do |
| + | |
| + | let(:pages) do |
| + | [ |
| + | { title: { en: 'Article template' }, content_type: 'articles', slug: { en: 'articles/content_type_template' }, _fullpath: 'articles/template', template_path: { en: 'articles/template.liquid' } }, |
| + | { title: { en: 'Archived article template' }, handle: 'archive', content_type: 'articles', slug: { en: 'archived/articles/content_type_template' }, _fullpath: 'archived/articles/template', template_path: { en: 'archived/articles/template.liquid' } }, |
| + | { title: { en: 'Home' }, handle: 'home', slug: { en: 'index' }, _fullpath: 'index', template_path: { en: 'index.liquid' } } |
| + | ] |
| + | end |
| + | let(:entry) { nil } |
| + | let(:handle) { nil } |
| + | |
| + | subject { repository.template_for(entry, handle) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | context 'both existing entry and page' do |
| + | |
| + | let(:entry) { instance_double('Article', content_type_slug: 'articles', _slug: { en: 'hello-world' }) } |
| + | it { expect(subject.title).to eq({ en: 'Article template' }) } |
| + | it { expect(subject.content_entry).to eq entry } |
| + | |
| + | context 'with a handle' do |
| + | |
| + | let(:handle) { 'archive' } |
| + | it { expect(subject.title).to eq({ en: 'Archived article template' }) } |
| + | it { expect(subject.content_entry).to eq entry } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | context 'unknown content type' do |
| + | |
| + | let(:entry) { instance_double('Project', content_type_slug: 'projects', _slug: { en: 'hello-world' }) } |
| + | it { is_expected.to eq nil } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#root' do |
| + | |
| + | subject { repository.root } |
| + | it { expect(subject.title).to eq({ en: 'Home' }) } |
| + | |
| + | end |
| + | |
| + | describe '#parent_of' do |
| + | |
| + | let(:page) { nil } |
| + | subject { repository.parent_of(page) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | context 'index' do |
| + | |
| + | let(:page) { instance_double('Page', index?: true) } |
| + | it { is_expected.to eq nil } |
| + | |
| + | end |
| + | |
| + | context 'page not nil' do |
| + | |
| + | let(:page) { instance_double('Page', index?: false, fullpath: { en: 'about-us' }) } |
| + | it { expect(subject.title).to eq({ en: 'Home' }) } |
| + | |
| + | end |
| + | |
| + | context 'nested pages' do |
| + | |
| + | let(:pages) do |
| + | [ |
| + | { title: { en: 'Somewhere' }, slug: { en: 'somewhere' }, _fullpath: 'somewhere', template_path: { en: 'somewhere.liquid' } }, |
| + | { title: { en: 'Home' }, slug: { en: 'index' }, _fullpath: 'index', template_path: { en: 'index.liquid' } } |
| + | ] |
| + | end |
| + | let(:page) { instance_double('Page', index?: false, fullpath: { en: 'somewhere/hello-world' }) } |
| + | |
| + | it { expect(subject.title).to eq({ en: 'Somewhere' }) } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#ancestors_of' do |
| + | |
| + | let(:page) { nil } |
| + | subject { repository.ancestors_of(page) } |
| + | |
| + | it { is_expected.to eq [] } |
| + | |
| + | context 'index' do |
| + | |
| + | let(:page) { instance_double('Page', fullpath: 'index') } |
| + | it { expect(subject.map(&:title)).to eq([{ en: 'Home' }]) } |
| + | |
| + | end |
| + | |
| + | context 'nested pages' do |
| + | |
| + | let(:pages) do |
| + | [ |
| + | { title: { en: 'Foo' }, slug: { en: 'foo' }, _fullpath: 'bar/foo', template_path: { en: 'bar/foo.liquid' } }, |
| + | { title: { en: 'Bar' }, slug: { en: 'bar' }, _fullpath: 'bar', template_path: { en: 'bar.liquid' } }, |
| + | { title: { en: 'Home' }, slug: { en: 'index' }, _fullpath: 'index', template_path: { en: 'index.liquid' } } |
| + | ] |
| + | end |
| + | let(:page) { instance_double('Page', title: { en: 'Foo' }, index?: false, fullpath: { en: 'bar/foo' }) } |
| + | |
| + | it { expect(subject.map { |p| p.title.values.first }).to eq ['Home', 'Bar', 'Foo'] } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#children_of' do |
| + | |
| + | let(:page) { nil } |
| + | subject { repository.children_of(page) } |
| + | |
| + | it { is_expected.to eq [] } |
| + | |
| + | context 'with pages' do |
| + | |
| + | let(:pages) do |
| + | [ |
| + | { title: { en: 'Foo' }, slug: { en: 'foo' }, _fullpath: 'bar/foo', template_path: { en: 'bar/foo.liquid' } }, |
| + | { title: { en: 'Bar' }, slug: { en: 'bar' }, _fullpath: 'bar', template_path: { en: 'bar.liquid' } }, |
| + | { title: { en: 'Home' }, slug: { en: 'index' }, _fullpath: 'index', template_path: { en: 'index.liquid' } } |
| + | ] |
| + | end |
| + | let(:page) { instance_double('Page', title: { en: 'Home' }, depth: 0, index?: true, fullpath: { en: 'index' }) } |
| + | |
| + | it { expect(subject.map { |p| p.title.values.first }).to eq ['Bar'] } |
| + | |
| + | context 'from a nested page' do |
| + | |
| + | let(:page) { instance_double('Page', title: { en: 'Bar' }, index?: false, depth: 1, fullpath: { en: 'bar' }) } |
| + | it { expect(subject.map { |p| p.title.values.first }).to eq ['Foo'] } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#editable_elements_of' do |
| + | |
| + | let(:page) { nil } |
| + | subject { repository.editable_elements_of(page) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | context 'page with editable elements' do |
| + | |
| + | let(:elements) { { 'title' => instance_double('Element', content: 'Stuff here') } } |
| + | let(:page) { instance_double('Page', editable_elements: { en: elements }) } |
| + | |
| + | it { expect(subject.map(&:content)).to eq ['Stuff here'] } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#editable_element_for' do |
| + | |
| + | let(:page) { nil } |
| + | let(:block) { nil } |
| + | let(:slug) { nil } |
| + | subject { repository.editable_element_for(page, block, slug) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | context 'page with editable elements' do |
| + | |
| + | let(:elements) { { 'title' => instance_double('Element', content: 'Stuff here') } } |
| + | let(:page) { instance_double('Page', editable_elements: { en: elements }) } |
| + | let(:block) { nil } |
| + | let(:slug) { 'title' } |
| + | |
| + | it { expect(subject.content).to eq 'Stuff here' } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
spec/unit/repositories/site_repository_spec.rb
+19
-9
| @@ | @@ -4,24 +4,34 @@ require_relative '../../../lib/locomotive/steam/adapters/filesystem.rb' |
| describe Locomotive::Steam::SiteRepository do | |
| - | let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(default_fixture_site_path) } |
| + | let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(nil) } |
| let(:repository) { Locomotive::Steam::SiteRepository.new(adapter) } | |
| - | describe '#all' do |
| + | before { allow(adapter).to receive(:collection).and_return([{ name: 'Acme', handle: 'acme', domains: ['example.org'] }]) } |
| - | subject { repository.all } |
| + | describe '#by_handle_or_domain' do |
| - | it { expect(subject.size).to eq 1 } |
| + | let(:handle) { nil } |
| + | let(:domains) { nil } |
| - | end |
| + | subject { repository.by_handle_or_domain(handle, domains) } |
| + | |
| + | it { expect(subject).to eq nil } |
| + | |
| + | context 'handle' do |
| - | describe '#query' do |
| + | let(:handle) { 'acme' } |
| + | it { expect(subject.class).to eq Locomotive::Steam::Site } |
| + | it { expect(subject.name).to eq 'Acme' } |
| - | subject do |
| - | repository.query { where(subdomain: 'sample') }.first |
| end | |
| - | it { expect(subject.name).to eq 'Sample website' } |
| + | context 'domain' do |
| + | |
| + | let(:domains) { 'example.org' } |
| + | it { expect(subject.name).to eq 'Acme' } |
| + | |
| + | end |
| end | |