Skip to content

my changes #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
using nokogiri to extract not only xml child but also xml attribute
add :put and :delete params in find options
edit readme
  • Loading branch information
qoyyim-at-kiranatama committed Aug 23, 2010
commit 061ae12fcb1958528308ecb1ef7c5bb84c41565b
49 changes: 13 additions & 36 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 => '<?xml version="1.0" encoding="UTF-8"?><search_params><region>EUR</region></search_params>')
will send '<?xml version="1.0" encoding="UTF-8"?><search_params><region>EUR</region></search_params>' with method post to yoursite+'/brands/search.xml'
and parse xml result



Expand Down Expand Up @@ -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
Expand Down
24 changes: 17 additions & 7 deletions lib/hyperactive_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1082,19 +1082,29 @@ 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
if post_value.nil?
instantiate_collection(get(from_value, options[:params]))
else
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])}"
if post_value.nil?
instantiate_collection(connection.get(path, headers).arrayify)
else
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)
Expand Down
79 changes: 79 additions & 0 deletions lib/parse_xml_attributes_too.rb
Original file line number Diff line number Diff line change
@@ -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