dynamic-active-resource
github.com/arusarka/dynamic-active-resource
DESCRIPTION:
ActiveResource makes connecting to rest resources very easy. However it has one problem and a big one at that. If you try setting the authentication credentials or the site or collection name, element name for the class for the second time it doesn’t work. E.g.
class Person < ActiveResource::Base
self.site = 'http://localhost:9090/'
end
After sometime you change it to
Person.site = ‘org-server/my_proj/’ Person.user = ‘admin’ Person.password = ‘secret’
Then you do
Person.find(:all) => It bombs
This class provides a mechanism by which you can get rid of this problem. Extend DynamicActiveResource::Base class in the actual class itself. Do not extend the extended class from ActiveResource::Base.
E.g.
class Person < DynamicActiveResource::Base end
set the credentials
Person.site = ‘localhost:8080’ Person.user = ‘foo’ Person.password = ‘bar’
Thats it. Now create some objects
asur = Person.new(:name => ‘Asur’, :job => ‘fooling around’, :status => ‘Single and ready 2 mingle’) asur.save
Now change the class attributes
Person.site = ‘org-server/mingle’ Person.collection_name = ‘boring_people’
Now instantiate an object
rakhshas = Person.new(:name => ‘Rakhshas’, :job => ‘eating people’, :status => ‘just woke up and hungry’) rakhshas.save => Voila !!!!!!! it works
CUSTOMIZATIONS
No amount of wrapping can provide very detailed customizations. Either you have a lot of methods that are not being used or there is hardly anything at all. To oversome this problem this module was written to provide only those methods which are common to most active resource objects. However if you want to have a little more control over your active resource objects its very easy. Here’s how you would do it normally
class Person < ActiveResource::Base
def self.count
find(:all).size
end
def occupation
return job if job
'Unemployed'
end
end
To do the same thing, here’s how you do it using this library
class Person < DynamicActiveResource::Base
module DynamicClassSingletonMethods
def count
find(:all).size
end
end
module DynamicClassInstanceMethods
def occupation
return job if job
'Unemployed'
end
end
end
The DynamicClassInstanceMethods will be available as instance methods in the objects created, DynamicClassSingletonMethods will be available as class methods in the class of the object. Also active resource associations are sometimes paginated. So even if you use find(:all), you get only the first few results. To overcome this, include in your DynamicClassSingletonMethods module a method called find_without_pagination. In that method route it to acitve resource find with proper parameters. An example of the method implementation is
module DynamicClassSingletonMethods
def find_without_pagination(*args)
scope = args.slice!(0)
= args.slice!(0) || {}
[:params] ||= {}
[:params].merge!({:page => 'all'})
# call ActiveResource::Base::find with proper options
find(scope, )
end
end
The class level find method will automatically pick up this method if defined as a method in the DynamicClassSingeletonMethod module else it will pass it to find.
ASSOCIATIONS
This gem also provides active record like associations(highly experimental). Right now it provides only two associations - 1) has_many, 2) belongs_to.
1) has_many
Taking the example from above the way it should be done
class Person < DynamicActiveResource::Base
has_many :cars
module DynamicClassSingletonMethods
def count
find(:all).size
end
end
module DynamicClassInstanceMethods
def occupation
return job if job
'Unemployed'
end
def resource_identifier
name()
end
end
end
Next a car class has to be initialized
class Car < DynARBase (alias for DynamicActiveResource::Base, inbuilt in the gem) end
set resource options only at the top level( Person in this case)
Person.site = ‘localhost:8080/’ Person.user = ‘test’ Person.password = ‘secret’
associations take care of setting the site in the children classes automatically you will notice that an additional method resource_identifier() has been defined in the parent class. It would be discussed shortly.
The way associations work is if you do something like
person = Person.find(‘asur’).cars it will hit the url localhost:8080/people/asur/cars.xml
You would notice that its getting the cars for the person with name ‘asur’. It does so because in the Person class a method called resource_identifier has been defined which says that the id is actually name instead of the database id. If the id attribute in the xml is set appropriately (to ‘name’ in this case) then you do not need to define the method.
2) belongs_to
Again, referring to the example above
class Person < DynamicActiveResource::Base
has_many :cars
module DynamicClassSingletonMethods
def count
find(:all).size
end
end
module DynamicClassInstanceMethods
def occupation
return job if job
'Unemployed'
end
def resource_identifier
name()
end
end
end
Next a car class has to be initialized
class Car < DynARBase (alias for DynamicActiveResource::Base)
belongs_to :person
end
Right now belongs_to supports only assocation with a single class. After defining this you automatically have a method ‘person’ available.
car = Car.find(‘WB1234I’) owner = car.person
FEATURES/PROBLEMS:
Only site, element_name, collection_name, user, password attributes of ActiveResource::Base is managed by the wrapper class.
SYNOPSIS:
FIX (code sample of usage)
REQUIREMENTS:
requires active-resource
INSTALL:
sudo gem install arusarka-dynamic-active-resource
LICENSE:
(The MIT License)
Copyright © 2009 Arusarka Haldar
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.