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