lib/spontaneous/plugins/aliases.rb in spontaneous-0.2.0.alpha2 vs lib/spontaneous/plugins/aliases.rb in spontaneous-0.2.0.alpha3

- old
+ new

@@ -4,31 +4,34 @@ module Spontaneous::Plugins module Aliases extend ActiveSupport::Concern included do - many_to_one :target, :class => self, :reciprocal => :aliases - one_to_many :aliases, :class => self, :key => :target_id, :reciprocal => :target + # '__target' rather than 'target' because we want to override the behaviour of the + # Content#target method only on classes that are aliases, and this is defined dynamically + many_to_one :__target, :class => self, :key => :target_id, :reciprocal => :aliases + one_to_many :aliases, :class => self, :key => :target_id, :reciprocal => :__target add_association_dependencies :aliases => :destroy end - # def self.configure(base) - # end module ClassMethods def alias_of(*args) options_list, class_list = args.partition { |e| e.is_a?(Hash) } @alias_options = options_list.first || {} @alias_classes = class_list extend ClassAliasMethods include AliasMethods include PieceAliasMethods unless page? - include PageAliasMethods if page? + include PageAliasMethods if page? + # alias_method :target, :__target + alias_method :target=, :__target= end + alias_method :aliases, :alias_of - def targets(owner = nil, box = nil) + def targets(owner = nil, box = nil, options = {}) targets = [] classes = [] proc_args = [owner, box].compact @alias_classes.each do |source| case source @@ -37,11 +40,11 @@ else classes.concat(source.to_s.constantize.sti_subclasses_array) end end query = S::Content.filter(sti_key => classes.map { |c| c.to_s }) - if container_procs = @alias_options[:container] + if (container_procs = @alias_options[:container]) containers = [container_procs].flatten.map { |p| p[*proc_args] }.flatten params = [] containers.each do |container| if container.is_page? params << Sequel::SQL::BooleanExpression.new(:'=', :page_id, container.id) @@ -55,15 +58,28 @@ end container_query = params[1..-1].inject(params.first) { |q, expr| q = q | expr; q } query = query.and(container_query) end targets.concat(query.all) - if filter = @alias_options[:filter] and filter.is_a?(Proc) - targets.select(&filter) - else - targets + + if (filter = @alias_options[:filter]) and filter.is_a?(Proc) + filtered = [] + targets.each { |target| + filtered << target if filter[*([target, owner, box][0...(filter.arity)])] + } + targets = filtered end + + if @alias_options[:unique] && box + existing = box.map { |entry| entry.target || entry } + targets.reject! { |target| existing.include?(target) } + end + + if (query = options[:search]) + targets.select! { |target| query === target.alias_title } + end + targets end def target_class(class_definition) end @@ -73,25 +89,57 @@ end end # ClassMethods module ClassAliasMethods + def for_target(target_id) + self.create(:target_id => target_id) + end + def alias? true end + + def use_configured_generator(generator_name, *args) + return nil unless @alias_options.key?(generator_name) + (generator = @alias_options[generator_name]).call(*args) + end + + def lookup_target(target_id) + use_configured_generator(:lookup, target_id) + end + + def target_slug(target) + use_configured_generator(:slug, target) + end end # included only in instances that are aliases module AliasMethods def alias? true end + def target + (_target = self.class.lookup_target(self.target_id)) and return _target + __target + end + def field?(field_name) super || target.class.field?(field_name) end + def respond_to_missing?(name, include_private = false) + return true if target && target.respond_to?(name) + super + end + + def respond_to?(name, include_private = false) + return true if target && target.respond_to?(name) + super + end + def method_missing(method, *args) if target && target.respond_to?(method) if block_given? target.__send__(method, *args, &Proc.new) else @@ -106,10 +154,11 @@ def find_named_style(style_name) super or target.find_named_style(style_name) end def style + return self.resolve_style(self.style_sid) unless target.respond_to?(:resolve_style) if self.class.styles.empty? target.resolve_style(style_sid) else self.resolve_style(self.style_sid) or target.resolve_style(self.style_sid) end @@ -118,22 +167,37 @@ def styles @styles ||= Spontaneous::Collections::PrototypeSet.new(target, :styles) end def export(user = nil) - super.merge(:target => target.shallow_export(user), :alias_title => target.alias_title, :alias_icon => target.exported_alias_icon) + super.merge(:target => exported_target(user), :alias_title => target.alias_title, :alias_icon => target.exported_alias_icon) end + def exported_target(user = nil) + case target + when S::Content + target.shallow_export(user) + else + target.to_json + end + end + + def hidden? + super || target.nil? || (target.respond_to?(:hidden?) && target.hidden?) + end end module PieceAliasMethods def path target.path end end module PageAliasMethods def slug + unless target.respond_to?(:slug) + slug = self.class.target_slug(target) and return slug + end target.slug end def layout # if this alias class has no layouts defined, then just use the one set on the target