metamolecular-chemcaster 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,35 @@
1
+ = Chemcaster Ruby API
2
+
3
+ This is the Ruby interface for the Chemcaster[http://chemcaster.com] RESTful Web
4
+ API. It consists of basic functionality needed to create
5
+ applications using chemical structure registration, storage, imaging, and
6
+ search.
7
+
8
+ == Example Use
9
+
10
+ === Connecting to the Service
11
+
12
+ require 'lib/chemcaster'
13
+ include Chemcaster
14
+
15
+ service = Service.connect 'username', 'password'
16
+
17
+ === Loading a Registry
18
+
19
+ require 'lib/chemcaster'
20
+ include Chemcaster
21
+
22
+ service = Service.connect 'username', 'password'
23
+ registries = service.registries
24
+ registries.size # => 3
25
+ registry = registries[0]
26
+
27
+ === Creating a Registry
28
+
29
+ require 'lib/chemcaster'
30
+ include Chemcaster
31
+
32
+ service = Service.connect 'username', 'password'
33
+ registries = service.registries
34
+
35
+ registries.create :name => 'CarboBlocks, Inc.'
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ require 'spec/rake/spectask'
5
+ Spec::Rake::SpecTask.new(:spec) do |spec|
6
+ spec.libs << 'lib' << 'spec'
7
+ spec.spec_files = FileList['spec/**/*_spec.rb']
8
+ end
@@ -0,0 +1,36 @@
1
+ module Chemcaster
2
+ class Error < RuntimeError; end
3
+ class LinkNotDefined < Error; end
4
+ class HTTPError < Error
5
+ attr_accessor :response
6
+ def initialize response
7
+ @response = response
8
+ end
9
+
10
+ def to_s
11
+ "received response code #{@response.code} with message:\n\n#{parse_errors}"
12
+ end
13
+
14
+ protected
15
+
16
+ def parse_errors
17
+ errors = nil
18
+ message = ""
19
+ begin
20
+ errors = JSON.parse response.body
21
+ rescue
22
+ return response.body
23
+ end
24
+
25
+ errors.each do |error|
26
+ if error['field']
27
+ message << "- field '#{error['field']}' #{error['text']}\n"
28
+ else
29
+ message << "- #{error['text']}\n"
30
+ end
31
+ end
32
+
33
+ message
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Image < Item
3
+ attributes :width, :height, :data
4
+ resources :imageable
5
+ end
6
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../chemcaster/representation'
2
+
3
+ module Chemcaster
4
+ class Index < Representation
5
+ attr_accessor :item_links#, :items
6
+ resources :parent
7
+
8
+ def create representation_attributes
9
+ @create_link.post representation_attributes
10
+ end
11
+
12
+ def size
13
+ @item_links.size
14
+ end
15
+
16
+ def [](index)
17
+ @item_links[index].get
18
+ end
19
+
20
+ protected
21
+
22
+ def load_hash atts
23
+ super
24
+
25
+ @create_link = Link.new atts['create']
26
+ @item_links = atts['items'].inject([]) do |result, atts|
27
+ result << Link.new(atts)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/../chemcaster/representation'
2
+
3
+ module Chemcaster
4
+ class Item < Representation
5
+ resources :index
6
+
7
+ def update representation_attributes
8
+ @update_link.put representation_attributes
9
+ end
10
+
11
+ def destroy
12
+ @destroy_link.delete
13
+ end
14
+
15
+ protected
16
+
17
+ def load_hash atts
18
+ super
19
+
20
+ @update_link = Link.new atts['update']
21
+ @destroy_link = Link.new atts['destroy']
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,89 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+
4
+ module Chemcaster
5
+ class Link
6
+ def initialize atts=nil
7
+ if atts
8
+ @uri = URI.parse(atts['uri']) if atts['uri']
9
+ @media_type = atts['media_type']
10
+ @media_class = MediaType.representation(@media_type) if @media_type
11
+ end
12
+ end
13
+
14
+ def get
15
+ do_http 'get'
16
+ end
17
+
18
+ def put attributes
19
+ do_http 'put', attributes
20
+ end
21
+
22
+ def post attributes
23
+ do_http 'post', attributes
24
+ end
25
+
26
+ def delete
27
+ do_http 'delete'
28
+ end
29
+
30
+ private
31
+
32
+ def do_http method, representation=nil
33
+ validate
34
+ request = request_for_method method, representation
35
+ response = send_request request
36
+
37
+ raise(HTTPError, response) unless response.code.to_i < 300
38
+ @media_class.new self, decode(response.body)
39
+ end
40
+
41
+ def send_request request
42
+ http = Net::HTTP.new(@uri.host, @uri.port)
43
+ http.use_ssl = (@uri.scheme == 'https')
44
+
45
+ if File.exists? Service.root_ca
46
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
47
+ http.ca_path = Service.root_ca
48
+ else
49
+ message =
50
+ "net/http couldn't locate this system's root SSL certificate files."+
51
+ "On Debian Linux systems, these files are located at /etc/ssl/certs "+
52
+ "(this library's default). For more information, see:\n\n"+
53
+ "http://codeidol.com/other/rubyckbk/Internet-Services/Making-an-HTTPS-Web-Request\n"+
54
+ "http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html\n"+
55
+ "http://notetoself.vrensk.com/2008/09/verified-https-in-ruby\n"
56
+ raise(message)
57
+ end
58
+
59
+ http.request(request)
60
+ end
61
+
62
+ def request_for_method method, attributes=nil
63
+ request = case method
64
+ when "get" then Net::HTTP::Get.new(@uri.path)
65
+ when "put" then Net::HTTP::Put.new(@uri.path)
66
+ when "post" then Net::HTTP::Post.new(@uri.path)
67
+ when "delete" then Net::HTTP::Delete.new(@uri.path)
68
+ end
69
+
70
+ request['accept'] = @media_type
71
+ request.basic_auth Service.username, Service.password
72
+
73
+ if attributes
74
+ request.body = {MediaType.hash_key(@media_type) => attributes}.to_json
75
+ request.content_type = @media_type
76
+ end
77
+
78
+ request
79
+ end
80
+
81
+ def validate
82
+ raise LinkNotDefined unless @uri && @media_class
83
+ end
84
+
85
+ def decode response
86
+ JSON.parse response
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,27 @@
1
+ module Chemcaster
2
+ class MediaType
3
+ def self.representation name
4
+ name.match(/application\/vnd\.com\.chemcaster\.(.*)\+json/)
5
+ raise "No such media type: #{name}" unless klass = $1
6
+
7
+ begin
8
+ Object.const_get(klass)
9
+ rescue
10
+ raise "No such class: #{klass}"
11
+ end
12
+ end
13
+
14
+ def self.hash_key full_mime_type_name
15
+ full_mime_type_name.match(/application\/vnd\.com\.chemcaster\.(.*)\+json/)
16
+ raise "No such media type: #{full_mime_type_name}" unless key = $1
17
+
18
+ begin
19
+ Object.const_get(key)
20
+ rescue
21
+ raise "No such class: #{key}"
22
+ end
23
+
24
+ key.downcase
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Query < Item
3
+ attributes :molfile
4
+ resources :images, :registry
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + '/../chemcaster/item'
2
+
3
+ module Chemcaster
4
+ class Registry < Item
5
+ attributes :name, :deletable
6
+ resources :queries, :structures
7
+ end
8
+ end
@@ -0,0 +1,66 @@
1
+ module Chemcaster
2
+ class Representation
3
+ # class instance variables - see: http://martinfowler.com/bliki/ClassInstanceVariable.html
4
+ class << self; attr_accessor :resource_ids; end
5
+ class << self; attr_accessor :attribute_ids; end
6
+
7
+ attr_accessor :attributes
8
+ attr_accessor :link
9
+
10
+ def initialize link, raw
11
+ @link = link
12
+ @attributes = {}
13
+ load_hash raw
14
+ end
15
+
16
+ def self.attributes *atts
17
+ self.attribute_ids ||= []
18
+ atts.each do |m|
19
+ self.attribute_ids << m.to_s
20
+ define_method(m) do
21
+ attributes[m.to_s]
22
+ end
23
+
24
+ define_method("#{m}=") do |val|
25
+ attributes.merge!({m.to_s => val})
26
+ end
27
+ end
28
+ end
29
+
30
+ def self.resources *res
31
+ self.resource_ids ||= self.superclass.resource_ids || []
32
+ res.each do |id|
33
+ self.resource_ids << id
34
+ define_method(id) do
35
+ instance_variable_get("@#{id}_link").send('get')
36
+ end
37
+ end
38
+ end
39
+
40
+ def to_json
41
+ JSON({attributes_name => @attributes})
42
+ end
43
+
44
+ def attributes_name
45
+ self.class.to_s.gsub(/Chemcaster::/, '').downcase
46
+ end
47
+
48
+ protected
49
+
50
+ def load_hash hash
51
+ self.class.attribute_ids ||= []
52
+ if hash[name = attributes_name]
53
+ hash[name].each do |attribute|
54
+ if self.class.attribute_ids.member? attribute[0]
55
+ attributes[attribute[0]] = attribute[1]
56
+ end
57
+ end
58
+ end
59
+
60
+ self.class.resource_ids ||= []
61
+ self.class.resource_ids.each do |resource_id|
62
+ instance_variable_set("@#{resource_id}_link".to_sym, Link.new(hash[resource_id.to_s]))
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/../chemcaster/representation'
2
+
3
+ module Chemcaster
4
+ class Service < Representation
5
+ attr_accessor :registries_link
6
+
7
+ # Ruby SSL needs to be told the location of the system's SSL CA files.
8
+ # On Debian Linux systems, these files are located at /etc/ssl/certs,
9
+ # which is this library's default. For more information, see:
10
+ #
11
+ # http://codeidol.com/other/rubyckbk/Internet-Services/Making-an-HTTPS-Web-Request
12
+ # http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html
13
+ # http://notetoself.vrensk.com/2008/09/verified-https-in-ruby
14
+
15
+ @@root_ca = nil; def self.root_ca; @@root_ca; end
16
+ @@username = nil; def self.username; @@username; end
17
+ @@password = nil; def self.password; @@password; end
18
+
19
+ def self.connect username, password, options = {}
20
+ @@username = username; @@password = password
21
+
22
+ @@root_ca = options[:root_ca] || '/etc/ssl/certs'
23
+ uri = options[:uri] || 'https://chemcaster.com/rest'
24
+
25
+ service_link = Link.new 'uri' => uri,
26
+ 'media_type' => 'application/vnd.com.chemcaster.Service+json', 'name' => 'root'
27
+ service_link.get
28
+ end
29
+
30
+ def registries
31
+ @registries_link.get
32
+ end
33
+
34
+ protected
35
+
36
+ def load_hash hash
37
+ super
38
+ @registries_link = Link.new hash['registries']
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Structure < Item
3
+ attributes :name, :molfile
4
+ resources :images, :registry
5
+ end
6
+ end
data/lib/chemcaster.rb ADDED
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + "/chemcaster/service"
2
+ require File.dirname(__FILE__) + '/chemcaster/service'
3
+ require File.dirname(__FILE__) + '/chemcaster/registry'
4
+ require File.dirname(__FILE__) + '/chemcaster/structure'
5
+ require File.dirname(__FILE__) + '/chemcaster/query'
6
+ require File.dirname(__FILE__) + '/chemcaster/image'
7
+ require File.dirname(__FILE__) + '/chemcaster/link'
8
+ require File.dirname(__FILE__) + '/chemcaster/index'
9
+ require File.dirname(__FILE__) + '/chemcaster/item'
10
+ require File.dirname(__FILE__) + '/chemcaster/representation'
11
+ require File.dirname(__FILE__) + '/chemcaster/media_type'
12
+ require File.dirname(__FILE__) + '/chemcaster/error'
13
+
14
+ require 'rubygems'
15
+ require 'json'
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metamolecular-chemcaster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Richard Apodaca
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-17 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.1.4
24
+ version:
25
+ description: A hypertext-driven Ruby client for the Chemcaster cheminformatics Web services platform.
26
+ email: info@metamolecular.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - README.rdoc
35
+ - Rakefile
36
+ - lib/chemcaster.rb
37
+ - lib/chemcaster/error.rb
38
+ - lib/chemcaster/image.rb
39
+ - lib/chemcaster/index.rb
40
+ - lib/chemcaster/item.rb
41
+ - lib/chemcaster/link.rb
42
+ - lib/chemcaster/media_type.rb
43
+ - lib/chemcaster/query.rb
44
+ - lib/chemcaster/registry.rb
45
+ - lib/chemcaster/representation.rb
46
+ - lib/chemcaster/service.rb
47
+ - lib/chemcaster/structure.rb
48
+ has_rdoc: false
49
+ homepage: http://chemcaster.com
50
+ licenses:
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.3.5
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: A hypertext-driven Ruby client for the Chemcaster cheminformatics Web services platform. End.
75
+ test_files: []
76
+