Skip to content

Commit

Permalink
Many-linked associations pass specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
seancribbs committed Jul 29, 2010
1 parent 1d6030e commit a83255f
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 6 deletions.
45 changes: 43 additions & 2 deletions ripple/lib/ripple/associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def initialize(type, name, options={})
@type, @name, @options = type, name, options.to_options
end

# @return String The class name of the associated object(s)
def class_name
@class_name ||= case
when @options[:class_name]
Expand All @@ -123,38 +124,78 @@ def class_name
end
end

# @return [Class] The class of the associated object(s)
def klass
@klass ||= options[:class] || class_name.constantize
end

# @return [true,false] Is the cardinality of the association > 1
def many?
@type == :many
end

# @return [true,false] Is the cardinality of the association == 1
def one?
@type == :one
end

# @return [true,false] Is the associated class an EmbeddedDocument
def embeddable?
klass.embeddable?
end

# TODO: Polymorphic not supported
# @return [true,false] Does the association support more than one associated class
def polymorphic?
false
end

# @return [true,false] Does the association use links
def linked?
using == :linked
end

# @return [String] the instance variable in the owner where the association will be stored
def ivar
"@_#{name}"
end

# @return [Class] the association proxy class
def proxy_class
@proxy_class ||= proxy_class_name.constantize
end

# @return [String] the class name of the association proxy
def proxy_class_name
@using ||= options[:using] || (embeddable? ? :embedded : :linked)
klass_name = (many? ? 'Many' : 'One') + @using.to_s.camelize + ('Polymorphic' if polymorphic?).to_s + 'Proxy'
klass_name = (many? ? 'Many' : 'One') + using.to_s.camelize + ('Polymorphic' if polymorphic?).to_s + 'Proxy'
"Ripple::Associations::#{klass_name}"
end

# @return [Proc] a filter proc to be used with Enumerable#select for collecting links that belong to this association (only when #linked? is true)
def link_filter
linked? ? lambda {|link| link.tag == link_tag } : lambda {|_| false }
end

# @return [String,nil] when #linked? is true, the tag for outgoing links
def link_tag
linked? ? Array(link_spec).first.tag : nil
end

# @return [Riak::WalkSpec] when #linked? is true, a specification for which links to follow to retrieve the associated documents
def link_spec
# TODO: support transitive linked associations
if linked?
tag = name.to_s
bucket = polymorphic? ? '_' : klass.bucket_name
Riak::WalkSpec.new(:tag => tag, :bucket => bucket)
else
nil
end
end

# @return [Symbol] which method is used for representing the association - currently only supports :embedded and :linked
def using
@using ||= options[:using] || (embeddable? ? :embedded : :linked)
end
end
end
6 changes: 3 additions & 3 deletions ripple/lib/ripple/associations/linked.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ module Linked
def replace(value)
@owner.robject.links -= links
Array(value).compact.each do |doc|
@owner.robject.links << doc.robject.to_link(@reflection.name.to_s)
@owner.robject.links << doc.robject.to_link(@reflection.link_tag)
end
loaded
@target = value
end

protected
def links
@owner.robject.links.select {|l| l.tag == @reflection.name.to_s }
@owner.robject.links.select(&@reflection.link_filter)
end

def robjects
@owner.robject.walk(:tag => @reflection.name.to_s).first
@owner.robject.walk(*Array(@reflection.link_spec)).first || []
rescue
[]
end
Expand Down
2 changes: 1 addition & 1 deletion ripple/spec/ripple/associations/many_linked_proxy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

it "should link-walk to the associated documents when accessing" do
@person.robject.links << @task.robject.to_link("tasks")
@person.robject.should_receive(:walk).and_return([])
@person.robject.should_receive(:walk).with(Riak::WalkSpec.new(:bucket => "tasks", :tag => "tasks")).and_return([])
@person.tasks.should == []
end

Expand Down

0 comments on commit a83255f

Please sign in to comment.