calculated 0.1.0

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/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
+