athena_resource 0.0.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.
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "athena_resource/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "athena_resource"
7
+ s.version = AthenaResource::VERSION
8
+ s.authors = ["Micah Frost"]
9
+ s.email = ["athena@fracturedatlas.org"]
10
+ s.homepage = "http://athena.fracturedatlas.org"
11
+ s.summary = %q{ ATHENA API Wrapper}
12
+ s.description = %q{ Easily consume ATHENA resources by subclasses AthenaResource }
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_development_dependency "rspec"
20
+ end
@@ -0,0 +1,16 @@
1
+ require 'active_support'
2
+ require 'active_resource'
3
+
4
+ require "athena_resource/version"
5
+
6
+ module AthenaResource
7
+ include ActiveResource
8
+
9
+ extend ActiveSupport::Autoload
10
+ autoload :Base
11
+ autoload :Encoding
12
+ autoload :Headers
13
+ autoload :AuthType
14
+ autoload :Callbacks
15
+ autoload :Finders
16
+ end
@@ -0,0 +1,15 @@
1
+ module AthenaResource
2
+ module AuthType
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def auth_type
7
+ if defined?(@auth_type)
8
+ @auth_type
9
+ elsif superclass != Object && superclass.auth_type
10
+ superclass.auth_type
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ require 'athena_resource/formats'
2
+
3
+ module AthenaResource
4
+ class Base < ActiveResource::Base
5
+ self.user = AthenaResource::USER
6
+ self.password = AthenaResource::PASSWORD
7
+ self.auth_type = AthenaResource::AUTH_TYPE
8
+
9
+ class << self
10
+ def patch(records, attributes)
11
+ response = connection.put(self.site.path + self.collection_name + "/patch/#{records.collect(&:id).join(",")}", attributes.to_json, self.headers)
12
+ format.decode(response.body).map{ |attributes| new(attributes) }
13
+ end
14
+ end
15
+
16
+ include Encoding
17
+ include AuthType
18
+ include Headers
19
+ include Callbacks
20
+ include Finders
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ module AthenaResource
2
+ module Callbacks
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ # Enable ActiveModel callbacks for models
7
+ extend ActiveModel::Callbacks
8
+ define_model_callbacks :save, :validation
9
+ end
10
+
11
+ module InstanceMethods
12
+ def save
13
+ run_callbacks :save do
14
+ super
15
+ end
16
+ end
17
+
18
+ # Note, that for the time being, validation callbacks are called after before_save, and before after_save
19
+ def valid?
20
+ run_callbacks :validation do
21
+ super
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ module AthenaResource
2
+ module Encoding
3
+ extend ActiveSupport::Concern
4
+ module ClassMethods
5
+ def format
6
+ read_inheritable_attribute(:format) || AthenaResource::Formats::AthenaFormat
7
+ end
8
+
9
+ def parameterize(params = {})
10
+ Hash[params.collect{|key, value| [key.camelize(:lower),value] }]
11
+ end
12
+ end
13
+
14
+ module InstanceMethods
15
+ def encode(options = {})
16
+ attrs = options.delete(:attributes) || attributes
17
+ return self.class.format.encode(attrs, options) if self.class.format.respond_to? :encode
18
+ super(options)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,42 @@
1
+ module AthenaResource
2
+ module Finders
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def search_index(search_query, organization, limit=10)
7
+ if search_query.blank?
8
+ search_query = ''
9
+ else
10
+ search_query.concat(' AND ')
11
+ end
12
+
13
+ search_query.concat("organizationId:").concat("#{organization.id}")
14
+ find(:all, :params => { '_q' => search_query, '_limit' => limit})
15
+ end
16
+
17
+ #Can be used when searching for a range because you can't dupe keys in a hash
18
+ #For example: datetime=lt2011-03-02&datetime=gt2010-05-05
19
+ def query(query_str)
20
+
21
+ #Neither CGI::Escape nor URI.escape worked here
22
+ #CGI::escape escaped everything and ATHENA threw 400
23
+ #URI.escape failed to change the + to %2B which is really the only thing I wanted it to do
24
+ query_str.gsub!(/\+/,'%2B')
25
+
26
+ connection.get(self.collection_path + "?" + query_str, self.headers)
27
+ end
28
+
29
+ # This method will translate find_by_some_object_id into ...?someObjectId=9
30
+ def method_missing(method_id, *arguments)
31
+ if method_id.to_s =~ /find_by_(\w+)/
32
+ arg = arguments[0]
33
+ term = $1.camelcase(:lower)
34
+
35
+ find(:all, :params => { term => arg })
36
+ else
37
+ super
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveResource
2
+ module Formats
3
+ autoload :XmlFormat, 'active_resource/formats/xml_format'
4
+ autoload :JsonFormat, 'active_resource/formats/json_format'
5
+ autoload :AthenaFormat, 'athena_resource/formats/athena_format'
6
+
7
+ # Lookup the format class from a mime type reference symbol. Example:
8
+ #
9
+ # ActiveResource::Formats[:xml] # => ActiveResource::Formats::XmlFormat
10
+ # ActiveResource::Formats[:json] # => ActiveResource::Formats::JsonFormat
11
+ def self.[](mime_type_reference)
12
+ ActiveResource::Formats.const_get(ActiveSupport::Inflector.camelize(mime_type_reference.to_s) + "Format")
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,90 @@
1
+ require 'active_support/json'
2
+
3
+ module ActiveResource
4
+ module Formats
5
+ module AthenaFormat
6
+ extend self
7
+
8
+ def extension
9
+ "json"
10
+ end
11
+
12
+ def mime_type
13
+ "application/json"
14
+ end
15
+
16
+ def encode(hash, options = {})
17
+ rejections = options.delete :rejections || []
18
+ hash = hash.reject { | k , v | rejections.include? k } unless rejections.nil?
19
+
20
+ results = encode_athena(hash)
21
+ results = ActiveSupport::JSON.encode(results, options) unless options.delete(:skip_serialization)
22
+
23
+ results
24
+ end
25
+
26
+ def decode(json)
27
+ decode_athena(ActiveSupport::JSON.decode(json))
28
+ end
29
+
30
+ private
31
+ def decode_athena(payload)
32
+ if payload.is_a? Array
33
+ payload.collect { |element| underscore_keys(element) }
34
+ else
35
+ underscore_keys(payload)
36
+ end
37
+ end
38
+
39
+ def underscore_keys(payload)
40
+ if payload.is_a? Hash
41
+ underscored_payload = {}
42
+ payload.each do |key, value|
43
+ if value.kind_of? Hash
44
+ underscored_payload[key.underscore] = underscore_keys(value)
45
+ elsif value.kind_of? Array
46
+ underscored_payload[key.underscore] = value.collect { |v| underscore_keys(v) }
47
+ else
48
+ underscored_payload[key.underscore] = value
49
+ end
50
+ end
51
+ underscored_payload
52
+ else
53
+ if payload.respond_to? :attributes
54
+ underscore_keyes(payload.attributes)
55
+ else
56
+ payload
57
+ end
58
+ end
59
+ end
60
+
61
+ def encode_athena(hash)
62
+ camelize_keys(hash)
63
+ end
64
+
65
+ def camelize_keys(hash_or_model)
66
+ if hash_or_model.respond_to? :encode and hash_or_model.respond_to? :attributes
67
+ return hash_or_model.encode(:skip_serialization => true)
68
+ end
69
+
70
+ if hash_or_model.is_a? Hash
71
+ camelized_hash = {}
72
+
73
+ hash_or_model.each do |key, value|
74
+ if value.kind_of? Hash
75
+ camelized_hash[key.camelize(:lower)] = camelize_keys(value)
76
+ elsif value.kind_of? Array
77
+ camelized_hash[key.camelize(:lower)] = value.collect{ |v| camelize_keys(v) }
78
+ else
79
+ camelized_hash[key.camelize(:lower)] = camelize_keys(value)
80
+ end
81
+ end
82
+ camelized_hash
83
+ else
84
+ hash_or_model
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+
@@ -0,0 +1,17 @@
1
+ module AthenaResource
2
+ module Headers
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ headers["User-agent"] = AthenaResource::USER_AGENT || ""
7
+ end
8
+
9
+ module ClassMethods
10
+ def headers
11
+ @headers ||= (superclass.headers.try(:dup) || {})
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+
@@ -0,0 +1,3 @@
1
+ module AthenaResource
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ class Foo < AthenaResource::Base
4
+ end
5
+
6
+ class Bar < AthenaResource::Base
7
+ self.auth_type = "basic"
8
+ end
9
+
10
+ describe AthenaResource::AuthType do
11
+ describe "subclasses" do
12
+ it "allow for separate auth types per subclass" do
13
+ Foo.auth_type.should eq nil
14
+ Bar.auth_type.should eq "basic"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ class CallbackResource < AthenaResource::Base
4
+ self.site = "http://localhost"
5
+ before_save :foo
6
+ after_save :bar
7
+
8
+ before_validation :baz
9
+ after_validation :bat
10
+
11
+ def history
12
+ @history ||= []
13
+ end
14
+
15
+ def foo; history << :foo; end
16
+ def bar; history << :bar; end
17
+ def baz; history << :baz; end
18
+ def bat; history << :bat; end
19
+ end
20
+
21
+ describe AthenaResource::Callbacks do
22
+ before(:all) do
23
+ ActiveResource::HttpMock.respond_to do |mock|
24
+ mock.post "/callback_resources.json", {"Authorization"=>"Basic dGVzdGVyOnBhc3N3b3Jk", "Content-Type"=>"application/json", "User-agent"=>"TestingAgent"}, ""
25
+ end
26
+ end
27
+
28
+ describe "#save callbacks" do
29
+ subject { CallbackResource.new }
30
+
31
+ before(:each) do
32
+ subject.save
33
+ end
34
+
35
+ it "calls before save methods before calling save" do
36
+ subject.history.first.should eq :foo
37
+ end
38
+
39
+ it "calls after save methods after calling save" do
40
+ subject.history.last.should eq :bar
41
+ end
42
+
43
+ it "calls calls each method in order" do
44
+ subject.history.should eq [ :foo, :baz, :bat, :bar ]
45
+ end
46
+ end
47
+
48
+ describe "#save callbacks" do
49
+ subject { CallbackResource.new }
50
+
51
+ before(:each) do
52
+ subject.valid?
53
+ end
54
+
55
+ it "calls before save methods before calling save" do
56
+ subject.history.first.should eq :baz
57
+ end
58
+
59
+ it "calls after save methods after calling save" do
60
+ subject.history.last.should eq :bat
61
+ end
62
+
63
+ it "calls calls each method in order" do
64
+ subject.history.should eq [ :baz, :bat ]
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ class Foo < AthenaResource::Base
4
+ end
5
+
6
+ class Bar < AthenaResource::Base
7
+ end
8
+
9
+ describe AthenaResource::Headers do
10
+
11
+ subject { AthenaResource::Base.new }
12
+
13
+ it "sets the default user User agent" do
14
+ subject.class.headers['User-agent'].should eq "TestingAgent"
15
+ end
16
+
17
+ describe "subclasses" do
18
+ it "allow for separate user agents per subclass" do
19
+ Foo.headers['User-agent'] = "FooAgent"
20
+ Bar.headers['User-agent'].should eq "TestingAgent"
21
+ Bar.headers['User-agent'].should_not eq "FooAgent"
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,6 @@
1
+ require 'athena_resource'
2
+
3
+ AthenaResource::USER_AGENT = "TestingAgent"
4
+ AthenaResource::USER = "tester"
5
+ AthenaResource::PASSWORD = "password"
6
+ AthenaResource::AUTH_TYPE = nil
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: athena_resource
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Micah Frost
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-07-29 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :development
25
+ version_requirements: *id001
26
+ description: " Easily consume ATHENA resources by subclasses AthenaResource "
27
+ email:
28
+ - athena@fracturedatlas.org
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files: []
34
+
35
+ files:
36
+ - .gitignore
37
+ - .rspec
38
+ - Gemfile
39
+ - Rakefile
40
+ - athena_resource.gemspec
41
+ - lib/athena_resource.rb
42
+ - lib/athena_resource/auth_type.rb
43
+ - lib/athena_resource/base.rb
44
+ - lib/athena_resource/callbacks.rb
45
+ - lib/athena_resource/encoding.rb
46
+ - lib/athena_resource/finders.rb
47
+ - lib/athena_resource/formats.rb
48
+ - lib/athena_resource/formats/athena_format.rb
49
+ - lib/athena_resource/headers.rb
50
+ - lib/athena_resource/version.rb
51
+ - spec/athena_resource/auth_type_spec.rb
52
+ - spec/athena_resource/callbacks_spec.rb
53
+ - spec/athena_resource/headers_spec.rb
54
+ - spec/spec_helper.rb
55
+ homepage: http://athena.fracturedatlas.org
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.8.5
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: ATHENA API Wrapper
82
+ test_files:
83
+ - spec/athena_resource/auth_type_spec.rb
84
+ - spec/athena_resource/callbacks_spec.rb
85
+ - spec/athena_resource/headers_spec.rb
86
+ - spec/spec_helper.rb