calculated 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
File without changes
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Richard Hooker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/ROADMAP.md ADDED
@@ -0,0 +1 @@
1
+ Its coming
data/lib/calculated.rb ADDED
@@ -0,0 +1,22 @@
1
+ # requires
2
+ require "httparty"
3
+ require "hashie"
4
+ require "moneta"
5
+ require "moneta/memory"
6
+
7
+
8
+ require "calculated/generic_object_api_calls"
9
+ require "calculated/object_template_api_calls"
10
+ require "calculated/relatable_category_api_calls"
11
+ require "calculated/answer_api_calls"
12
+ require "calculated/session"
13
+ require "calculated/service"
14
+ require "calculated/logging"
15
+
16
+ require "calculated/models/characteristic"
17
+ require "calculated/models/formula_input"
18
+ require "calculated/models/generic_object"
19
+ require "calculated/models/object_template"
20
+ require "calculated/models/relatable_category"
21
+ require "calculated/models/source"
22
+ require "calculated/models/answer"
@@ -0,0 +1,24 @@
1
+ module Calculated
2
+ module AnswerApiCalls
3
+
4
+ # @param [String] id
5
+ # @param [Hash] params
6
+ # @return [Array<Calculated::Models::Answer>]
7
+ def answer_for_calculator(calculator_id, params = {})
8
+ api_call(:get, "/calculators/#{calculator_id}/answer", params) do |response|
9
+ Calculated::Models::Answer.new(response)
10
+ end
11
+ end
12
+
13
+
14
+ # @param [String] id
15
+ # @param [Hash] params
16
+ # @return [Array<Calculated::Models::Answer>]
17
+ def answer_for_computation(compuation_id, params = {})
18
+ api_call(:get, "/computations/#{compuation_id}/answer", params) do |response|
19
+ Calculated::Models::Answer.new(response)
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ module Calculated
2
+ module GenericObjectApiCalls
3
+
4
+ # @param [Hash] params
5
+ # @return [Array<Calculated::Models::GeneriObject>]
6
+ def generic_objects(params = {})
7
+ api_call(:get, "/generic_objects", params) do |response|
8
+ response["generic_objects"].map{|generic_object| Calculated::Models::GenericObject.new(generic_object)}
9
+ end
10
+ end
11
+
12
+ # @param [String] id
13
+ # @param [Hash] params
14
+ # @return [Calculated::Models::GeneriObject
15
+ def generic_object(id, params = {})
16
+ api_call(:get, "/generic_objects/#{id}", params) do |response|
17
+ Calculated::Models::GenericObject.new(response["generic_object"])
18
+ end
19
+ end
20
+
21
+ # @param [String] id
22
+ # @param [Hash] params
23
+ # @return [Array<Calculated::Models::FormulaInput>]
24
+ def formula_inputs_for_generic_object(id, params = {})
25
+ api_call(:get, "/generic_objects/#{id}/formula_inputs", params) do |response|
26
+ response["formula_inputs"].map{|formula_input| Calculated::Models::FormulaInput.new(formula_input)}
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ require 'benchmark'
2
+ module Calculated
3
+ @@logger = nil
4
+ def self.logger=(logger)
5
+ @@logger = logger
6
+ end
7
+ def self.logger
8
+ @@logger
9
+ end
10
+
11
+ module Logging
12
+ def self.log_calculated_api(method, path, options)
13
+ message = method
14
+ dump = format_da_dump(path, options)
15
+ if block_given?
16
+ result = nil
17
+ seconds = Benchmark.realtime { result = yield }
18
+ log_info(message, dump, seconds)
19
+ result
20
+ else
21
+ log_info(message, dump)
22
+ nil
23
+ end
24
+ rescue Exception => e
25
+ exception = "#{e.class.name}: #{e.message}: #{dump}"
26
+ log_info(message, exception)
27
+ raise
28
+ end
29
+
30
+ def self.format_da_dump(path, params)
31
+ "Calculated: PATH: #{path} PARAMS: #{params.inspect}"
32
+ end
33
+
34
+ def self.log_info(message, dump, seconds = 0)
35
+ return unless Calculated.logger
36
+ log_message = "#{message} (#{seconds}) #{dump}"
37
+ Calculated.logger.info(log_message)
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ # Answers from the api
2
+ #  calculations will be in the form of a hash with value and units keys
3
+ # answer.calculations["co2"]["value"] == 10
4
+ # answer.calculations["co2"]["units"] == "kg"
5
+ module Calculated
6
+ module Models
7
+ class Answer < Hashie::Dash
8
+
9
+ # properties
10
+ property :calculations # [Hash]
11
+ property :object_references # [Hash]
12
+ property :used_global_computations # [Hash]
13
+ property :calculator_id # [String]
14
+ property :computation_id # [String]
15
+ property :answer_set_id # [String]
16
+ property :source # [Calculated::Models::Source]
17
+ property :errors # [Hash]
18
+
19
+ def source=(value)
20
+ unless value.nil?
21
+ self[:source] = Models::Source.new(value)
22
+ end
23
+ end
24
+
25
+ def valid?
26
+ errors.nil?
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ module Calculated
2
+ module Models
3
+ class Characteristic < Hashie::Dash
4
+
5
+ # properties
6
+ property :id # [String]
7
+ property :attribute # [String]
8
+ property :value # [String]
9
+ property :value_type # [String]
10
+ property :units # [String]
11
+ property :image_id # [String]
12
+ property :image_name # [String]
13
+ property :image_size # [String]
14
+ property :image_type # [String]
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ module Calculated
2
+ module Models
3
+ class FormulaInput < Hashie::Dash
4
+
5
+ # properties
6
+ property :id # [String]
7
+ property :values # [Hash]
8
+ property :name # [String]
9
+ property :base_unit # [String]
10
+ property :active_at # [Time] yes time
11
+ property :main_source_id # [String]
12
+ property :group_name # [String]
13
+ property :input_units # [String]
14
+ property :label_input_units # [String]
15
+ property :model_state # [String]
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ module Calculated
2
+ module Models
3
+ class GenericObject < Hashie::Dash
4
+
5
+ # properties
6
+ property :id # [String]
7
+ property :template_name # [String]
8
+ property :identifier # [String]
9
+ property :characteristics # [Array<Calculated::Models::Characteristic>]
10
+ property :formula_inputs # [Array<Calculated::Models::FormulaInput>]
11
+
12
+ # dont ask why I need to check for nil? here just dont!
13
+ def characteristics=(value)
14
+ unless value.nil?
15
+ self[:characteristics] = value.map{|characteristic| Calculated::Models::Characteristic.new(characteristic)}
16
+ end
17
+ end
18
+
19
+ # setting the formula inputs to a defined model
20
+ def formula_inputs=(value)
21
+ unless value.nil?
22
+ self[:formula_inputs] = value.map{|formula| Calculated::Models::FormulaInput.new(formula)}
23
+ end
24
+ end
25
+
26
+ def used_formula_inputs=(value)
27
+ unless value.nil?
28
+ self[:used_formula_inputs] = value.map{|formula| Calculated::Models::FormulaInput.new(formula)}
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,48 @@
1
+ module Calculated
2
+ module Models
3
+ class ObjectTemplate < Hashie::Dash
4
+
5
+ # properties
6
+ property :id # [String]
7
+ property :name # [String]
8
+ property :generic_objects # [Array<Calculated::Models::GenericObject>]
9
+
10
+ # characteristics from an object template will not have a value property set as it is a template
11
+ property :characteristics # [Hash] not the same as generi_objects characteristics
12
+
13
+ # formula_inputs from an object template will not have a value property set as it is a template
14
+ property :formula_inputs # [Hash] not the same as generi_objects formula_inputs
15
+
16
+ property :relatable_categories # [Array<Calculated::Models::RelatableCategory>]
17
+
18
+ # dont ask why I need to check for nil? here just dont!
19
+ def generic_objects=(value)
20
+ unless value.nil?
21
+ self[:generic_objects] = value.map{|generic_object| Calculated::Models::GenericObject.new(generic_object)}
22
+ end
23
+ end
24
+
25
+ # dont ask why I need to check for nil? here just dont!
26
+ def characteristics=(value)
27
+ unless value.nil?
28
+ self[:characteristics] = value.map{|characteristic| Calculated::Models::Characteristic.new(characteristic)}
29
+ end
30
+ end
31
+
32
+ # setting the formula inputs to a defined model
33
+ def formula_inputs=(value)
34
+ unless value.nil?
35
+ self[:formula_inputs] = value.map{|formula| Calculated::Models::FormulaInput.new(formula)}
36
+ end
37
+ end
38
+
39
+ # setting the formula inputs to a defined model
40
+ def relatable_categories=(value)
41
+ unless value.nil?
42
+ self[:relatable_categories] = value.map{|relatable_category| Calculated::Models::RelatableCategory.new(relatable_category)}
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ module Calculated
2
+ module Models
3
+ class RelatableCategory < Hashie::Dash
4
+
5
+ # properties
6
+ property :id # [String]
7
+ property :name # [String]
8
+ property :related_attribute # [String]
9
+ property :related_object_name # [String]
10
+ # @example
11
+ # "emission_source" => {
12
+ # {
13
+ # "4c349f6068fe5434960178c2" => "flaring and venting",
14
+ # "4c349f6068fe54349601791f" => "fugitives",
15
+ # }
16
+ # }
17
+ property :related_categories # [Hash{name => <Hash{:id => identifier}}]
18
+
19
+
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module Calculated
2
+ module Models
3
+ class Source < Hashie::Dash
4
+
5
+ # properties
6
+ property :id # [String]
7
+ property :description # [String]
8
+ property :main_source_ids # [Array<String>]
9
+ property :external_url # [String]
10
+ property :wave_id # [String]
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,61 @@
1
+ module Calculated
2
+ module ObjectTemplateApiCalls
3
+
4
+ # @param [Hash] params
5
+ # @return [Array<Calculated::Models::ObjectTemplate>]
6
+ def object_templates(params = {})
7
+ api_call(:get, "/object_templates", params) do |response|
8
+ response["object_templates"].map{|object_template| Calculated::Models::ObjectTemplate.new(object_template)}
9
+ end
10
+ end
11
+
12
+
13
+ # this request will have loaded generic objects for the ready basically
14
+ # @param [String] name
15
+ # @param [Hash] params
16
+ # @return [Calculated::Models::ObjectTemplate]
17
+ def generic_objects_for_object_template(name, params = {})
18
+ api_call(:get, "/object_templates/#{name}/generic_objects", params) do |response|
19
+ Calculated::Models::ObjectTemplate.new(response["object_template"])
20
+ end
21
+ end
22
+
23
+ # this request will have loaded relatable categories for the object template
24
+ # @param [String] related_attribute
25
+ # @param [String] name
26
+ # @param [Hash] params
27
+ # @return [Calculated::Models::ObjectTemplate]
28
+ def relatable_categories_for_object_template(name, related_attribute, params = {})
29
+ api_call(:get, "/object_templates/#{name}/relatable_categories", params.merge!(:related_attribute => related_attribute)) do |response|
30
+ Calculated::Models::ObjectTemplate.new(response["object_template"])
31
+ end
32
+ end
33
+
34
+ # This will filter the results of the generic objects from a simple text search
35
+ # note this is not an expancive text search so limit to 1 word searches for best
36
+ # results
37
+ #
38
+ # @example
39
+ # generic_objects_for_object_template_with_filter('airport', 'london')
40
+ #
41
+ # There is also the usuage of relatable_category_values with the params
42
+ # this will allow further filtering on the search its an AND Filter not an OR filter
43
+ #
44
+ # @example
45
+ # searching for ford diesel cars for example
46
+ #
47
+ # generic_objects_for_object_template_with_filter('car', 'diesel', :relatable_category_values => ["ford"])
48
+ #
49
+ # this request will have loaded relatable categories for the object template
50
+ # @param [String] name
51
+ # @param [String] filter
52
+ # @param [Hash] params
53
+ # @return [Calculated::Models::GeneriObject]
54
+ def generic_objects_for_object_template_with_filter(name, filter, params = {})
55
+ api_call(:get, "/object_templates/#{name}/generic_objects/filter", params.merge!(:filter => filter)) do |response|
56
+ Calculated::Models::ObjectTemplate.new(response["object_template"])
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,38 @@
1
+ module Calculated
2
+ module RelatableCategoryApiCalls
3
+
4
+ # this call just beings back a native array with hash of ids and identifiers
5
+ # @example
6
+ #
7
+ # "4bf42d8b46a95925b5001a0c" => "Particle Board"
8
+ #
9
+ # @param [String] template_name
10
+ # @param [Array<String>] relatable_category_ids
11
+ # @param [Hash] params
12
+ # @return [Hash]
13
+ def related_objects_from_relatable_categories(template_name, relatable_category_ids, params = {})
14
+ relatable_category_ids = relatable_category_ids.is_a?(String) ? [relatable_category_ids] : relatable_category_ids
15
+ api_call(:get, "/relatable_categories/related_objects", params.merge!(:template_name => template_name, :relatable_category_ids => relatable_category_ids)) do |response|
16
+ response["related_objects"]
17
+ end
18
+ end
19
+
20
+
21
+
22
+ ## this call just beings back a native array with hash of ids and identifiers
23
+ # @example
24
+ #
25
+ # "4bf42d8a46a95925b5001999" => "timber"
26
+ #
27
+ # @param [String] id
28
+ # @param [String] related_attribute
29
+ # @param [Hash] params
30
+ # @return [Hash]
31
+ def related_categories_from_relatable_category(id, related_attribute, params = {})
32
+ api_call(:get, "/relatable_categories/#{id}/related_categories", params.merge!(:related_attribute => related_attribute)) do |response|
33
+ response["related_categories"]
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,51 @@
1
+ module Calculated
2
+ class Service
3
+ include HTTParty
4
+ format :json
5
+ headers 'Accept' => 'application/json'
6
+
7
+ # set the httparty defaults [this obviously makes 1 service] limitation me feels
8
+ def initialize(server, api_version, api_key)
9
+ self.class.base_uri "http://#{server}/api/#{api_version}"
10
+ self.class.default_params :api_key => api_key
11
+ end
12
+
13
+ def get(path, params = {})
14
+ perform_request(:get, path, params)
15
+ end
16
+
17
+ def post(path, params = {})
18
+ perform_request(:post, path, params)
19
+ end
20
+
21
+ private
22
+ def perform_request(type, path, params)
23
+ response = self.class.send(type, path, :query => params)
24
+ check_response(response)
25
+ response
26
+ rescue Errno::ECONNREFUSED, SocketError
27
+ raise Calculated::Session::ServerNotFound, "Carbon Calculated Server could not be found"
28
+ end
29
+
30
+ # checking the status code of the response; if we are not authenticated
31
+ # then authenticate the session
32
+ # @raise [Calculated::PermissionDenied] if the status code is 403
33
+ # @raise [Calculated::SessionExpired] if a we get a 401
34
+ # @raise [Calculated::MissingParameter] if we get something strange
35
+ def check_response(response)
36
+ case response.code
37
+ when 200, 201
38
+ true
39
+ when 401
40
+ raise Calculated::Session::PermissionDenied.new("Your Request could not be authenticated is your api key valid?")
41
+ when 404
42
+ raise Calculated::Session::NotFound.new("Resource was not found")
43
+ when 412
44
+ raise Calculated::Session::MissingParameter.new("Missing Parameter: #{response.body}")
45
+ else
46
+ raise Calculated::Session::UnknownError.new("super strange type unknown error: #{response.code} :body #{response.body}")
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,106 @@
1
+ require 'active_support/core_ext/object/to_query'
2
+ module Calculated
3
+ class Session
4
+
5
+ class CalculatedError < StandardError ;end
6
+ class Expired < CalculatedError; end
7
+ class UnAuthorized < CalculatedError; end
8
+ class NotAuthenticated < CalculatedError; end
9
+ class PermissionDenied < CalculatedError; end
10
+ class NotFound < CalculatedError; end
11
+ class ServerNotFound < CalculatedError; end
12
+ class MissingParameter < CalculatedError; end
13
+ class UnknownError < CalculatedError; end
14
+
15
+ # api calls that can be made on the session
16
+ include Calculated::GenericObjectApiCalls
17
+ include Calculated::ObjectTemplateApiCalls
18
+ include Calculated::RelatableCategoryApiCalls
19
+ include Calculated::AnswerApiCalls
20
+
21
+ # accessors
22
+ attr_accessor :cache, :caching, :logging, :server, :expires_in, :api_version
23
+
24
+ # creating a session one must supply the api_key as this is always required basically
25
+ # @param [Hash] options
26
+ # @return [Calculated::Session]
27
+ def self.create(options = {})
28
+ api_key = options.delete(:api_key)
29
+ raise ArgumentError.new("You need an API Key to save the planet") unless api_key
30
+ new(api_key, options)
31
+ end
32
+
33
+ # @param [String] api_key
34
+ # @param [Hash] options
35
+ # default options
36
+ # caching => true
37
+ # expires_in => 60*60*24
38
+ # cache => Moneta::Memory.new
39
+ # server => "api.carboncalculated.com"
40
+ # api_version => "v1"
41
+ # logging => true
42
+ def initialize(api_key, options)
43
+ @api_key = api_key
44
+ if @caching = options[:caching].nil? ? true : options.delete(:caching)
45
+ @expires_in = options.delete(:expires_in) || 60*60*24
46
+ @cache = options.delete(:cache) || Moneta::Memory.new
47
+ end
48
+ @server = options.delete(:server) || "api.carboncalculated.com"
49
+ @api_version = options.delete(:api_version) || "v1"
50
+ @logging = options[:logging].nil? ? true : options.delete(:caching)
51
+ end
52
+
53
+
54
+ # api calls
55
+ def api_call_without_logging(method, path, params = {}, &proc)
56
+ result = service.send(method, path, params)
57
+ result = yield result if block_given?
58
+ store_call(result, path, params || {}) if caching?
59
+ result
60
+ end
61
+
62
+ # if we caching and we have the same cache lets try and get the
63
+ # cache; otherwise we will make the request logging if need be
64
+ def api_call(method, path, params ={}, &proc)
65
+ if cache = caching? && (@cache[cache_key(path, params)])
66
+ return cache
67
+ else
68
+ if @logging
69
+ Calculated::Logging.log_calculated_api(method, path, params) do
70
+ api_call_without_logging(method, path, params, &proc)
71
+ end
72
+ else
73
+ api_call_without_logging(method, path, params, &proc)
74
+ end
75
+ end
76
+ end
77
+
78
+ def service
79
+ @service ||= Calculated::Service.new(@server, @api_version, @api_key)
80
+ end
81
+
82
+ def caching?
83
+ @caching
84
+ end
85
+
86
+ protected
87
+ # @param [String] path
88
+ # @param [Hash] params
89
+ # @return [String] the cache key from the path and the params
90
+ def cache_key(path, params = {})
91
+ parts = []
92
+ parts << path
93
+ parts << params.to_query
94
+ parts.join("/")
95
+ end
96
+
97
+ # @param [Object] result
98
+ # @param [String] path
99
+ # @param [Hash] params
100
+ def store_call(result, path, params)
101
+ key = cache_key(path, params ||{})
102
+ @cache.store(key, result, :expires_in => @expires_in)
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,3 @@
1
+ module Calculated
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: calculated
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Richard Hooker
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-07-14 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activesupport
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 3
29
+ - 0
30
+ - 0
31
+ - beta3
32
+ version: 3.0.0.beta3
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: httparty
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ - 6
45
+ - 1
46
+ version: 0.6.1
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: hashie
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ - 2
59
+ - 1
60
+ version: 0.2.1
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: moneta
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ - 6
73
+ - 0
74
+ version: 0.6.0
75
+ type: :runtime
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: tzinfo
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ - 3
87
+ - 22
88
+ version: 0.3.22
89
+ type: :runtime
90
+ version_requirements: *id005
91
+ description: makes using a simple api even more simple;
92
+ email:
93
+ - richard.hooker@carboncalculated.com
94
+ executables: []
95
+
96
+ extensions: []
97
+
98
+ extra_rdoc_files: []
99
+
100
+ files:
101
+ - lib/calculated/answer_api_calls.rb
102
+ - lib/calculated/generic_object_api_calls.rb
103
+ - lib/calculated/logging.rb
104
+ - lib/calculated/models/answer.rb
105
+ - lib/calculated/models/characteristic.rb
106
+ - lib/calculated/models/formula_input.rb
107
+ - lib/calculated/models/generic_object.rb
108
+ - lib/calculated/models/object_template.rb
109
+ - lib/calculated/models/relatable_category.rb
110
+ - lib/calculated/models/source.rb
111
+ - lib/calculated/object_template_api_calls.rb
112
+ - lib/calculated/relatable_category_api_calls.rb
113
+ - lib/calculated/service.rb
114
+ - lib/calculated/session.rb
115
+ - lib/calculated/version.rb
116
+ - lib/calculated.rb
117
+ - LICENSE
118
+ - CHANGELOG.md
119
+ - ROADMAP.md
120
+ has_rdoc: true
121
+ homepage: http://github.com/hookercookerman/calculated
122
+ licenses: []
123
+
124
+ post_install_message:
125
+ rdoc_options: []
126
+
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ segments:
141
+ - 1
142
+ - 3
143
+ - 6
144
+ version: 1.3.6
145
+ requirements: []
146
+
147
+ rubyforge_project: calculated
148
+ rubygems_version: 1.3.6
149
+ signing_key:
150
+ specification_version: 3
151
+ summary: A gem to use the carbon calculated api
152
+ test_files: []
153
+