Skip to content

Commit 7310672

Browse files
committed
first commit
0 parents  commit 7310672

12 files changed

+1019
-0
lines changed

MIT-LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2008 Medical Decision Logic
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.

README

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
HyperactiveResource
2+
===================
3+
4+
Many have said that ActiveResource is not really "complete". On the surface, this means that some features that are documented aren't implemented. Digging a little deeper, we find that some features that should exist don't.
5+
6+
Arguably, a "complete" ActiveResource would behave like ActiveRecord or, as the rdoc for ActiveResource states "very similarly to Active Record".
7+
8+
Hyperactive Resource is MDL's extension to ActiveResource::Base written to support our Patient Registry and goes a long way towards the goal of an ActiveResource that behaves like ActiveRecord.
9+
10+
Features
11+
* Client side validations
12+
* Hooks for before_validate, before_save
13+
* Dynamic finders: find_by_X
14+
* save!
15+
* Awareness of associations between resources: belongs_to, has_many, has_one & columns
16+
* Patient.new.name returns nil instead of MethodMissing
17+
* Patient.new.races returns [] instead of MethodMissing
18+
* pat = Patient.new; pat.gender_id = 1; pat.gender #Will return find the gender obj
19+
* Resources can be associated with records
20+
* Records can be associated with records
21+
* ActiveRecord-like attributes= (updates rather than replaces)
22+
* ActiveRecord-like #load that doesn't #dup attributes (stores direct reference)
23+
* Supports saving resources that :include other resources via:
24+
* Nested resource saving (creating a patient will create their associated addresses)
25+
* Mapping associations ([:gender].id will serialize as :gender_id)
26+
27+
Example
28+
=======
29+
30+
1. Install the plugin via: (insert svn commands here)
31+
32+
2. Create a HyperactiveResource where you would normally use ActiveResource and define the meta-data/associations that drive the dynamic magic:
33+
34+
class Address < HyperactiveResource
35+
self.columns = [ :street_address, :city, :zipcode, :home_phone_number ]
36+
self.belong_tos = [ :country, :state ]
37+
self.has_manys = [ :people ]
38+
end
39+
40+
3. Enjoy the magic
41+
42+
address = Address.new
43+
address.country # nil instead of method_missing
44+
address.country_id = 5
45+
address.country #Returns Country.find(5)
46+
etc..
47+
48+
Copyright (c) 2008 Medical Decision Logic, released under the MIT license

Rakefile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
require 'rake'
2+
require 'rake/testtask'
3+
require 'rake/rdoctask'
4+
5+
desc 'Default: run unit tests.'
6+
task :default => :test
7+
8+
desc 'Test the hyperactive_resource plugin.'
9+
Rake::TestTask.new(:test) do |t|
10+
t.libs << 'lib'
11+
t.pattern = 'test/**/*_test.rb'
12+
t.verbose = true
13+
end
14+
15+
desc 'Generate documentation for the hyperactive_resource plugin.'
16+
Rake::RDocTask.new(:rdoc) do |rdoc|
17+
rdoc.rdoc_dir = 'rdoc'
18+
rdoc.title = 'HyperactiveResource'
19+
rdoc.options << '--line-numbers' << '--inline-source'
20+
rdoc.rdoc_files.include('README')
21+
rdoc.rdoc_files.include('lib/**/*.rb')
22+
end

init.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Include hook code here

install.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Install hook code here

