eac-resourcify 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/lib/resourcify.rb +26 -0
- data/lib/resourcify/actions.rb +56 -0
- data/lib/resourcify/controller.rb +14 -0
- data/lib/resourcify/data_mapper/parents.rb +25 -0
- data/lib/resourcify/data_mapper/serialize_errors.rb +11 -0
- data/lib/resourcify/parent_relationship.rb +72 -0
- data/lib/resourcify/resource.rb +104 -0
- data/lib/resourcify/responses.rb +50 -0
- metadata +60 -0
data/lib/resourcify.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# make sure we're running inside Merb
|
2
|
+
if defined?(Merb::Plugins)
|
3
|
+
require 'extlib'
|
4
|
+
|
5
|
+
Merb::BootLoader.before_app_loads do
|
6
|
+
# require code that must be loaded before the application
|
7
|
+
require 'resourcify/data_mapper/parents'
|
8
|
+
require 'resourcify/data_mapper/serialize_errors'
|
9
|
+
::DataMapper::Model.append_extensions(Resourcify::DataMapper::Parents)
|
10
|
+
::DataMapper::Resource.append_inclusions(Resourcify::DataMapper::SerializeErrors)
|
11
|
+
|
12
|
+
require 'resourcify/controller'
|
13
|
+
require 'resourcify/resource'
|
14
|
+
require 'resourcify/actions'
|
15
|
+
require 'resourcify/responses'
|
16
|
+
require 'resourcify/parent_relationship'
|
17
|
+
Merb::Controller.send(:extend, Resourcify::Controller)
|
18
|
+
end
|
19
|
+
|
20
|
+
Merb::BootLoader.after_app_loads do
|
21
|
+
# code that can be required after the application loads
|
22
|
+
end
|
23
|
+
|
24
|
+
# Merb::Plugins.add_rakefiles "resourcify/merbtasks"
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Resourcify
|
2
|
+
module Actions
|
3
|
+
|
4
|
+
protected
|
5
|
+
|
6
|
+
# UI Actions
|
7
|
+
def new
|
8
|
+
only_provides :html
|
9
|
+
resource
|
10
|
+
render
|
11
|
+
end
|
12
|
+
|
13
|
+
def edit
|
14
|
+
only_provides :html
|
15
|
+
resource
|
16
|
+
render
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Verbs
|
22
|
+
|
23
|
+
def get
|
24
|
+
display resource
|
25
|
+
end
|
26
|
+
|
27
|
+
def put
|
28
|
+
if resource.save
|
29
|
+
put_successful
|
30
|
+
else
|
31
|
+
put_failed
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def post
|
36
|
+
if resource.save
|
37
|
+
post_successful
|
38
|
+
else
|
39
|
+
post_failed
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete
|
44
|
+
resource.destroy || raise(StandardError.new("Failed to destroy resource: #{resource.inspect}"))
|
45
|
+
delete_successful
|
46
|
+
end
|
47
|
+
|
48
|
+
# Quick compatiblity with Resourceful Routes
|
49
|
+
alias_method :index, :get
|
50
|
+
alias_method :show, :get
|
51
|
+
alias_method :destroy, :delete
|
52
|
+
alias_method :update, :put
|
53
|
+
alias_method :create, :post
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Resourcify
|
2
|
+
module DataMapper
|
3
|
+
module Parents
|
4
|
+
|
5
|
+
# FIXME Only works for single-field foreign keys
|
6
|
+
def parent_keys
|
7
|
+
parent_relationships.keys
|
8
|
+
end
|
9
|
+
|
10
|
+
# FIXME Not grabbing proper relationships
|
11
|
+
def parent_relationships
|
12
|
+
parent_relationships = {}
|
13
|
+
relationships.each do |relationship_name, relationship|
|
14
|
+
if relationship.child_model == self
|
15
|
+
parent_key = relationship.child_key.entries.first.field.to_sym
|
16
|
+
parent_relationships[parent_key] = relationship
|
17
|
+
end
|
18
|
+
end
|
19
|
+
parent_relationships
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Resourcify
|
2
|
+
module ParentRelationship
|
3
|
+
|
4
|
+
|
5
|
+
# e.g.
|
6
|
+
# class Person
|
7
|
+
# belongs_to :location
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# class Location
|
11
|
+
# has n, :people
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# access_by :location
|
15
|
+
#
|
16
|
+
# (Options)
|
17
|
+
# :collection => :person
|
18
|
+
#
|
19
|
+
def self.included(base)
|
20
|
+
base.class_eval do
|
21
|
+
class_inheritable_accessor :relationship_collections
|
22
|
+
self.relationship_collections = {}
|
23
|
+
|
24
|
+
def self.access_by(relationship, options = {})
|
25
|
+
options[:collection] ||= Extlib::Inflection.tableize(model_name_parts.last).to_sym
|
26
|
+
|
27
|
+
relationship_collections[relationship] = options[:collection]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def owner
|
35
|
+
collection || model
|
36
|
+
end
|
37
|
+
|
38
|
+
def parent
|
39
|
+
@parent ||= parent_relationship.parent_model.get!(params[parent_key]) if parent_relationship?
|
40
|
+
end
|
41
|
+
|
42
|
+
def collection(query = {})
|
43
|
+
if parent_relationship?
|
44
|
+
if association_name = relationship_collections[parent_relationship.name]
|
45
|
+
parent.send(association_name, query)
|
46
|
+
else
|
47
|
+
raise(ArgumentError.new(
|
48
|
+
"Parent relationship #{parent_relationship.name} found, but not marked as accessible.
|
49
|
+
Specify `access_by :#{parent_relationship.name}` for this controller."
|
50
|
+
))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def relationship_collections
|
56
|
+
self.class.relationship_collections
|
57
|
+
end
|
58
|
+
|
59
|
+
def parent_relationship?
|
60
|
+
!parent_relationship.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
def parent_relationship
|
64
|
+
@parent_relationship ||= model.parent_relationships[parent_key]
|
65
|
+
end
|
66
|
+
|
67
|
+
def parent_key
|
68
|
+
@parent_key ||= model.parent_keys.detect { |parent_key| params[parent_key] }
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Resourcify
|
2
|
+
module Resource
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
|
6
|
+
base.class_eval do
|
7
|
+
def self.model
|
8
|
+
Extlib::Inflection.constantize(model_name)
|
9
|
+
rescue NameError
|
10
|
+
raise NameError.new(
|
11
|
+
"Could not find a model named #{model_name}. Override #{self.name}.model_name with an existing class."
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def self.model_name
|
18
|
+
model_name_parts.join('::')
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.model_name_parts
|
22
|
+
name_parts = name.split('::')
|
23
|
+
model_name = name_parts.pop.singular
|
24
|
+
name_parts << model_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.resources_path
|
28
|
+
Extlib::Inflection.tableize(model_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# def self.inherited(subclass)
|
36
|
+
# subclass.model = Kernel.const_get(subclass.name.singular)
|
37
|
+
# end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
# Resources
|
42
|
+
|
43
|
+
def model
|
44
|
+
self.class.model
|
45
|
+
end
|
46
|
+
|
47
|
+
def resource_url
|
48
|
+
url(self.class.resources_path.singular.to_sym, resource.key)
|
49
|
+
end
|
50
|
+
|
51
|
+
def resource_collection_url
|
52
|
+
url(self.class.resources_path.to_sym)
|
53
|
+
end
|
54
|
+
|
55
|
+
def resource
|
56
|
+
@resource ||= assign_resource_instance_variable
|
57
|
+
end
|
58
|
+
|
59
|
+
def fetch_resource
|
60
|
+
case params[:action]
|
61
|
+
when *self.class.load_actions then load_resource
|
62
|
+
when *self.class.build_actions then build_resource
|
63
|
+
else
|
64
|
+
raise ArgumentError, "Unknown resource action #{params[:action].inspect}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_resource
|
69
|
+
parent ? owner.build(resource_params || {}) : owner.new(resource_params || {})
|
70
|
+
end
|
71
|
+
|
72
|
+
def load_resource
|
73
|
+
params[:id] ? owner.get!(params[:id]) : owner.all
|
74
|
+
end
|
75
|
+
|
76
|
+
def resource_params
|
77
|
+
params[model.name.snake_case]
|
78
|
+
end
|
79
|
+
|
80
|
+
# ParentRelationships overrides this method.
|
81
|
+
def owner
|
82
|
+
model
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
# FIXME Rewrite
|
88
|
+
# Equivelent to @users = User.all or @user = User.get!(id)
|
89
|
+
# TODO Dynamically create method?
|
90
|
+
# def resource #{singular_name} = fetch_resource end
|
91
|
+
# def resources #{plural_name} = fetch_resource end
|
92
|
+
def assign_resource_instance_variable
|
93
|
+
fetched_resource = fetch_resource
|
94
|
+
base_name = Extlib::Inflection.underscore(
|
95
|
+
Extlib::Inflection.demodulize(self.class.name)
|
96
|
+
).downcase
|
97
|
+
instance_variable_name = fetched_resource.is_a?(Array) ? "@#{base_name}" : "@#{base_name.singular}"
|
98
|
+
instance_variable_set(instance_variable_name, fetched_resource)
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Resourcify
|
2
|
+
module Responses
|
3
|
+
|
4
|
+
# Responses
|
5
|
+
# Success
|
6
|
+
def put_successful
|
7
|
+
case content_type
|
8
|
+
when :html then redirect(resource_url)
|
9
|
+
else
|
10
|
+
self.status = 204 # No Content
|
11
|
+
''
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def delete_successful
|
16
|
+
case content_type
|
17
|
+
when :html then redirect(resource_collection_url)
|
18
|
+
else
|
19
|
+
self.status = 204 # No Content
|
20
|
+
''
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def post_successful
|
25
|
+
case content_type
|
26
|
+
when :html then redirect(resource_url)
|
27
|
+
else
|
28
|
+
display(resource, :status => 201, :location => resource_url) # 201 Created
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Failure 422 Unproccessable entity
|
33
|
+
def post_failed
|
34
|
+
case content_type
|
35
|
+
when :html then render(:new, :status => 422)
|
36
|
+
else
|
37
|
+
display(resource, :status => 422)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def put_failed
|
42
|
+
case content_type
|
43
|
+
when :html then render(:edit, :status => 422)
|
44
|
+
else
|
45
|
+
display(resource, :status => 422)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eac-resourcify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eric Chapweske
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-09-29 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Basic enhancements for making Merb controllers more resourceful. Provides reduced code duplication, nested resource support, and aims for RFC2616 compliant responses.
|
17
|
+
email: eric@slantwisedesign.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- lib/resourcify.rb
|
26
|
+
- lib/resourcify/controller.rb
|
27
|
+
- lib/resourcify/actions.rb
|
28
|
+
- lib/resourcify/parent_relationship.rb
|
29
|
+
- lib/resourcify/resource.rb
|
30
|
+
- lib/resourcify/responses.rb
|
31
|
+
- lib/resourcify/data_mapper/parents.rb
|
32
|
+
- lib/resourcify/data_mapper/serialize_errors.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage:
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.8.6
|
45
|
+
version:
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
requirements:
|
53
|
+
- Install datamapper to get full functionality out of the box.
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.2.0
|
56
|
+
signing_key:
|
57
|
+
specification_version: 2
|
58
|
+
summary: Resourceful merb controllers.
|
59
|
+
test_files: []
|
60
|
+
|