the with_scope liquid tag accepts a slug if querying a belongs_to field
did
committed Sep 26, 2016
commit a2cba33b3e70c3bb1f08465a6e4a75f469a43e85
Showing 5
changed files with
56 additions
and 26 deletions
locomotive/steam/adapters/mongodb.rb b/lib/locomotive/steam/adapters/mongodb.rb
+5
-1
| @@ | @@ -52,7 +52,11 @@ module Locomotive::Steam |
| end | |
| def make_id(id) | |
| - | BSON::ObjectId.from_string(id) |
| + | begin |
| + | BSON::ObjectId.from_string(id) |
| + | rescue BSON::ObjectId::Invalid |
| + | false |
| + | end |
| end | |
| def base_url(mapper, scope, entity = nil) | |
locomotive/steam/repositories/content_entry_repository.rb b/lib/locomotive/steam/repositories/content_entry_repository.rb
+32
-13
| @@ | @@ -22,8 +22,12 @@ module Locomotive |
| default_attribute :content_type, -> (repository) { repository.content_type } | |
| end | |
| - | # this is the starting point of all the next methods |
| + | # this is the starting point of all the next methods. |
| + | # type can be either an instance of the ContentTypeRepository class |
| + | # or the id of a content type. |
| def with(type) | |
| + | type = self.content_type_repository.find(type) if type.is_a?(String) |
| + | |
| self.content_type = type # used for creating the scope | |
| self.scope.context[:content_type] = type | |
| @@ | @@ -131,11 +135,15 @@ module Locomotive |
| end | |
| def prepare_conditions(*conditions) | |
| - | _conditions = Conditions.new(adapter, conditions.first, self.content_type.fields).prepare |
| + | _conditions = Conditions.new(conditions.first, self.content_type.fields, simple_clone).prepare |
| super({ _visible: true }, _conditions) | |
| end | |
| + | def simple_clone |
| + | self.class.new(self.adapter, self.site, self.locale, self.content_type_repository) |
| + | end |
| + | |
| def add_localized_fields_to_mapper(mapper) | |
| unless self.content_type.localized_names.blank? | |
| mapper.localized_attributes(*self.content_type.localized_names) | |
| @@ | @@ -185,10 +193,10 @@ module Locomotive |
| class Conditions | |
| - | def initialize(adapter, conditions = {}, fields) |
| - | @adapter = adapter |
| + | def initialize(conditions = {}, fields, target_repository) |
| @conditions = conditions.try(:with_indifferent_access) || {} | |
| @fields, @operators = fields, {} | |
| + | @target_repository = target_repository |
| @conditions.each do |name, value| | |
| _name, operator = name.to_s.split('.') | |
| @@ | @@ -206,10 +214,10 @@ module Locomotive |
| _prepare(@fields.dates_and_date_times) { |field, value| value_to_date(value, field.type) } | |
| # belongs_to | |
| - | _prepare(@fields.belongs_to) { |field, value| value_to_id(value) } |
| + | _prepare(@fields.belongs_to) { |field, value| value_to_id(value, field.target_id) } |
| # many_to_many | |
| - | _prepare(@fields.many_to_many) { |field, value| values_to_ids(value) } |
| + | _prepare(@fields.many_to_many) { |field, value| values_to_ids(value, field.target_id) } |
| @conditions | |
| end | |
| @@ | @@ -237,16 +245,31 @@ module Locomotive |
| end | |
| end | |
| - | def value_to_id(value) |
| + | def values_to_ids(value, target_id) |
| + | [*value].map { |_value| value_to_id(_value, target_id) } |
| + | end |
| + | |
| + | def value_to_id(value, target_id) |
| _value = if value.is_a?(Hash) | |
| value['_id'] || value[:_id] | |
| elsif value.respond_to?(:each) # array | |
| - | values_to_ids(value) |
| + | values_to_ids(value, target_id) |
| else | |
| value.respond_to?(:_id) ? value._id : value | |
| end | |
| - | @adapter.make_id(_value) |
| + | if (id = @target_repository.adapter.make_id(_value)) == false |
| + | slug_to_id(value, target_id) |
| + | else |
| + | id |
| + | end |
| + | end |
| + | |
| + | def slug_to_id(slug, target_id) |
| + | if _repository = @target_repository.with(target_id) |
| + | _entry = _repository.first { where(_slug: slug).only(:_id) } |
| + | _entry.try(:_id) |
| + | end |
| end | |
| def value_to_date(value, type) | |
| @@ | @@ -259,10 +282,6 @@ module Locomotive |
| type == :date ? _value.to_date : _value.to_datetime | |
| end | |
| - | def values_to_ids(value) |
| - | [*value].map { |_value| value_to_id(_value) } |
| - | end |
| - | |
| end | |
| end | |
spec/integration/repositories/content_entry_repository_spec.rb
+15
-9
| @@ | @@ -7,11 +7,13 @@ describe Locomotive::Steam::ContentEntryRepository do |
| shared_examples_for 'a repository' do | |
| - | let(:site) { Locomotive::Steam::Site.new(_id: site_id, locales: %w(en fr nb)) } |
| - | let(:locale) { :en } |
| - | let(:type_repository) { Locomotive::Steam::ContentTypeRepository.new(adapter, site, locale) } |
| - | let(:repository) { described_class.new(adapter, site, locale, type_repository).with(type) } |
| - | let(:type) { type_repository.by_slug('bands') } |
| + | let(:site) { Locomotive::Steam::Site.new(_id: site_id, locales: %w(en fr nb)) } |
| + | let(:locale) { :en } |
| + | let(:type_repository) { Locomotive::Steam::ContentTypeRepository.new(adapter, site, locale) } |
| + | let(:repository) { described_class.new(adapter, site, locale, type_repository).with(type) } |
| + | let(:type) { type_repository.by_slug('bands') } |
| + | let(:target_type) { type_repository.by_slug('songs') } |
| + | let(:target_repository) { described_class.new(adapter, site, locale, type_repository).with(target_type) } |
| describe '#all' do | |
| subject { repository.all } | |
| @@ | @@ -55,6 +57,11 @@ describe Locomotive::Steam::ContentEntryRepository do |
| it { expect(subject.map { |entry| entry[:name] }).to eq(['Alice in Chains', 'Pearl Jam']) } | |
| end | |
| + | describe 'filter by a belongs_to field' do |
| + | subject { target_repository.all(band: 'the-who') } |
| + | it { expect(subject.map { |entry| entry[:title] }).to eq(['Song #5', 'Song #6']) } |
| + | end |
| + | |
| describe '#group_by_select_option' do | |
| subject { repository.group_by_select_option(:kind) } | |
| it { expect(subject.map { |h| h[:name] }).to eq(%w(grunge rock country)) } | |
| @@ | @@ -73,9 +80,8 @@ describe Locomotive::Steam::ContentEntryRepository do |
| describe '#create' do | |
| - | let(:type) { type_repository.by_slug('songs') } |
| - | let(:attributes) { { title: 'Jeremy', band: 'pearl-jam', short_description: '"Jeremy" is a song by the American rock band Pearl Jam' } } |
| - | let(:entry) { repository.with(type).build(attributes) } |
| + | let(:attributes) { { title: 'Jeremy', band_id: 'pearl-jam', short_description: '"Jeremy" is a song by the American rock band Pearl Jam' } } |
| + | let(:entry) { repository.with(target_type).build(attributes) } |
| subject { repository.create(entry) } | |
| @@ | @@ -89,7 +95,7 @@ describe Locomotive::Steam::ContentEntryRepository do |
| describe '#inc' do | |
| let(:type) { type_repository.by_slug('songs') } | |
| - | let(:attributes) { { title: 'Jeremy', band: 'pearl-jam', short_description: '"Jeremy" is a song by the American rock band Pearl Jam', views: 41 } } |
| + | let(:attributes) { { title: 'Jeremy', band_id: 'pearl-jam', short_description: '"Jeremy" is a song by the American rock band Pearl Jam', views: 41 } } |
| let(:entry) { repository.with(type).build(attributes) } | |
| before { repository.create(entry) } | |
spec/support/mongo.rb
+2
-1
| @@ | @@ -1,3 +1,4 @@ |
| require 'mongo' | |
| - | Mongo::Logger.logger.level = Logger::INFO # DEBUG # INFO |
| + | Mongo::Logger.logger.level = Logger::INFO |
| + | # Mongo::Logger.logger.level = Logger::DEBUG |
spec/unit/repositories/content_entry_repository_spec.rb
+2
-2
| @@ | @@ -407,7 +407,7 @@ describe Locomotive::Steam::ContentEntryRepository do |
| context 'belongs_to fields' do | |
| let(:value) { 42 } | |
| - | let(:field) { instance_double('BelongsToField', name: 'person', persisted_name: 'person_id') } |
| + | let(:field) { instance_double('BelongsToField', name: 'person', persisted_name: 'person_id', target_id: '42') } |
| let(:_fields) { instance_double('Fields', selects: [], belongs_to: [field], many_to_many: [], dates_and_date_times: []) } | |
| let(:conditions) { { 'person' => value } } | |
| @@ | @@ -450,7 +450,7 @@ describe Locomotive::Steam::ContentEntryRepository do |
| context 'many_to_many fields' do | |
| let(:value) { 42 } | |
| - | let(:field) { instance_double('ManyToManyField', name: 'tags', persisted_name: 'tag_ids') } |
| + | let(:field) { instance_double('ManyToManyField', name: 'tags', persisted_name: 'tag_ids', target_id: '42') } |
| let(:_fields) { instance_double('Fields', selects: [], belongs_to: [], many_to_many: [field], dates_and_date_times: []) } | |
| let(:conditions) { { 'tags.in' => value } } | |