lib/datamapper4rails/adapters/restful_adapter.rb in datamapper4rail-0.1.0 vs lib/datamapper4rails/adapters/restful_adapter.rb in datamapper4rail-0.2.0

- old
+ new

@@ -1,9 +1,10 @@ -require 'adapters/restful_adapter' +require 'datamapper4rails/adapters/base_adapter' require 'net/http' require 'extlib/inflection' require 'extlib/module' +require 'dm-serializer' module DataMapper module Adapters class RestfulAdapter < BaseAdapter @@ -42,11 +43,23 @@ end[2] else raise "compound keys are not supported" end end + + def single_entity_query?(query) + query.conditions.count {|c| c[1].key? and c[0] == :eql} == query.model.key.size + end + def attributes_to_xml(name, attributes) + xml = "<#{name}>" + attributes.each do |attr, val| + xml += "<#{attr.name}>#{val}</#{attr.name}>" + end + xml += "</#{name}>" + end + def http_get(uri) send_request do |http| request = Net::HTTP::Get.new(uri) request.basic_auth(@uri[:login], @uri[:password]) unless @uri[:login].blank? @@ -64,17 +77,20 @@ @uri[:password]) unless @uri[:login].blank? http.request(request, data) end end - def http_put(uri, data = {}) + def http_put(uri, data = nil) send_request do |http| - request = Net::HTTP::Put.new(uri) + request = Net::HTTP::Put.new(uri, { + 'content-type' => 'application/xml', + 'content-length' => data.length.to_s + }) request.basic_auth(@uri[:login], @uri[:password]) unless @uri[:login].blank? - request.set_form_data(data) - http.request(request) +# request.set_form_data(data) + http.request(request, data) end end def http_delete(uri) send_request do |http| @@ -110,38 +126,70 @@ end end #puts #puts "elements" #p elements +#p query +#p model resource = model.load(model.properties.collect do |f| elements[f.name] end, query) resource.send("#{keys_from_query(query)[0].name}=".to_sym, elements[keys_from_query(query)[0].name] ) -#p resource - associations.each do |name, association| - model = +# p resource +#p associations + associations.each do |name, association| +# puts "asso" +# p model +# p name +# p association +#p model.relationships + is_one_to_one = false + asso_model = if rel = model.relationships[name] +#puts "rel" +#p rel if rel.child_model == model rel.parent_model else rel.child_model end # else #::Extlib::Inflection.constantize(::Extlib::Inflection.classify(name)) # model.find_const(::Extlib::Inflection.classify(name)) end + # p asso_model if resource.respond_to? "#{name}=".to_sym + # puts +# puts "association" +# puts name +# p model +# p asso_model resource.send("#{name}=".to_sym, - parse_resource(association, model, - ::DataMapper::Query.new(query.repository, model ))) + parse_resource(association, asso_model, + ::DataMapper::Query.new(query.repository, asso_model ))) unless asso_model.nil? else resource.send(("#{name.to_s.pluralize}<" + "<").to_sym, - parse_resource(association, model, - ::DataMapper::Query.new(query.repository, model ))) + parse_resource(association, asso_model, + ::DataMapper::Query.new(query.repository, asso_model ))) unless asso_model.nil? end end + +#puts "many 2 many" +#p many_to_many + many_to_many.each do |name, many| + if model.relationships[name] + # TODO + else + # p ::Extlib::Inflection.classify(name.to_s.singularize) + many_model = Object.const_get(::Extlib::Inflection.classify(name.to_s.singularize)) + resource.send(name).send(("<" + "<").to_sym, + parse_resource(many, many_model, + ::DataMapper::Query.new(query.repository, many_model ))) unless many_model.nil? + end + end resource.instance_variable_set(:@new_record, false) +#p resource resource end # @see BaseAdapter def create_resource(resource) @@ -166,69 +214,74 @@ resource end # @see BaseAdapter def read_resource(query) - if(query.conditions.empty?) - raise "not implemented" + key = key_value_from_query(query) + uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml" + logger.debug { "get #{uri}" } + response = http_get(uri) + if response.kind_of?(Net::HTTPSuccess) + logger.debug { response.body.to_s } + parse_resource(REXML::Document::new(response.body).root, + query.model, + query) else - key = key_value_from_query(query) - uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml" + #TODO may act on different response codes differently + end + end + + # @see BaseAdapter + def read_resources(query) + if single_entity_query?(query) + [read_resource(query)] + else + uri = "/#{resource_name_from_query(query).pluralize}.xml" logger.debug { "get #{uri}" } response = http_get(uri) if response.kind_of?(Net::HTTPSuccess) - parse_resource(REXML::Document::new(response.body).root, - query.model, - query) + result = [] + logger.debug { response.body.to_s } + REXML::Document::new(response.body).root.each do |element| + result << parse_resource(element, + query.model, + query) + end + result else #TODO may act on different response codes differently end end end - # @see BaseAdapter - def read_resources(query) -# raise "not implemented" - [read_resource(query)] - end - # @overwrite BaseAdapter def update(attributes, query) - name = resource_name_from_query(query) - params = {} - attributes.each do |attr, val| - params["#{name}[#{attr.name}]"]=val + if query.limit == 1 or single_entity_query?(query) + xml = attributes_to_xml(resource_name_from_query(query), attributes) + key = key_value_from_query(query) + uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml" + logger.debug { "put #{uri}" } + response = http_put(uri, xml) + response.kind_of?(Net::HTTPSuccess) + else + super end - key = key_value_from_query(query) - uri = "/#{name.pluralize}/#{key}.xml" - logger.debug { "put #{uri}" } - response = http_put(uri, params) - response.kind_of?(Net::HTTPSuccess) end # @see BaseAdapter def update_resource(resource, attributes) query = resource.to_query - if(query.conditions.empty?) - raise "not implemented" - else - name = resource.name - params = {} - attributes.each do |attr, val| - params["#{name}[#{attr.name}]"]=val - end - key = key_value_from_query(query) - logger.debug {resource.to_xml} - response = http_put("/#{resource_name_from_query(query).pluralize}/#{key}.xml", params) - response.kind_of?(Net::HTTPSuccess) - end + xml = attributes_to_xml(resource.name, attributes) + key = key_value_from_query(query) + logger.debug {resource.to_xml} + response = http_put("/#{resource_name_from_query(query).pluralize}/#{key}.xml", xml) + response.kind_of?(Net::HTTPSuccess) end - + # @overwrite BaseAdapter def delete(query) - # TODO limit == 1 is NOT sufficient ONLY necessary - if query.limit == 1 + if query.limit == 1 or single_entity_query?(query) name = resource_name_from_query(query) key = key_value_from_query(query) uri = "/#{name.pluralize}/#{key}.xml" logger.debug { "delete #{uri}" } response = http_delete(uri) @@ -239,10 +292,10 @@ end # @see BaseAdapter def delete_resource(resource) name = resource.name - key = key_value_from_query(resource.to_queryquery) + key = key_value_from_query(resource.to_query) uri = "/#{name.pluralize}/#{key}.xml" logger.debug { "delete #{uri}" } response = http_delete(uri) response.kind_of?(Net::HTTPSuccess) end