working on the content entry filesystem repository (WIP), broken specs (tha's bad I know)
did
committed Feb 13, 2015
commit a5c798c67ad54c6ffe2f0f168e81a1ede975569f
Showing 22
changed files with
583 additions
and 40 deletions
Gemfile.lock
+2
-0
| @@ | @@ -4,6 +4,7 @@ PATH |
| locomotivecms_steam (0.2.0.pre.beta) | |
| RedCloth (~> 4.2.9) | |
| activesupport (~> 4.2.0) | |
| + | chronic (~> 0.10.2) |
| coffee-script (~> 2.3.0) | |
| compass (~> 1.0.3) | |
| dragonfly (~> 1.0.7) | |
| @@ | @@ -52,6 +53,7 @@ GEM |
| columnize (~> 0.8) | |
| debugger-linecache (~> 1.2) | |
| slop (~> 3.6) | |
| + | chronic (0.10.2) |
| chunky_png (1.3.3) | |
| codeclimate-test-reporter (0.4.6) | |
| simplecov (>= 0.7.1, < 1.0.0) | |
locomotive/steam.rb b/lib/locomotive/steam.rb
+2
-0
| @@ | @@ -16,6 +16,8 @@ require_relative 'steam/repositories' |
| require_relative 'steam/services' | |
| # TODO: move into a file named dependencies | |
| + | |
| + | # TODO: move them to a different place |
| require 'haml' | |
| require 'compass' | |
| require 'mimetype_fu' | |
locomotive/steam/liquid/drops/content_entry.rb b/lib/locomotive/steam/liquid/drops/content_entry.rb
+12
-10
| @@ | @@ -50,14 +50,16 @@ module Locomotive |
| return '' if @_source.nil? | |
| if not @@forbidden_attributes.include?(meth.to_s) | |
| - | value = @_source.send(meth) |
| + | repository.value_for(meth, @_source, @context['with_scope']) |
| - | # check for an association (lazy loading) |
| - | if value.respond_to?(:all) |
| - | filter_association(value) |
| - | else |
| - | value |
| - | end |
| + | # value = @_source.send(meth) |
| + | |
| + | # # check for an association (lazy loading) |
| + | # if value.respond_to?(:all) |
| + | # filter_association(value) |
| + | # else |
| + | # value |
| + | # end |
| else | |
| nil | |
| end | |
| @@ | @@ -69,9 +71,9 @@ module Locomotive |
| @context.registers[:services].repositories.content_entry | |
| end | |
| - | def filter_association(association) |
| - | repository.filter(association, @context['with_scope'] || {}) |
| - | end |
| + | # def fetch_association(name) |
| + | # repository.association(name, @_source, @context['with_scope'] || {}) |
| + | # end |
| end | |
| end | |
locomotive/steam/repositories/filesystem.rb b/lib/locomotive/steam/repositories/filesystem.rb
+3
-1
| @@ | @@ -39,7 +39,9 @@ module Locomotive |
| end | |
| register :content_entry do | |
| - | Filesystem::ContentEntry.new(current_site) |
| + | Filesystem::ContentEntry.new( |
| + | YAMLLoaders::ContentEntry.new(options[:path], cache), |
| + | current_site, current_locale) |
| end | |
| register :theme_asset do | |
locomotive/steam/repositories/filesystem/concerns/queryable.rb b/lib/locomotive/steam/repositories/filesystem/concerns/queryable.rb
+18
-9
| @@ | @@ -8,25 +8,34 @@ module Locomotive |
| extend ActiveSupport::Concern | |
| - | def query(&block) |
| + | def query(*args, &block) |
| _locale = respond_to?(:current_locale) ? current_locale : nil | |
| - | MemoryAdapter::Query.new(collection, _locale, &block) |
| + | MemoryAdapter::Query.new(memoized_collection(*args), _locale, &block) |
| end | |
| private | |
| - | def collection |
| + | def memoized_collection(*args) |
| return @collection if @collection | |
| - | @collection = loader.list_of_attributes.map do |attributes| |
| + | @collection = collection(*args) |
| + | end |
| + | |
| + | def collection(*args) |
| + | _collection = loader.list_of_attributes(*args).map do |attributes| |
| collection_options[:model].new(attributes) | |
| end | |
| - | if sanitizer = collection_options[:sanitizer] |
| - | sanitizer.new(site.default_locale, site.locales).apply_to(@collection) |
| - | else |
| - | @collection |
| - | end |
| + | sanitize!(_collection) |
| + | end |
| + | |
| + | def sanitize!(collection) |
| + | sanitizer.try(:apply_to, collection) || collection |
| + | end |
| + | |
| + | def sanitizer |
| + | return unless (klass = collection_options[:sanitizer]) |
| + | klass.new(site.default_locale, site.locales) |
| end | |
| module ClassMethods | |
locomotive/steam/repositories/filesystem/content_entry.rb b/lib/locomotive/steam/repositories/filesystem/content_entry.rb
+41
-13
| @@ | @@ -3,48 +3,76 @@ module Locomotive |
| module Repositories | |
| module Filesystem | |
| - | class ContentEntry < Struct.new(:site) |
| + | class ContentEntry < Struct.new(:loader, :site, :current_locale) |
| + | include Concerns::Queryable |
| + | |
| + | set_collection model: Filesystem::Models::ContentEntry, sanitizer: Filesystem::Sanitizers::ContentEntry |
| + | |
| + | # Engine: ??? |
| def all(type, conditions = {}) | |
| - | # TODO |
| - | raise 'TODO all' |
| + | conditions ||= {} |
| + | |
| + | # TODO: order_by goes here (get settings from the type) |
| + | |
| + | query(type) do |
| + | where(conditions.merge(_visible: true)).order_by(conditions.delete(:order_by)) |
| + | end.all |
| + | end |
| + | |
| + | # Engine: entry.name :-) |
| + | def value_for(name, entry, conditions = {}) |
| + | value = entry.send(name) |
| + | |
| + | if value.respond_to?(:association) |
| + | association(value, conditions || {}) |
| + | else |
| + | value |
| + | end |
| end | |
| - | def filter(association, conditions = {}) |
| + | # Note: |
| + | def association(metadata, conditions = {}) |
| # only visible entries | |
| # conditions[:_visible] = true | |
| # order_by = conditions.delete(:order_by).try(:split) | |
| # association.filtered(conditions, order_by) | |
| - | |
| raise 'TODO filter' | |
| end | |
| + | # Engine: entry.next |
| def next(entry) | |
| - | # entry.next |
| raise 'TODO next' | |
| end | |
| + | # Engine: entry.previous |
| def previous(entry) | |
| - | # entry.previous |
| raise 'TODO previous' | |
| end | |
| + | # Engine: content_type.entries.klass.send(:group_by_select_option, name, content_type.order_by_definition) |
| def group_by_select_option(type, name) | |
| - | # klass = content_type.entries.klass |
| - | # order = content_type.order_by_definition |
| - | |
| - | # klass.send(:group_by_select_option, name, order) |
| raise 'TODO group_by_select_option' | |
| end | |
| + | # Engine: content_type.entries.klass.send(:"#{name}_options").map { |option| option['name'] } |
| def select_options(type, name) | |
| - | # klass = content_type.entries.klass |
| - | # klass.send(:"#{name}_options").map { |option| option['name'] } |
| raise 'TODO select_options' | |
| end | |
| + | private |
| + | |
| + | def memoized_collection(content_type) |
| + | slug = content_type.slug |
| + | @collections ||= {} |
| + | |
| + | return @collections[slug] if @collections[slug] |
| + | |
| + | @collections[slug] = collection(content_type) |
| + | end |
| + | |
| end | |
| end | |
locomotive/steam/repositories/filesystem/memory_adapter/query.rb b/lib/locomotive/steam/repositories/filesystem/memory_adapter/query.rb
+1
-1
| @@ | @@ -39,7 +39,7 @@ module Locomotive |
| end | |
| def order_by(order_string) | |
| - | @sorting = order_string.downcase.split.map(&:to_sym) unless order_string.empty? |
| + | @sorting = order_string.downcase.split.map(&:to_sym) unless order_string.blank? |
| self | |
| end | |
locomotive/steam/repositories/filesystem/models/base.rb b/lib/locomotive/steam/repositories/filesystem/models/base.rb
+1
-1
| @@ | @@ -14,7 +14,7 @@ module Locomotive |
| def method_missing(name, *args, &block) | |
| if attributes.include?(name) | |
| - | attributes[name.to_sym] |
| + | self[name] |
| else | |
| super | |
| end | |
locomotive/steam/repositories/filesystem/models/content_entry.rb b/lib/locomotive/steam/repositories/filesystem/models/content_entry.rb
+79
-0
| @@ | @@ -0,0 +1,79 @@ |
| + | require 'chronic' |
| + | |
| + | module Locomotive |
| + | module Steam |
| + | module Repositories |
| + | module Filesystem |
| + | module Models |
| + | |
| + | class ContentEntry < Base |
| + | |
| + | set_localized_attributes [:_id, :_slug, :seo_title, :meta_description, :meta_keywords] |
| + | |
| + | attr_accessor :content_type |
| + | |
| + | def initialize(attributes = {}) |
| + | super({ |
| + | _visible: true, |
| + | _position: 0 |
| + | }.merge(attributes)) |
| + | end |
| + | |
| + | def _slug; self[:_slug]; end |
| + | alias :_id :_slug |
| + | alias :_permalink :_slug |
| + | |
| + | def _label |
| + | self[content_type.label_field_name] |
| + | end |
| + | |
| + | def [](name) |
| + | is_dynamic_attribute?(name) ? cast_value(name) : super |
| + | end |
| + | |
| + | def localized_attributes |
| + | self.class.localized_attributes + content_type.localized_fields_names |
| + | end |
| + | |
| + | private |
| + | |
| + | def is_dynamic_attribute?(name) |
| + | content_type.fields_by_name.has_key?(name) |
| + | end |
| + | |
| + | def cast_value(name) |
| + | case (field = content_type.fields_by_name[name]).type |
| + | when :integer then _cast_value(name, &:to_i) |
| + | when :float then _cast_value(name, &:to_f) |
| + | when :date then _cast_value(name) { |v| v.is_a?(String) ? Chronic.parse(v).to_date : v } |
| + | when :date_time then _cast_value(name) { |v| v.is_a?(String) ? Chronic.parse(v).to_datetime : v } |
| + | when :file then _cast_value(name) { |v| v.present? ? { 'url' => v } : nil } |
| + | when :belongs_to, :has_many, :many_to_many |
| + | AssociationMetadata.new(field.type, self, field, [*attributes[name]]) |
| + | else |
| + | attributes[name] |
| + | end |
| + | rescue Exception => e |
| + | Locomotive::Common::Logger.info "[#{content_type.slug}][#{_label}] Unable to cast the \"#{name}\" field, reason: #{e.message}".yellow |
| + | nil |
| + | end |
| + | |
| + | def _cast_value(name, &block) |
| + | if (value = attributes[name]).is_a?(Hash) |
| + | value.each { |l, _value| value[l] = yield(_value) } |
| + | else |
| + | yield(value) |
| + | end |
| + | end |
| + | |
| + | class AssociationMetadata < Struct.new(:type, :source, :field, :target_slugs) |
| + | def association; true; end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/repositories/filesystem/models/content_type.rb b/lib/locomotive/steam/repositories/filesystem/models/content_type.rb
+14
-0
| @@ | @@ -6,6 +6,20 @@ module Locomotive |
| class ContentType < Base | |
| + | attr_accessor :fields, :fields_by_name |
| + | |
| + | def label_field_name |
| + | (self[:label_field_name] || fields.first.name).to_sym |
| + | end |
| + | |
| + | def localized_fields_names |
| + | query_fields { where(localized: true) }.all.map(&:name) |
| + | end |
| + | |
| + | def query_fields(&block) |
| + | Filesystem::MemoryAdapter::Query.new(fields, &block) |
| + | end |
| + | |
| end | |
| end | |
locomotive/steam/repositories/filesystem/models/content_type_field.rb b/lib/locomotive/steam/repositories/filesystem/models/content_type_field.rb
+2
-1
| @@ | @@ -8,7 +8,8 @@ module Locomotive |
| def initialize(attributes) | |
| super({ | |
| - | type: :string |
| + | type: :string, |
| + | localized: false |
| }.merge(attributes)) | |
| end | |
locomotive/steam/repositories/filesystem/models/page.rb b/lib/locomotive/steam/repositories/filesystem/models/page.rb
+1
-1
| @@ | @@ -6,7 +6,7 @@ module Locomotive |
| class Page < Base | |
| - | set_localized_attributes [:title, :slug, :permalink, :editable_elements, :template, :template_path, :fullpath, :seo, :meta_description, :meta_keywords] |
| + | set_localized_attributes [:title, :slug, :permalink, :editable_elements, :template, :template_path, :fullpath, :seo_title, :meta_description, :meta_keywords] |
| attr_accessor :depth, :_fullpath | |
locomotive/steam/repositories/filesystem/models/site.rb b/lib/locomotive/steam/repositories/filesystem/models/site.rb
+1
-1
| @@ | @@ -6,7 +6,7 @@ module Locomotive |
| class Site < Base | |
| - | set_localized_attributes [:seo, :meta_description, :meta_keywords] |
| + | set_localized_attributes [:seo_title, :meta_description, :meta_keywords] |
| attr_accessor :root_path | |
locomotive/steam/repositories/filesystem/sanitizers/content_entry.rb b/lib/locomotive/steam/repositories/filesystem/sanitizers/content_entry.rb
+66
-0
| @@ | @@ -0,0 +1,66 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Repositories |
| + | module Filesystem |
| + | module Sanitizers |
| + | |
| + | class ContentEntry < Struct.new(:default_locale, :locales) |
| + | |
| + | def apply_to(collection) |
| + | collection.each do |entry| |
| + | set_content_type(entry) |
| + | add_label(entry) |
| + | set_slug(entry, collection) |
| + | end |
| + | end |
| + | |
| + | def set_slug(entry, collection) |
| + | if entry._label.is_a?(Hash) |
| + | entry[:_slug] ||= {} |
| + | entry._label.each do |locale, label| |
| + | entry[:_slug][locale] ||= slugify(label, collection, locale) |
| + | end |
| + | else |
| + | entry[:_slug] ||= slugify(entry._label, collection) |
| + | end |
| + | end |
| + | |
| + | def slugify(label, collection, locale = nil) |
| + | base, index = label.singularize.parameterize('-'), nil |
| + | _slugify = -> (i) { [base, i].compact.join('-') } |
| + | |
| + | while !is_slug_unique?(_slugify.call(index), collection, locale) |
| + | index += 1 |
| + | end |
| + | |
| + | _slugify.call(index) |
| + | end |
| + | |
| + | def is_slug_unique?(slug, collection, locale) |
| + | Filesystem::MemoryAdapter::Query.new(collection, locale) do |
| + | where(_slug: slug) |
| + | end.first.nil? |
| + | end |
| + | |
| + | def set_content_type(entry) |
| + | entry.content_type = entry.attributes.delete(:content_type) |
| + | end |
| + | |
| + | def add_label(entry) |
| + | value = entry.attributes.delete(:_label) |
| + | name = entry.content_type.label_field_name |
| + | |
| + | if entry.attributes[name].is_a?(Hash) # localized? |
| + | entry.attributes[name][default_locale] = value |
| + | else |
| + | entry.attributes[name] = value |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/repositories/filesystem/sanitizers/content_type.rb b/lib/locomotive/steam/repositories/filesystem/sanitizers/content_type.rb
+14
-2
| @@ | @@ -8,9 +8,11 @@ module Locomotive |
| def apply_to(collection) | |
| collection.each do |content_type| | |
| - | if list = content_type.fields |
| - | content_type[:fields] = build_fields(list) |
| + | if list = content_type.attributes[:fields] |
| + | content_type[:slug] = content_type[:slug].to_s |
| + | content_type.fields = build_fields(list) |
| end | |
| + | build_fields_by_name_shortcut(content_type) |
| end | |
| end | |
| @@ | @@ -24,10 +26,20 @@ module Locomotive |
| _attributes[:label] = name.to_s.humanize | |
| end | |
| + | _attributes[:type] = _attributes[:type].to_sym |
| + | |
| Filesystem::Models::ContentTypeField.new(_attributes) | |
| end | |
| end | |
| + | def build_fields_by_name_shortcut(content_type) |
| + | content_type.fields_by_name = {} |
| + | |
| + | (content_type.fields || []).each do |field| |
| + | content_type.fields_by_name[field.name] = field |
| + | end |
| + | end |
| + | |
| end | |
| end | |
locomotive/steam/repositories/filesystem/yaml_loaders/content_entry.rb b/lib/locomotive/steam/repositories/filesystem/yaml_loaders/content_entry.rb
+45
-0
| @@ | @@ -0,0 +1,45 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Repositories |
| + | module Filesystem |
| + | module YAMLLoaders |
| + | |
| + | class ContentEntry < Struct.new(:root_path, :cache) |
| + | |
| + | include YAMLLoaders::Concerns::Common |
| + | |
| + | def list_of_attributes(content_type) |
| + | cache.fetch("data/#{content_type.slug}") { load_list(content_type) } |
| + | end |
| + | |
| + | private |
| + | |
| + | def load_list(content_type) |
| + | [].tap do |list| |
| + | each(content_type.slug) do |label, attributes, position| |
| + | default = { content_type: content_type, _position: position, _label: label.to_s } |
| + | list << default.merge(attributes) |
| + | end |
| + | end |
| + | end |
| + | |
| + | def each(slug, &block) |
| + | position = 0 |
| + | load(File.join(path, "#{slug}.yml")).each do |element| |
| + | label, attributes = element.keys.first, element.values.first |
| + | yield(label, attributes, position) |
| + | position += 1 |
| + | end |
| + | end |
| + | |
| + | def path |
| + | File.join(root_path, 'data') |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
locomotivecms_steam.gemspec
+1
-0
| @@ | @@ -23,6 +23,7 @@ Gem::Specification.new do |spec| |
| spec.add_dependency 'stringex', '~> 2.5.2' | |
| spec.add_dependency 'morphine', '~> 0.1.1' | |
| spec.add_dependency 'httparty', '~> 0.13.3' | |
| + | spec.add_dependency 'chronic', '~> 0.10.2' |
| spec.add_dependency 'rack-cache', '~> 1.2' | |
| spec.add_dependency 'dragonfly', '~> 1.0.7' | |
spec/unit/repositories/filesystem/content_entry_spec.rb
+81
-0
| @@ | @@ -0,0 +1,81 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Repositories::Filesystem::ContentEntry do |
| + | |
| + | # let(:fields) { [{ title: { hint: 'Title of the article' } }, { author: { type: 'string', label: 'Fullname of the author' } }] } |
| + | let(:type) { instance_double('Articles', slug: 'articles', label_field_name: :title, localized_fields_names: [:title], fields_by_name: { title: instance_double('Field', type: :string) }) } |
| + | let(:loader) { instance_double('Loader', list_of_attributes: [{ content_type: type, _position: 0, _label: 'Update #1', title: { fr: 'Mise a jour #1' }, text: { en: 'added some free stuff', fr: 'phrase FR' }, date: '2009/05/12', category: 'General' }]) } |
| + | let(:site) { instance_double('Site', default_locale: :en, locales: [:en, :fr]) } |
| + | let(:locale) { :en } |
| + | |
| + | let(:repository) { Locomotive::Steam::Repositories::Filesystem::ContentEntry.new(loader, site, locale) } |
| + | |
| + | describe '#collection' do |
| + | |
| + | subject { repository.send(:collection, type) } |
| + | |
| + | it { expect(subject.size).to eq 1 } |
| + | |
| + | describe 'once after the sanitizer has been applied' do |
| + | |
| + | subject { repository.send(:collection, type).first } |
| + | |
| + | it { expect(subject.class).to eq Locomotive::Steam::Repositories::Filesystem::Models::ContentEntry } |
| + | it { expect(subject.title).to eq({ en: 'Update #1', fr: 'Mise a jour #1' }) } |
| + | it { expect(subject._slug).to eq({ en: 'update-1', fr: 'mise-a-jour-1' }) } |
| + | it { expect(subject.content_type).to eq type } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#value_for' do |
| + | |
| + | let(:name) { :title } |
| + | let(:entry) { instance_double('Article', title: 'Hello world') } |
| + | |
| + | subject { repository.value_for(name, entry) } |
| + | |
| + | it { is_expected.to eq 'Hello world' } |
| + | |
| + | context 'association' do |
| + | |
| + | # TODO |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#all' do |
| + | |
| + | let(:conditions) { nil } |
| + | subject { repository.all(type, conditions) } |
| + | |
| + | it { expect(subject.size).to eq 1 } |
| + | |
| + | end |
| + | |
| + | # describe '#by_slug' do |
| + | |
| + | # let(:slug) { nil } |
| + | # subject { repository.by_slug(slug) } |
| + | |
| + | # it { is_expected.to eq nil } |
| + | |
| + | # context 'existing content type' do |
| + | |
| + | # let(:slug) { 'articles' } |
| + | # it { expect(subject.name).to eq 'Articles' } |
| + | |
| + | # end |
| + | |
| + | # context 'slug is already a content type' do |
| + | |
| + | # let(:slug) { instance_double('ContentType') } |
| + | # it { is_expected.to eq slug } |
| + | |
| + | # end |
| + | |
| + | # end |
| + | |
| + | end |
spec/unit/repositories/filesystem/content_type_spec.rb
+2
-0
| @@ | @@ -17,7 +17,9 @@ describe Locomotive::Steam::Repositories::Filesystem::ContentType do |
| it 'applies the sanitizer' do | |
| expect(subject.name).to eq('Articles') | |
| + | expect(subject.slug).to eq('articles') |
| expect(subject.fields.size).to eq 2 | |
| + | expect(subject.fields_by_name.size).to eq 2 |
| end | |
| describe 'a field of the first element' do | |
spec/unit/repositories/filesystem/models/content_entry_spec.rb
+133
-0
| @@ | @@ -0,0 +1,133 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Repositories::Filesystem::Models::ContentEntry do |
| + | |
| + | let(:type) { instance_double('ContentType', slug: 'articles', label_field_name: :title, localized_fields_names: [:title], fields_by_name: {}) } |
| + | let(:attributes) { { title: 'Hello world', _slug: 'hello-world' } } |
| + | let(:content_entry) do |
| + | Locomotive::Steam::Repositories::Filesystem::Models::ContentEntry.new(attributes).tap do |entry| |
| + | entry.content_type = type |
| + | end |
| + | end |
| + | |
| + | describe '#_label' do |
| + | |
| + | subject { content_entry._label } |
| + | it { is_expected.to eq 'Hello world' } |
| + | |
| + | end |
| + | |
| + | describe '#_id' do |
| + | |
| + | subject { content_entry._id } |
| + | it { is_expected.to eq 'hello-world' } |
| + | |
| + | end |
| + | |
| + | describe '#localized_attributes' do |
| + | |
| + | subject { content_entry.localized_attributes } |
| + | it { is_expected.to include :seo_title } |
| + | it { is_expected.to include :title } |
| + | it { is_expected.to include :_slug } |
| + | |
| + | end |
| + | |
| + | describe 'dynamic attributes' do |
| + | |
| + | let(:field_type) { :string } |
| + | let(:attributes) { { my_field: value } } |
| + | let(:field) { instance_double('Field', type: field_type) } |
| + | before { allow(type).to receive(:fields_by_name).and_return(my_field: field) } |
| + | |
| + | subject { content_entry.my_field } |
| + | |
| + | describe 'unable to cast it' do |
| + | |
| + | let(:field_type) { :float } |
| + | let(:value) { [] } |
| + | it { is_expected.to eq nil } |
| + | |
| + | end |
| + | |
| + | context 'a string' do |
| + | let(:value) { 'Hello world' } |
| + | it { is_expected.to eq 'Hello world' } |
| + | context 'localized' do |
| + | let(:value) { { en: 'Hello world', fr: 'Bonjour monde' } } |
| + | it { is_expected.to eq({ en: 'Hello world', fr: 'Bonjour monde' }) } |
| + | end |
| + | end |
| + | |
| + | context 'an integer' do |
| + | let(:field_type) { :integer } |
| + | let(:value) { '42' } |
| + | it { is_expected.to eq 42 } |
| + | context 'localized' do |
| + | let(:value) { { en: 42, fr: '42' } } |
| + | it { is_expected.to eq({ en: 42, fr: 42 }) } |
| + | end |
| + | end |
| + | |
| + | context 'a float' do |
| + | let(:field_type) { :float } |
| + | let(:value) { '42.0' } |
| + | it { is_expected.to eq 42.0 } |
| + | context 'localized' do |
| + | let(:value) { { en: 42.0, fr: '42.0' } } |
| + | it { is_expected.to eq({ en: 42.0, fr: 42.0 }) } |
| + | end |
| + | end |
| + | |
| + | context 'a date' do |
| + | let(:field_type) { :date } |
| + | let(:value) { '2007/06/29' } |
| + | let(:date) { Date.parse('2007/06/29') } |
| + | it { is_expected.to eq date } |
| + | context 'localized' do |
| + | let(:value) { { en: '2007/06/29', fr: date } } |
| + | it { is_expected.to eq({ en: date, fr: date }) } |
| + | end |
| + | end |
| + | |
| + | context 'a date time' do |
| + | let(:field_type) { :date } |
| + | let(:value) { '2007/06/29 00:00:00' } |
| + | let(:datetime) { DateTime.parse('2007/06/29 00:00:00') } |
| + | it { is_expected.to eq datetime } |
| + | context 'localized' do |
| + | let(:value) { { en: '2007/06/29 00:00:00', fr: datetime } } |
| + | it { is_expected.to eq({ en: datetime, fr: datetime }) } |
| + | end |
| + | end |
| + | |
| + | context 'a belongs_to relationship' do |
| + | let(:field_type) { :belongs_to } |
| + | let(:value) { 'john-doe' } |
| + | it { expect(subject.type).to eq :belongs_to } |
| + | it { expect(subject.target_slugs).to eq ['john-doe'] } |
| + | it { expect(subject.source).to eq content_entry } |
| + | it { expect(subject.field).to eq field } |
| + | end |
| + | |
| + | context 'a has_many relationship' do |
| + | let(:field_type) { :has_many } |
| + | let(:value) { nil } |
| + | it { expect(subject.type).to eq :has_many } |
| + | it { expect(subject.target_slugs).to eq [] } |
| + | it { expect(subject.source).to eq content_entry } |
| + | it { expect(subject.field).to eq field } |
| + | end |
| + | |
| + | context 'a many_to_many relationship' do |
| + | let(:field_type) { :many_to_many } |
| + | let(:value) { ['john-doe', 'jane-doe'] } |
| + | it { expect(subject.type).to eq :many_to_many } |
| + | it { expect(subject.target_slugs).to eq ['john-doe', 'jane-doe'] } |
| + | it { expect(subject.source).to eq content_entry } |
| + | it { expect(subject.field).to eq field } |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
spec/unit/repositories/filesystem/models/content_type_spec.rb
+42
-0
| @@ | @@ -0,0 +1,42 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Repositories::Filesystem::Models::ContentType do |
| + | |
| + | let(:fields) { [instance_double('Field1', label: 'Title', name: 'title'), instance_double('Field2', label: 'Author', name: 'author')] } |
| + | let(:content_type) do |
| + | Locomotive::Steam::Repositories::Filesystem::Models::ContentType.new(name: 'Articles').tap do |type| |
| + | type.fields = fields |
| + | end |
| + | end |
| + | |
| + | describe '#field_by_name' do |
| + | |
| + | let(:name) { nil } |
| + | subject { content_type.field_by_name(name) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | context 'not nil name' do |
| + | |
| + | let(:name) { 'author' } |
| + | it { expect(subject.label).to eq 'Author' } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#label_field' do |
| + | |
| + | subject { content_type.label_field.try(:label) } |
| + | it { is_expected.to eq 'Title' } |
| + | |
| + | context 'defined within the content type itself' do |
| + | |
| + | before { allow(content_type.attributes).to receive(:[]).with(:label_field_name).and_return('author') } |
| + | it { is_expected.to eq 'Author' } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
spec/unit/repositories/filesystem/yaml_loaders/content_entry_spec.rb
+22
-0
| @@ | @@ -0,0 +1,22 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::ContentEntry do |
| + | |
| + | let(:root_path) { default_fixture_site_path } |
| + | let(:cache) { NoCacheStore.new } |
| + | let(:content_type) { instance_double('Articles', slug: 'bands') } |
| + | let(:loader) { Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::ContentEntry.new(root_path, cache) } |
| + | |
| + | describe '#list_of_attributes' do |
| + | |
| + | subject { loader.list_of_attributes(content_type).sort { |a, b| a[:_label] <=> b[:_label] } } |
| + | |
| + | it 'tests various stuff' do |
| + | expect(subject.size).to eq 3 |
| + | expect(subject.first[:_label]).to eq 'Alice in Chains' |
| + | expect(subject.first.content_type).to eq content_type |
| + | end |
| + | |
| + | end |
| + | |
| + | end |