service_crud 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown ADDED
@@ -0,0 +1,106 @@
1
+ # Service Crud
2
+
3
+ The `service_crud` gem: A simple mixin for adding crud actions for a RESTful, ActiveResource style service (xml and json).
4
+
5
+ ## Requirements
6
+
7
+ This gem works with Rails 3.
8
+
9
+ ## Installation
10
+
11
+ $ cd /path/to/your/rails3/app
12
+ $ echo "gem service_crud" >> Gemfile
13
+ $ bundle install
14
+
15
+ ## Usage
16
+
17
+ Let's suppose we have a "Book" model, and we want to create XML and JSON RESTful services for it. Simple:
18
+
19
+ First, go to your routes.rb file and add the following route:
20
+
21
+ resources :books
22
+
23
+ Next, create the following controller in RAILS_ROOT/app/books_controller.rb:
24
+
25
+ class BooksController
26
+ include ServiceCrud
27
+ end
28
+
29
+ That's it. You can now GET, POST, PUT, and DELETE books through the standard RESTful urls.
30
+
31
+ ## Callbacks
32
+
33
+ Sometimes you need to do a little extra work on your data before/after you create/update/destroy. And sometimes that can't be pushed down to the ORM layer.
34
+ For example, suppose we want to set the `:updated_by` property on our model to the `current_user`. We could simply:
35
+
36
+ class BooksController
37
+ include ServiceCrud
38
+ before_update :set_updated_by
39
+
40
+ private
41
+ def set_updated_by(model)
42
+ model.update_by = current_user
43
+ end
44
+ end
45
+
46
+ ServiceCrud supports the following callbacks: `before_create`, `after_create`, `before_update`, `after_update`, `before_destroy`, and `after_destroy`.
47
+
48
+ ## Model Guessing
49
+
50
+ The `service_crud` library will look at the controller name and try to guess the model (e.g., "BooksController" -> "Book").
51
+
52
+ If your controller name doesn't match your model, call the `model` method:
53
+
54
+ class MyBooksController
55
+ include ServiceCrud
56
+ model Book
57
+ end
58
+
59
+ ## PUT/POST parameter guessing
60
+
61
+ Similarly, on POST or PUT, `service_crud` assumes that the top-level node of the XML or JSON is the lowercased, underscored, singularized symbol of your model name.
62
+
63
+ If that's not the case for your service, call the `model_attribute_root` class method:
64
+
65
+ class BooksController
66
+ include ServiceCrud
67
+ model_attribute_root :my_book
68
+ end
69
+
70
+ ## ORM
71
+
72
+ The `service_crud` library assumes an ActiveRecord ORM by default. It also, out of the box, supports the `couchrest_model` ORM for couchdb.
73
+ To use `couchrest_model`, simply:
74
+
75
+ class BooksController
76
+ include ServiceCrud
77
+ orm_methods! ServiceCrud::CouchRest::Model
78
+ end
79
+
80
+ The default ORM methods are:
81
+
82
+ module ServiceCrud
83
+ module DefaultOrm
84
+ def all; :all; end
85
+ def new; :new; end
86
+ def find; :find; end
87
+ def destroy; :destroy; end
88
+ def update_attributes; :update_attributes; end
89
+ def save; :save; end
90
+ end
91
+ end
92
+
93
+ If you're using an ORM other than ActiveRecord or CouchRest::Model, and some or all of your ORM's method names differ from ActiveRecord's,
94
+ then simply create a module that redefines one or more DefaultOrm methods. For example, suppose we create our own ORM, `MoonOrm`, and our method for finding
95
+ records is `lookup` instead of `find`. Then we'd simply:
96
+
97
+ module MoonOrmMethods
98
+ def find; :lookup; end
99
+ end
100
+
101
+ Then, in our controller:
102
+
103
+ class BooksController
104
+ include ServiceCrud
105
+ orm_methods! MoonOrmMethods
106
+ end
@@ -0,0 +1,7 @@
1
+ module ServiceCrud
2
+ module CouchRest
3
+ module Model
4
+ def find; :get; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ module ServiceCrud
2
+ class DefaultOrm
3
+ def all; :all; end
4
+ def new; :new; end
5
+ def find; :find; end
6
+ def destroy; :destroy; end
7
+ def update_attributes; :update_attributes; end
8
+ def save; :save; end
9
+ end
10
+ end
@@ -0,0 +1,153 @@
1
+ module ServiceCrud
2
+
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def model(klass=nil)
9
+ @model ||= klass
10
+ @model || self.to_s.gsub("Controller", "").singularize.constantize
11
+ end
12
+
13
+ def model_attribute_root(root=nil)
14
+ @model_attribute_root ||= root
15
+ @model_attribute_root || self.model.to_s.underscore.to_sym
16
+ end
17
+
18
+ def orm_methods!(orm_module)
19
+ self.orm_methods.extend orm_module
20
+ end
21
+
22
+ def orm_methods
23
+ @orm_methods ||= ServiceCrud::DefaultOrm.new
24
+ end
25
+
26
+ def before_create(method=nil, &block)
27
+ self.before_creates << method if method
28
+ self.before_creates << block if block
29
+ end
30
+
31
+ def before_update(method=nil, &block)
32
+ self.before_updates << method if method
33
+ self.before_updates << block if block
34
+ end
35
+
36
+ def before_destroy(method=nil, &block)
37
+ self.before_destroys << method if method
38
+ self.before_destroys << block if block
39
+ end
40
+
41
+ def after_create(method=nil, &block)
42
+ self.after_creates << method if method
43
+ self.after_creates << block if block
44
+ end
45
+
46
+ def after_update(method=nil, &block)
47
+ self.after_updates << method if method
48
+ self.after_updates << block if block
49
+ end
50
+
51
+ def after_destroy(method=nil, &block)
52
+ self.after_destroys << method if method
53
+ self.after_destroys << block if block
54
+ end
55
+
56
+ def before_creates; @before_creates ||= []; end
57
+ def before_updates; @before_updates ||= []; end
58
+ def before_destroys; @before_destroys ||= []; end
59
+ def after_creates; @after_creates ||= []; end
60
+ def after_updates; @after_updates ||= []; end
61
+ def after_destroys; @after_destroys ||= []; end
62
+
63
+ end
64
+
65
+ # GET /your_model.xml
66
+ # GET /your_model.json
67
+ def index
68
+ @models = self.class.model.send self.class.orm_methods.all
69
+
70
+ respond_to do |format|
71
+ format.xml { render :xml => @models }
72
+ format.json { render :json => @models }
73
+ end
74
+ end
75
+
76
+ # GET /your_model/1.xml
77
+ # GET /your_model/1.json
78
+ def show
79
+ @model = self.class.model.send self.class.orm_methods.find, params[:id]
80
+
81
+ respond_to do |format|
82
+ format.xml { render :xml => @model }
83
+ format.json { render :json => @model }
84
+ end
85
+ end
86
+
87
+ # POST /your_model.xml
88
+ # POST /your_model.json
89
+ def create
90
+ @model = self.class.model.send self.class.orm_methods.new, params[self.class.model_attribute_root]
91
+ run_service_crud_before_callbacks @model
92
+
93
+ respond_to do |format|
94
+ if @model.send self.class.orm_methods.save
95
+ run_service_crud_after_callbacks @model
96
+ location = "/#{controller_name}/#{@model.id}"
97
+ format.xml { render :xml => @model, :status => :created, :location => location }
98
+ format.json { render :json => @model, :status => :created, :location => location }
99
+ else
100
+ format.xml { render :xml => @model.errors, :status => :unprocessable_entity }
101
+ format.json { render :json => {:errors => @model.errors.to_a}.to_json, :status => :unprocessable_entity }
102
+ end
103
+ end
104
+ end
105
+
106
+ # PUT /your_model/1.xml
107
+ # PUT /your_model/1.json
108
+ def update
109
+ @model = self.class.model.send self.class.orm_methods.find, params[:id]
110
+ run_service_crud_before_callbacks @model
111
+
112
+ respond_to do |format|
113
+ if @model.send self.class.orm_methods.update_attributes, params[self.class.model_attribute_root]
114
+ run_service_crud_after_callbacks @model
115
+ format.xml { head :ok }
116
+ format.json { head :ok }
117
+ else
118
+ format.xml { render :xml => @model.errors, :status => :unprocessable_entity }
119
+ format.json { render :json => {:errors => @model.errors.to_a}.to_json, :status => :unprocessable_entity }
120
+ end
121
+ end
122
+ end
123
+
124
+ # DELETE /your_model/1.xml
125
+ # DELETE /your_model/1.json
126
+ def destroy
127
+ @model = self.class.model.send self.class.orm_methods.find, params[:id]
128
+ run_service_crud_before_callbacks @model
129
+ @model.send self.class.orm_methods.destroy
130
+ run_service_crud_after_callbacks @model
131
+
132
+ respond_to do |format|
133
+ format.xml { head :ok }
134
+ format.json { head :ok }
135
+ end
136
+ end
137
+
138
+ private
139
+ def run_service_crud_before_callbacks(model)
140
+ run_service_crud_callbacks self.class.send("before_#{action_name}s".to_sym), model
141
+ end
142
+
143
+ def run_service_crud_after_callbacks(model)
144
+ run_service_crud_callbacks self.class.send("after_#{action_name}s".to_sym), model
145
+ end
146
+
147
+ def run_service_crud_callbacks(service_crud_callbacks, model)
148
+ service_crud_callbacks.each do |method|
149
+ method.call(model) if method.respond_to?(:call) # if it's a proc
150
+ self.send method, model if method.kind_of?(Symbol)
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,3 @@
1
+ require 'service_crud/default_orm'
2
+ require 'service_crud/couchrest_model'
3
+ require 'service_crud/service_crud'
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: service_crud
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Matt Parker
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-07 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rails
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 3
32
+ - 0
33
+ version: "3.0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: A simple mixin for providing crud actions for a RESTful, ActiveResource style service (xml and json).
37
+ email: moonmaster9000@gmail.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - README.markdown
44
+ files:
45
+ - README.markdown
46
+ - lib/service_crud.rb
47
+ - lib/service_crud/couchrest_model.rb
48
+ - lib/service_crud/default_orm.rb
49
+ - lib/service_crud/service_crud.rb
50
+ has_rdoc: true
51
+ homepage: http://github.com/moonmaster9000/service_crud
52
+ licenses: []
53
+
54
+ post_install_message:
55
+ rdoc_options:
56
+ - --charset=UTF-8
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.3.7
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: DRY service crud.
84
+ test_files: []
85
+