chemcaster 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc ADDED
@@ -0,0 +1,94 @@
1
+ = Chemcaster[http://chemcaster.com] 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
+ == Installation
9
+
10
+ Installation through the Ruby Gem hosted on GitHub is recommended:
11
+
12
+ # add GitHub to your local list of gem sources:
13
+ gem sources -a http://gems.github.com/
14
+
15
+ # install the gem:
16
+ gem install metamolecular-chemcaster
17
+
18
+ == Example Use
19
+
20
+ === Connecting to the Service
21
+
22
+ require 'rubygems'
23
+ require 'chemcaster'
24
+
25
+ service = Chemcaster::Service.connect 'username', 'password'
26
+
27
+ Because Chemcaster[http://chemcaster.com] authenticates using SSL, you'll need to make sure the
28
+ Ruby HTTP library can find the root SSL certificates on your system. On
29
+ Debian Linux systems, these files are found in /etc/ssl/certs. This is
30
+ also the default location used by the Chemcaster Ruby Client.
31
+
32
+ To override the default SSL certificates path, pass the +root_ca+ option to the
33
+ +connect+ method:
34
+
35
+ service = Chemcaster::Service.connect 'username', 'password',
36
+ :root_ca => 'path/to/root_ssl_certs'
37
+
38
+ More information can be found here:
39
+
40
+ * {Making an HTTPS Web Request}[http://codeidol.com/other/rubyckbk/Internet-Services/Making-an-HTTPS-Web-Request]
41
+ * {SSL Certificates and Net::HTTPS}[http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html]
42
+ * {Verified HTTPS in Ruby}[http://notetoself.vrensk.com/2008/09/verified-https-in-ruby]
43
+
44
+ === Loading a Registry from a Listing
45
+
46
+ require 'rubygems'
47
+ require 'chemcaster'
48
+
49
+ service = Chemcaster::Service.connect 'username', 'password'
50
+ registries = service.registries
51
+ registries.size # => 3
52
+ registry = registries[0]
53
+
54
+ === Loading a Registry from a URI
55
+
56
+ require 'rubygems'
57
+ require 'chemcaster'
58
+
59
+ Chemcaster::Service.connect 'username', 'password'
60
+
61
+ link = Chemcaster::Link.new 'name'=> 'foo',
62
+ 'uri' => 'https://chemcaster.com/registries/123456',
63
+ 'media_type' => 'application/vnd.com.chemcaster.Registry+json'
64
+ registry = link.get
65
+
66
+ Note: No assumptions should be made about Chemcaster[http://chemcaster.com] URI layout. Once
67
+ you receive a resource URI, you can expect it to work at any point
68
+ in the future for random-access. But URI templates are unnecessary
69
+ when accessing resources.
70
+
71
+ === Creating a Registry
72
+
73
+ require 'rubygems'
74
+ require 'chemcaster'
75
+
76
+ service = Chemcaster::Service.connect 'username', 'password'
77
+ registries = service.registries
78
+
79
+ registries.create :name => 'CarboBlocks, Inc.'
80
+
81
+ === Changing a Registry Name
82
+
83
+ require 'rubygems'
84
+ require 'chemcaster'
85
+
86
+ service = Chemcaster::Service.connect 'username', 'password'
87
+ registry = service.registries[0]
88
+ registry.update :name => 'CarboBlocks International, Inc.'
89
+
90
+
91
+ == API Documentation
92
+
93
+ RDoc documentation is available at
94
+ {rdoc.info}[http://rdoc.info/projects/metamolecular/chemcaster-ruby].
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'spec/rake/spectask'
4
+ require 'rake/rdoctask'
5
+
6
+ Spec::Rake::SpecTask.new(:spec) do |spec|
7
+ spec.libs << 'lib' << 'spec'
8
+ spec.spec_files = FileList['spec/**/*_spec.rb']
9
+ end
10
+
11
+ desc 'Generate RDoc documentation for Chemcaster client.'
12
+ Rake::RDocTask.new(:rdoc) do |rdoc|
13
+ rdoc.rdoc_files.include('README.rdoc', 'LICENSE').include('lib/**/*.rb')
14
+
15
+ rdoc.main = "README.rdoc" # page to start on
16
+ rdoc.title = "Chemcaster Client Documentation"
17
+
18
+ rdoc.rdoc_dir = 'doc' # rdoc output folder
19
+ rdoc.options << '--inline-source' << '--charset=UTF-8'
20
+ rdoc.options << '--webcvs=http://github.com/mislav/will_paginate/tree/master/'
21
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Archive < Item
3
+ attributes :created_at, :done
4
+ resources :zipfile, :registry
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Component < Item
3
+ attributes :multiplier
4
+ resources :structure, :substance
5
+ end
6
+ 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,19 @@
1
+ module Chemcaster
2
+ class Execution < Item
3
+ attributes :cursor, :reverse, :next_cursor, :previous_cursor
4
+ resources :executable
5
+ attr_accessor :results
6
+
7
+ protected
8
+
9
+ def load_hash hash
10
+ super
11
+
12
+ hash['results'] ||= []
13
+
14
+ @results = hash['results'].inject([]) do |result, atts|
15
+ result << Link.new(atts)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Image < Item
3
+ attributes :width, :height, :data, :format
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,93 @@
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)
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
+ if response.content_type.match(/application\/vnd\.com\.chemcaster\.(.*)\+json/)
87
+ JSON.parse response.body
88
+ else
89
+ response.body
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,32 @@
1
+ module Chemcaster
2
+ class MediaType
3
+ def self.representation name
4
+ name.match(/application\/vnd\.com\.chemcaster\.(.*)\+json/)
5
+
6
+ unless klass = $1
7
+ klass = "Zip" if name == 'application/zip'
8
+ end
9
+
10
+ raise "No such media type: #{name}" unless klass
11
+
12
+ begin
13
+ Chemcaster.const_get("#{klass}")
14
+ rescue
15
+ raise "Unable to create class from media type: #{name}"
16
+ end
17
+ end
18
+
19
+ def self.hash_key full_mime_type_name
20
+ full_mime_type_name.match(/application\/vnd\.com\.chemcaster\.(.*)\+json/)
21
+ raise "No such media type: #{full_mime_type_name}" unless key = $1
22
+
23
+ begin
24
+ Chemcaster.const_get(key)
25
+ rescue
26
+ raise "No such class: #{key}"
27
+ end
28
+
29
+ key.downcase
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Query < Item
3
+ attributes :serialization
4
+ resources :images, :registry, :executions
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + '/../chemcaster/item'
2
+
3
+ module Chemcaster
4
+ class Registration < Item
5
+ attributes :templates
6
+ resources :substance, :registry
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../chemcaster/item'
2
+
3
+ module Chemcaster
4
+ class Registry < Item
5
+ attributes :name, :deletable
6
+ resources :service, :queries, :structures, :substances,
7
+ :archives, :registrations
8
+ end
9
+ 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,31 @@
1
+ require File.dirname(__FILE__) + '/../chemcaster/representation'
2
+
3
+ module Chemcaster
4
+ class Service < Representation
5
+ attributes :version
6
+ resources :registries
7
+
8
+ # Ruby SSL needs to be told the location of the system's SSL CA files.
9
+ # On Debian Linux systems, these files are located at /etc/ssl/certs,
10
+ # which is this library's default. For more information, see:
11
+ #
12
+ # http://codeidol.com/other/rubyckbk/Internet-Services/Making-an-HTTPS-Web-Request
13
+ # http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html
14
+ # http://notetoself.vrensk.com/2008/09/verified-https-in-ruby
15
+
16
+ @@root_ca = nil; def self.root_ca; @@root_ca; end
17
+ @@username = nil; def self.username; @@username; end
18
+ @@password = nil; def self.password; @@password; end
19
+
20
+ def self.connect username, password, options = {}
21
+ @@username = username; @@password = password
22
+
23
+ @@root_ca = options[:root_ca] || '/etc/ssl/certs'
24
+ uri = options[:uri] || 'https://chemcaster.com/rest'
25
+
26
+ service_link = Link.new 'uri' => uri,
27
+ 'media_type' => 'application/vnd.com.chemcaster.Service+json', 'name' => 'root'
28
+ service_link.get
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Structure < Item
3
+ attributes :serialization, :inchi
4
+ resources :images, :registry, :components
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Chemcaster
2
+ class Substance < Item
3
+ attributes :serialization, :inchi
4
+ resources :components, :registry, :images, :registration
5
+ end
6
+ end
data/lib/chemcaster.rb ADDED
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + "/chemcaster/service"
2
+ require File.dirname(__FILE__) + '/chemcaster/registry'
3
+ require File.dirname(__FILE__) + '/chemcaster/registration'
4
+ require File.dirname(__FILE__) + '/chemcaster/structure'
5
+ require File.dirname(__FILE__) + '/chemcaster/substance'
6
+ require File.dirname(__FILE__) + '/chemcaster/component'
7
+ require File.dirname(__FILE__) + '/chemcaster/query'
8
+ require File.dirname(__FILE__) + '/chemcaster/image'
9
+ require File.dirname(__FILE__) + '/chemcaster/execution'
10
+ require File.dirname(__FILE__) + '/chemcaster/archive'
11
+ require File.dirname(__FILE__) + '/chemcaster/link'
12
+ require File.dirname(__FILE__) + '/chemcaster/index'
13
+ require File.dirname(__FILE__) + '/chemcaster/item'
14
+ require File.dirname(__FILE__) + '/chemcaster/representation'
15
+ require File.dirname(__FILE__) + '/chemcaster/media_type'
16
+ require File.dirname(__FILE__) + '/chemcaster/error'
17
+ require File.dirname(__FILE__) + '/chemcaster/zip'
18
+
19
+ require 'rubygems'
20
+ require 'json'
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chemcaster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.1
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/index.rb
39
+ - lib/chemcaster/item.rb
40
+ - lib/chemcaster/link.rb
41
+ - lib/chemcaster/media_type.rb
42
+ - lib/chemcaster/representation.rb
43
+ - lib/chemcaster/service.rb
44
+ - lib/chemcaster/registry.rb
45
+ - lib/chemcaster/registration.rb
46
+ - lib/chemcaster/substance.rb
47
+ - lib/chemcaster/structure.rb
48
+ - lib/chemcaster/component.rb
49
+ - lib/chemcaster/query.rb
50
+ - lib/chemcaster/execution.rb
51
+ - lib/chemcaster/archive.rb
52
+ - lib/chemcaster/image.rb
53
+ has_rdoc: true
54
+ homepage: http://chemcaster.com
55
+ licenses: []
56
+
57
+ post_install_message:
58
+ rdoc_options: []
59
+
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.5
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: A hypertext-driven Ruby client for the Chemcaster cheminformatics Web services platform. End.
81
+ test_files: []
82
+