better to_json handling for content entries and their matching liquid drops (WIP)
did
committed Sep 11, 2015
commit 2eb5ea0821c7ac7eccdf8d35c46d5edbf5f94007
Showing 11
changed files with
161 additions
and 15 deletions
locomotive/steam/decorators/i18n_decorator.rb b/lib/locomotive/steam/decorators/i18n_decorator.rb
+16
-0
| @@ | @@ -84,6 +84,22 @@ module Locomotive |
| end | |
| end | |
| + | def to_hash |
| + | __getobj__.to_hash.tap do |hash| |
| + | @__localized_attributes__.keys.each do |name| |
| + | hash[name.to_s] = __get_localized_value__(name) |
| + | end |
| + | end |
| + | end |
| + | |
| + | def as_json(options = nil) |
| + | to_hash.as_json(options) |
| + | end |
| + | |
| + | def to_json |
| + | as_json.to_json |
| + | end |
| + | |
| #:nocov: | |
| def inspect | |
| "[Decorated #{__getobj__.class.name}][I18n] attributes exist? " + | |
locomotive/steam/liquid/drops/base.rb b/lib/locomotive/steam/liquid/drops/base.rb
+4
-0
| @@ | @@ -28,6 +28,10 @@ module Locomotive |
| records | |
| end | |
| + | def as_json(options = nil) |
| + | @_source.as_json(options) |
| + | end |
| + | |
| protected | |
| def liquify(*records, &block) | |
locomotive/steam/liquid/drops/content_entry_collection.rb b/lib/locomotive/steam/liquid/drops/content_entry_collection.rb
+7
-1
| @@ | @@ -13,7 +13,13 @@ module Locomotive |
| end | |
| def all | |
| - | collection |
| + | collection.map do |entry| |
| + | entry.to_liquid.tap do |drop| |
| + | if drop && drop.respond_to?(:context=) |
| + | drop.context = @context |
| + | end |
| + | end |
| + | end |
| end | |
| def count | |
locomotive/steam/liquid/filters/json.rb b/lib/locomotive/steam/liquid/filters/json.rb
+11
-14
| @@ | @@ -4,19 +4,15 @@ module Locomotive |
| module Filters | |
| module Json | |
| - | def json(input, fields = nil) |
| + | def json(input, fields = []) |
| if fields && fields.is_a?(String) | |
| fields = fields.split(',').map(&:strip) | |
| end | |
| - | if fields.blank? |
| - | input.to_json |
| - | elsif input.respond_to?(:each) |
| - | if fields.size == 1 |
| - | input.map { |object| object[fields.first].to_json }.join(',') |
| - | else |
| - | input.map { |object| "{" + object_to_json(object, fields) + "}" }.join(',') |
| - | end |
| + | if input.respond_to?(:each) |
| + | input.map do |object| |
| + | fields.size == 1 ? object[fields.first].to_json : object_to_json(object, fields) |
| + | end.join(',') |
| else | |
| object_to_json(input, fields) | |
| end | |
| @@ | @@ -25,11 +21,12 @@ module Locomotive |
| protected | |
| def object_to_json(input, fields) | |
| - | [].tap do |output| |
| - | fields.each do |field| |
| - | output << %("#{field}":#{input[field].to_json}) |
| - | end |
| - | end.join(',') |
| + | if input.respond_to?(:as_json) |
| + | options = fields.blank? ? {} : { only: fields } |
| + | input.as_json(options).to_json |
| + | else |
| + | input.to_json |
| + | end |
| end | |
| end | |
locomotive/steam/models.rb b/lib/locomotive/steam/models.rb
+1
-0
| @@ | @@ -1,4 +1,5 @@ |
| require_relative 'models/concerns/validation' | |
| + | require_relative 'models/concerns/to_json' |
| require_relative 'models/i18n_field' | |
| require_relative 'models/associations/embedded' | |
| require_relative 'models/associations/referenced' | |
locomotive/steam/models/concerns/to_json.rb b/lib/locomotive/steam/models/concerns/to_json.rb
+34
-0
| @@ | @@ -0,0 +1,34 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Models |
| + | module Concerns |
| + | |
| + | module ToJson |
| + | |
| + | def to_hash |
| + | {}.tap do |_attributes| |
| + | attributes.each do |key, value| |
| + | next if value && value.respond_to?(:repository) # skip associations |
| + | |
| + | _attributes[key] = (case value |
| + | when Locomotive::Steam::Models::I18nField then value.to_hash |
| + | else value |
| + | end) |
| + | end |
| + | end.stringify_keys |
| + | end |
| + | |
| + | def as_json(options = nil) |
| + | to_hash.as_json(options) |
| + | end |
| + | |
| + | def to_json |
| + | as_json.to_json |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/models/entity.rb b/lib/locomotive/steam/models/entity.rb
+1
-0
| @@ | @@ -4,6 +4,7 @@ module Locomotive::Steam |
| module Entity | |
| include Locomotive::Steam::Models::Concerns::Validation | |
| + | include Locomotive::Steam::Models::Concerns::ToJson |
| attr_accessor :attributes, :associations, :localized_attributes, :base_url | |
locomotive/steam/models/i18n_field.rb b/lib/locomotive/steam/models/i18n_field.rb
+2
-0
| @@ | @@ -36,6 +36,8 @@ module Locomotive::Steam |
| alias :__translations__ :translations | |
| + | alias :to_hash :translations |
| + | |
| def serialize(attributes) | |
| attributes[@name] = @translations | |
| end | |
spec/support/liquid.rb
+4
-0
| @@ | @@ -18,6 +18,10 @@ module Liquid |
| def before_method(meth) | |
| @_source[meth.to_sym] | |
| end | |
| + | |
| + | def as_json(options = nil) |
| + | @_source.as_json(options) |
| + | end |
| end | |
| class SimpleEventsListener | |
spec/unit/decorators/i18n_decorator_spec.rb
+9
-0
| @@ | @@ -83,6 +83,15 @@ describe Locomotive::Steam::Decorators::I18nDecorator do |
| expect(decorated.__locale__).to eq :fr | |
| end | |
| + | describe '#to_hash' do |
| + | |
| + | before { expect(page).to receive(:to_hash).and_return('title' => { 'en' => 'some stuff', 'fr' => 'some stuff' }) } |
| + | subject { decorated.to_hash } |
| + | |
| + | it { expect(subject).to eq('title' => 'Bonjour monde', 'slug' => 'hello-world') } |
| + | |
| + | end |
| + | |
| def i18n_field(name, translations) | |
| Locomotive::Steam::Models::I18nField.new(name, translations) | |
| end | |
spec/unit/models/concerns/to_json_spec.rb
+72
-0
| @@ | @@ -0,0 +1,72 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Models::Concerns::ToJson do |
| + | |
| + | let(:attributes) { {} } |
| + | let(:entity) { SimpleEntity.new(attributes) } |
| + | |
| + | describe '#to_hash' do |
| + | |
| + | subject { entity.to_hash } |
| + | |
| + | it { expect(subject).to eq({}) } |
| + | |
| + | context 'simple attributes' do |
| + | let(:attributes) { { title: 'Hello world', published: true, tags: ['a', 'b'] } } |
| + | it { expect(subject).to eq('title' => 'Hello world', 'published' => true, 'tags' => ['a', 'b']) } |
| + | end |
| + | |
| + | context 'localized attributes' do |
| + | let(:attributes) { { title: Locomotive::Steam::Models::I18nField.new(:title, { fr: 'Bonjour', en: 'Hi' })} } |
| + | it { expect(subject).to eq('title' => { 'fr' => 'Bonjour', 'en' => 'Hi' }) } |
| + | end |
| + | |
| + | context 'referenced associations' do |
| + | let(:attributes) { { title: 'Lorem ipsum', author: instance_double('BelongsToAssociation', repository: true) } } |
| + | it { expect(subject).to eq('title' => 'Lorem ipsum') } |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#as_json' do |
| + | |
| + | let(:options) { nil } |
| + | |
| + | subject { entity.as_json(options) } |
| + | |
| + | it { expect(subject).to eq({}) } |
| + | |
| + | context 'with options' do |
| + | |
| + | let(:options) { { only: ['title'] } } |
| + | let(:attributes) { { title: 'Hello world', body: 'Lorem ipsum' } } |
| + | |
| + | it { expect(subject).to eq('title' => 'Hello world') } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe '#to_json' do |
| + | |
| + | subject { entity.to_json } |
| + | |
| + | it { expect(subject).to eq('{}') } |
| + | |
| + | context 'with attributes' do |
| + | |
| + | let(:attributes) { { title: 'Hello world', published: true } } |
| + | |
| + | it { expect(subject).to eq(%{{"title":"Hello world","published":true}}) } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | class SimpleEntity |
| + | include Locomotive::Steam::Models::Concerns::ToJson |
| + | attr_reader :attributes |
| + | def initialize(attributes = {}); @attributes = attributes; end |
| + | end |
| + | |
| + | end |