forked from activeadmin/activeadmin
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extracted ResourceCollection from methods on ActiveAdmin::Namespace
- Loading branch information
Showing
7 changed files
with
208 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
module ActiveAdmin | ||
|
||
class ResourceMismatchError < StandardError; end | ||
|
||
# Holds on to a collection of Resources. Is an Enumerable object | ||
# so it has some Array like qualities. | ||
# | ||
# Adding a resource assumes that the object responds to #resource_key | ||
class ResourceCollection | ||
include Enumerable | ||
|
||
def initialize | ||
@resource_hash = {} | ||
end | ||
|
||
# Add a new resource to the collection. If the resource_key already | ||
# exists, the exiting resource is returned. | ||
# | ||
# @param [Resource, Page] resource The resource to add to the collection | ||
# | ||
# @returns [Resource, Page] Either the existing resource or the new one | ||
def add(resource) | ||
if has_key?(resource.resource_key) | ||
existing_resource = find_by_key(resource.resource_key) | ||
ensure_resource_classes_match!(existing_resource, resource) | ||
existing_resource | ||
else | ||
@resource_hash[resource.resource_key] = resource | ||
end | ||
end | ||
|
||
# @returns [Array] An array of all the resources | ||
def resources | ||
@resource_hash.values | ||
end | ||
|
||
# For enumerable | ||
def each(&block) | ||
@resource_hash.values.each(&block) | ||
end | ||
|
||
# @returns [Array] An array of all the keys registered in the collection | ||
def keys | ||
@resource_hash.keys | ||
end | ||
|
||
# @returns [Boolean] If the key has been registered in the collection | ||
def has_key?(resource_key) | ||
@resource_hash.has_key?(resource_key) | ||
end | ||
|
||
# Finds a resource by a given key | ||
def find_by_key(resource_key) | ||
@resource_hash[resource_key] | ||
end | ||
|
||
# Finds a resource based on it's class. Looks up the class Heirarchy if its | ||
# a subclass of an Active Record class (ie: implementes base_class) | ||
def find_by_resource_class(resource_class) | ||
resource_class_name = resource_class.to_s | ||
match = resources_with_a_resource_class.find{|r| r.resource.to_s == resource_class_name } | ||
return match if match | ||
|
||
if resource_class.respond_to?(:base_class) | ||
base_class_name = resource_class.base_class.to_s | ||
resources_with_a_resource_class.find{|r| r.resource.to_s == base_class_name } | ||
else | ||
nil | ||
end | ||
end | ||
|
||
private | ||
|
||
def resources_with_a_resource_class | ||
select{|resource| resource.respond_to?(:resource) } | ||
end | ||
|
||
def ensure_resource_classes_match!(existing_resource, resource) | ||
return unless existing_resource.respond_to?(:resource) && resource.respond_to?(:resource) | ||
|
||
if existing_resource.resource != resource.resource | ||
raise ActiveAdmin::ResourceMismatchError, | ||
"Tried to register #{resource.resource} as #{resource.resource_key} but already registered to #{existing_resource.resource}" | ||
end | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
require 'spec_helper' | ||
require 'active_admin/resource_collection' | ||
|
||
include ActiveAdmin | ||
|
||
describe ActiveAdmin::ResourceCollection do | ||
|
||
let(:collection){ ResourceCollection.new } | ||
|
||
it "should have no resources when new" do | ||
collection.resources.should == [] | ||
end | ||
|
||
it "should be enumerable" do | ||
resource = mock(:resource_key => "MyResource") | ||
collection.add(resource) | ||
collection.each{|r| r.should == resource } | ||
end | ||
|
||
it "should return the available keys" do | ||
resource = mock(:resource_key => "MyResource") | ||
collection.add resource | ||
collection.keys.should == [resource.resource_key] | ||
end | ||
|
||
describe "adding a new resource" do | ||
let(:resource){ mock(:resource_key => "MyResource") } | ||
|
||
it "should return the resource" do | ||
collection.add(resource).should == resource | ||
end | ||
|
||
it "should add a new resource" do | ||
collection.add(resource) | ||
collection.resources.should == [resource] | ||
end | ||
|
||
it "should be available by name" do | ||
collection.add(resource) | ||
collection.find_by_key(resource.resource_key).should == resource | ||
end | ||
end | ||
|
||
describe "adding a new resource when the key already exists" do | ||
let(:stored_resource){ mock(:resource_key => "MyResource") } | ||
let(:resource){ mock(:resource_key => "MyResource") } | ||
|
||
before do | ||
collection.add(stored_resource) | ||
end | ||
|
||
it "should return the original resource" do | ||
collection.add(resource).should == stored_resource | ||
end | ||
|
||
it "should not add a new resource" do | ||
collection.add(resource) | ||
collection.resources.should == [stored_resource] | ||
end | ||
end | ||
|
||
describe "adding an existing resource key with a different resource class" do | ||
let(:stored_resource){ mock(:resource_key => "MyResource", :resource => mock) } | ||
let(:resource){ mock(:resource_key => "MyResource", :resource => mock) } | ||
|
||
it "should raise a ActiveAdmin::ResourceMismatchError" do | ||
collection.add(stored_resource) | ||
lambda { | ||
collection.add(resource) | ||
}.should raise_error(ActiveAdmin::ResourceMismatchError) | ||
end | ||
|
||
end | ||
|
||
describe "#find_by_resource_class" do | ||
|
||
let(:base_class){ mock(:to_s => "BaseClass")} | ||
let(:resource_from_base_class){ mock(:resource_key => "MyBaseClassResource", :resource => base_class )} | ||
let(:resource_class){ mock(:base_class => base_class, :to_s => "ResourceClass") } | ||
let(:resource){ mock(:resource_key => "MyResource", :resource => resource_class) } | ||
|
||
it "should find a resource when it's in the collection" do | ||
collection.add resource | ||
collection.find_by_resource_class(resource_class).should == resource | ||
end | ||
|
||
it "should return nil when the resource class is not in the collection" do | ||
collection.find_by_resource_class(resource_class).should == nil | ||
end | ||
|
||
it "should return the resource when it and it's base class is in the collection" do | ||
collection.add resource_from_base_class | ||
collection.find_by_resource_class(resource_class).should == resource_from_base_class | ||
end | ||
|
||
it "should return nil the resource_class does not repond to base_class and it's not in the collection" do | ||
collection.find_by_resource_class(mock).should == nil | ||
end | ||
end | ||
|
||
end |