diff --git a/README b/README
index deabb73..0407694 100644
--- a/README
+++ b/README
@@ -38,6 +38,7 @@ These are the features that have been added to HyRes.
* Active Record-like #load that doesn't #dup attributes (stores direct reference)
* reload that does a full clear/fetch to reload (also clears associations
cache!)
+ * now not only extract xml child but also xml attribute
== Callbacks
@@ -61,6 +62,7 @@ These are the features that have been added to HyRes.
* no 404-explosion for collection-finders that don't return anything They
just return nil (just like Active Record). This includes finders for
associations eg User.posts will return nil if the user hasn't any.
+ * add :post, :put and :delete options at find
=== Validations
@@ -118,6 +120,11 @@ Currently:
because (obviously) we're not using SQL...
* it's possible to still pass in :params => {:conditions => ...} (ie old
code shouldn't break) but it's not essential anymore (too complicated).
+
+if your api not restful enough you can custom find by option :post, :put and :delete
+Brands.find(:all, :from => '/brands/search.xml', :post => 'EUR')
+will send 'EUR' with method post to yoursite+'/brands/search.xml'
+and parse xml result
@@ -396,51 +403,21 @@ Currently in progress (ie awaiting discussion on RailsCore):
0) Testing!
-1) proper callbacks for before/after save/create/validate etc rather than
- bodgied-up functions called directly in the code
+1) more customizable
-2) MyModel.with_scope
+2) if method post or put and using methods 'find_by' automatically create xml data to send to API
-3) find(:include => ...)
-4) attr_protected/attr_accessible
-
-5) MyModel.calculate/average/minimum/maximum etc
-
-6) reflections. There should be no reason why we can't re-use
- Active Record-style reflections for our associations. They are not
- SQL-specific. This will also allow a lot more code to automatically Just
- Work (eg an Active Record could use "has_many :through" a HyRes)
-
-7) Split HyRes into Base and other grouped functions as per AR
-
-8) default_scope (as per AR)
-
-9) validates_associated (as per AR)
-
-10) write_attribute that actually hits the remoteAPI ???
-
-11) a default format for when it doesn't understand how to deal with a given
-mime-formats? One which will just pass back the raw data and let you play
-with it?
-
-12) cache the raw (un-decoded) data onto the object so we don't have to do a
-second fetch? Or at least allow a universal attribute to be set that turns
-on cacheing
-
-13) HABTM - and the reverse (ie AR HABTM HyRes and HyRes HABTM AR)
-
-14) has_many :through - and allowing AR's "through" to work as well
-
-N) merge this stuff back into the real Active Resource (currently underway for Rails 3.0)
+== Copyright and Authorship
+Author:: Ibnul Qoyyim
-== Copyright and Authorship
+Forked from :
-Author:: Taryn East
+Taryn East
Copyright (c) 2009:: White Label Dating [http://whitelabeldating.com]
Based on Work Done by Medical Decision Logic
diff --git a/lib/hyperactive_resource.rb b/lib/hyperactive_resource.rb
index 285c0a9..c818723 100644
--- a/lib/hyperactive_resource.rb
+++ b/lib/hyperactive_resource.rb
@@ -103,7 +103,7 @@ class ResourceNotFound < AbstractRecordError; end
def self.human_name(options = {})
self.name.humanize
end
- # Quick overloading of the ActvieRecord-style naming functions for
+ # Quick overloading of the ActiveRecord-style naming functions for
# attributes in error messages.
# This will be updated when associations are complete
def self.human_attribute_name(attribute_key_name, options = {})
@@ -1026,7 +1026,7 @@ def self.method_missing(method_name, *args )
# the user asked for find! and we found nothing - so raise a
# descriptive exception
- raise ResourceNotFound, "Couldn't find #{self.name} with #{attr_conds.to_a.collect {|pair| "#{pair.first} = #{pair.second}"}.join(', ')}" if match.bang? && results.blank?
+ raise ResourceNotFound, "Couldn't find #{self.name} with " + attr_conds.to_a.collect {|pair| "#{pair.first} = #{pair.second}"}.join(', ') if match.bang? && results.blank?
# otherwise return whatever we found
return results
@@ -1081,12 +1081,31 @@ def self.method_missing(method_name, *args )
def self.find_every(options)
begin
from_value = options.respond_to?(:has_key?) && options.has_key?(:from) ? options.delete(:from) : nil
+ post_value = options.respond_to?(:has_key?) && options.has_key?(:post) ? options.delete(:post) : nil
+ put_value = options.respond_to?(:has_key?) && options.has_key?(:put) ? options.delete(:put) : nil
+ is_delete = options.respond_to?(:has_key?) && options.has_key?(:delete)
case from_value
when Symbol
- instantiate_collection(get(from_value, options[:params]))
+ if !post_value.nil?
+ instantiate_collection(post(from_value, options[:params], post_value))
+ elsif !put_value.nil?
+ instantiate_collection(put(from_value, options[:params], put_value))
+ elsif is_delete
+ instantiate_collection(delete(from_value, options[:params]))
+ else
+ instantiate_collection(get(from_value, options[:params]))
+ end
when String
path = "#{from_value}#{query_string(options[:params])}"
- instantiate_collection(connection.get(path, headers).arrayify)
+ if !post_value.nil?
+ instantiate_collection(format.decode(connection.post(path, post_value, headers).body).arrayify)
+ elsif !put_value.nil?
+ instantiate_collection(format.decode(connection.put(path, put_value, headers).body).arrayify)
+ elsif is_delete
+ instantiate_collection(connection.delete(path, headers).arrayify)
+ else
+ instantiate_collection(connection.get(path, headers).arrayify)
+ end
else
prefix_options, query_options = split_options(options)
suffix_options = query_options.delete(:suffix_options)
diff --git a/lib/parse_xml_attributes_too.rb b/lib/parse_xml_attributes_too.rb
new file mode 100644
index 0000000..fc2b0d6
--- /dev/null
+++ b/lib/parse_xml_attributes_too.rb
@@ -0,0 +1,79 @@
+# USAGE: Hash.from_xml:(YOUR_XML_STRING)
+require 'nokogiri'
+# modified from http://stackoverflow.com/questions/1230741/convert-a-nokogiri-document-to-a-ruby-hash/1231297#1231297
+# EDITED from http://gist.github.com/335286
+
+class Hash
+ class << self
+ alias :from_xml_without_attributes :from_xml
+ def from_xml(xml_io, options = {})
+ begin
+ return from_xml_without_attributes(xml_io) unless options.has_key?(:with_attributes)
+ result = Nokogiri::XML(xml_io)
+ return { result.root.name.to_sym => xml_node_to_hash(result.root)}
+ rescue Exception => e
+ # raise your custom exception here
+ end
+ end
+
+ def xml_node_to_hash(node)
+ # If we are at the root of the document, start the hash
+ if node.element?
+ result_hash = {}
+ if node.attributes != {}
+ result_hash[:attributes] = {}
+ node.attributes.keys.each do |key|
+ result_hash[:attributes][node.attributes[key].name.to_sym] = prepare(node.attributes[key].value)
+ end
+ end
+ if node.children.size > 0
+ node.children.each do |child|
+ result = xml_node_to_hash(child)
+
+ if child.name == "text"
+ unless child.next_sibling || child.previous_sibling
+ return prepare(result)
+ end
+ elsif result_hash[child.name.to_sym]
+ if result_hash[child.name.to_sym].is_a?(Object::Array)
+ result_hash[child.name.to_sym] << prepare(result)
+ else
+ result_hash[child.name.to_sym] = [result_hash[child.name.to_sym]] << prepare(result)
+ end
+ else
+ result_hash[child.name.to_sym] = prepare(result)
+ end
+ end
+
+ return result_hash
+ else
+ return result_hash
+ end
+ else
+ return prepare(node.content.to_s)
+ end
+ end
+
+ def prepare(data)
+ (data.class == String && data.to_i.to_s == data) ? data.to_i : data
+ end
+ end
+
+ def to_struct(struct_name)
+ Struct.new(struct_name,*keys).new(*values)
+ end
+end
+
+module ActiveResource
+ module Formats
+ module XmlFormat
+ extend self
+
+ def decode(xml)
+ from_xml_data(Hash.from_xml(xml, :with_attributes))
+ end
+ end
+ end
+end
+
+