lib/cross_associated_model.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
module CrossAssociatedModel
2+
def self.included(mod)
3+
mod.extend(CrossAssociatedModelClassMethods)
4+
end
5+
6+
module CrossAssociatedModelClassMethods
7+
8+
#The base implementation assumes a resource that references a record
9+
def belongs_to_record( name )
10+
#Assumes this record has a "name_id" and that a "Name" exists that is an active_record
11+
instance_var = "@#{name}"
12+
13+
define_method( name ) do
14+
association_id = send("#{name}_id")
15+
resource_class = name.to_s.classify.constantize
16+
17+
if association_id == 0 or association_id.nil?
18+
return nil
19+
elsif instance_variable_get(instance_var).nil?
20+
instance_variable_set( instance_var, resource_class.find(association_id) )
21+
end
22+
instance_variable_get(instance_var)
23+
end
24+
25+
define_method( "#{name}=" ) do |new_associated_resource|
26+
instance_variable_set( instance_var, new_associated_resource )
27+
send("#{name}_id=", (new_associated_resource.nil? ? nil : new_associated_resource.id))
28+
end
29+
end
30+
31+
#The base implementation assumes a resource that references many record
32+
def has_many_records( name )
33+
#Assumes this record has a "name_ids" and that a "Name" exists that is an active_record
34+
instance_var = "@#{name}"
35+
36+
define_method( name ) do
37+
resource_class = name.to_s.classify.constantize
38+
finder_method = "find_all_by_#{self.class.name.tableize.singularize}_id"
39+
40+
if instance_variable_get(instance_var).nil?
41+
instance_variable_set( instance_var, resource_class.send( finder_method, self.id ) )
42+
end
43+
instance_variable_get(instance_var)
44+
end
45+
end
46+
47+
alias_method :belongs_to_resource, :belongs_to_record
48+
alias_method :has_many_resources, :has_many_records
49+
end
50+
end

lib/http_mock_mod.rb

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
require 'active_resource/connection'
2+
3+
module ActiveResource
4+
class InvalidRequestError < StandardError; end #:nodoc:
5+
6+
class HttpMock
7+
class ResponderWithLoc < Responder
8+
for method in [ :post ]
9+
module_eval <<-EOE
10+
def #{method}(path, request_headers = {}, body = nil, status = 200, response_headers = {}, response_body = nil, location = nil)
11+
@responses[Request.new(:#{method}, path, nil, request_headers)] = ResponseWithLoc.new(response_body || body || "", status, response_headers, location)
12+
end
13+
EOE
14+
end
15+
end
16+
17+
class << self
18+
def respond_to_with_location(pairs = {})
19+
reset!
20+
pairs.each do |(path, response)|
21+
responses[path] = response
22+
end
23+
24+
if block_given?
25+
yield ResponderWithLoc.new(responses)
26+
else
27+
ResponderWithLoc.new(responses)
28+
end
29+
end
30+
end
31+
32+
for method in [ :post, :put ] # try to remove the authorization info from @request.headers
33+
module_eval <<-EOE
34+
def #{method}(path, body, headers)
35+
request = ActiveResource::Request.new(:#{method}, path, body, headers)
36+
request.headers.delete('Authorization')
37+
self.class.requests << request
38+
self.class.responses[request] || raise(InvalidRequestError.new("No response recorded for: \#{request.inspect}"))
39+
end
40+
EOE
41+
end
42+
43+
for method in [ :get, :delete ]
44+
module_eval <<-EOE
45+
def #{method}(path, headers)
46+
request = ActiveResource::Request.new(:#{method}, path, nil, headers)
47+
request.headers.delete('Authorization')
48+
self.class.requests << request
49+
self.class.responses[request] || raise(InvalidRequestError.new("No response recorded for: \#{request.inspect}"))
50+
end
51+
EOE
52+
end
53+
54+
end
55+
56+
class ResponseWithLoc < Response
57+
attr_accessor :location
58+
59+
def initialize(body, message = 200, headers = {}, location=nil)
60+
@body, @message, @headers = body, message.to_s, headers
61+
@code = @message[0,3].to_i
62+
self['Location'] = location if location
63+
64+
resp_cls = Net::HTTPResponse::CODE_TO_OBJ[@code.to_s]
65+
if resp_cls && !resp_cls.body_permitted?
66+
@body = nil
67+
end
68+
69+
if @body.nil?
70+
self['Content-Length'] = "0"
71+
else
72+
self['Content-Length'] = body.size.to_s
73+
end
74+
end
75+
end
76+
end

0 commit comments

Comments
 (0)