Skip to content

Instantly share code, notes, and snippets.

@ulitiy
Created January 28, 2015 22:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ulitiy/b2757646ae6102faa130 to your computer and use it in GitHub Desktop.
Save ulitiy/b2757646ae6102faa130 to your computer and use it in GitHub Desktop.
next/previous locomotive drop
module Locomotive
module Liquid
module Drops
class ContentEntry < Base
delegate :_slug, :_permalink, :_translated, :seo_title, :meta_keywords, :meta_description, to: :@_source
def _id
@_source._id.to_s
end
def _label
@_label ||= @_source._label
end
# Returns the next content for the parent content type.
# If no content is found, nil is returned.
#
# Usage:
#
# {% if article.next %}
# <a href="/articles/{{ article.next._permalink }}">Read next article</a>
# {% endif %}
#
def next
next_or_previous :gt
end
# Returns the previous content for the parent content type.
# If no content is found, nil is returned.
#
# Usage:
#
# {% if article.previous %}
# <a href="/articles/{{ article.previous._permalink }}">Read previous article</a>
# {% endif %}
#
def previous
next_or_previous :lt
end
def next_or_previous matcher
self.modify_with_scope
matcher = matcher == :gt ? :lt : :gt if @_source.content_type.order_direction != 'asc'
attribute = @_source.content_type.order_by_attribute
direction = matcher == :gt ? 'asc' : 'desc'
criterion = attribute.to_sym.send(matcher)
value = @_source.send(attribute.to_sym)
order_by = [attribute, direction]
# throw @context['with_scope']
# @_source.class.where({ _visible: true }.merge(@context['with_scope']).merge({ criterion => value })).limit(1).order_by(order_by).first.to_liquid
@_source.class.where({ _visible: true }.merge({ criterion => value })).limit(1).order_by(order_by).where(@context['with_scope']).first.to_liquid
# ContentTypeProxyCollection.new(@_source.content_type).all.where({ criterion => value }).limit(1).first.to_liquid # no context inside
end
def errors
@_source.errors.messages.to_hash.stringify_keys
end
def before_method(meth)
return '' if @_source.nil?
if not @@forbidden_attributes.include?(meth.to_s)
value = @_source.send(meth)
if value.respond_to?(:all) # check for an association
filter_and_order_list(value)
else
value
end
else
nil
end
end
protected
def filter_and_order_list(list)
conditions, order_by = HashWithIndifferentAccess.new(_visible: true), nil
if @context['with_scope']
conditions.merge!(@context['with_scope'])
order_by = conditions.delete(:order_by).try(:split)
end
list.filtered(conditions, order_by)
end
########### COPIED FROM ContentTypeProxyCollection #########
# Modify the attributes of the with_scope tag so that
# they can be resolved by MongoDB.
#
def modify_with_scope
@context['with_scope'].dup.each do |key, value|
field = @_source.content_type.find_entries_custom_field(key.to_s)
next if field.nil?
case field.type.to_sym
when :belongs_to
self.modify_with_scope_key(key, "#{key.to_s}_id", self.object_to_id(field, value))
when :many_to_many
self.modify_with_scope_key(key, "#{key.to_s.singularize}_ids", self.object_to_id(field, value))
when :select
option = field.select_options.detect { |option| [option.name, option._id.to_s].include?(value) }
self.modify_with_scope_key(key, "#{key.to_s}_id", option.try(:_id))
end
end
end
# Change the value of a key of the with_scope depending of its type.
# If the key is a Origin::Key, we only change the name.
# If the key is a String, we replace it.
#
# @param [ Object ] key Either a String or a Origin::Key
# @param [ String ] name The new name of the key
# @param [ String ] value The new value associated to the key
#
def modify_with_scope_key(key, name, value)
if key.respond_to?(:operator)
key.instance_variable_set :@name, name
@context['with_scope'][key] = value
else
@context['with_scope'].delete(key)
@context['with_scope'][name] = value
end
end
# Get the _id attribute of a object or a list of objects which
# can include String (needed to retrieve a model
# based on its permalink or its label field) or ContentEntry instances.
#
# @param [ Object ] field The custom field
# @param [ Object ] value An object (content entry or label) or a list of objects
#
def object_to_id(field, value)
if value.respond_to?(:map)
value.map { |el| self.object_to_id(field, el) }
elsif value.respond_to?(:_id)
value._id
else
model = Locomotive::ContentType.class_name_to_content_type(field.class_name, @content_type.site)
model.entries.or({ _slug: value }, { model.label_field_name => value }).first.try(:_id)
end
end
#########
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment