eac-resourcify 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,14 @@
1
+ module Resourcify
2
+ module Controller
3
+
4
+ def resourcify
5
+
6
+ include Resource
7
+ include Actions
8
+ include Responses
9
+ include ParentRelationship
10
+
11
+ end
12
+
13
+ end
14
+ 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,11 @@
1
+ module Resourcify
2
+ module DataMapper
3
+ module SerializeErrors
4
+
5
+ def serialize_properties
6
+ errors.blank? ? {} : { :errors => errors.send(:errors) }
7
+ end
8
+
9
+ end
10
+ end
11
+ 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
+