rack-backend-api 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -0
- data/example/basic_admin.rb +2 -1
- data/lib/backend_api.rb +6 -1
- data/lib/sequel_rack_backend_api_adapter.rb +8 -1
- data/rack-backend-api.gemspec +1 -1
- data/test/spec_backend_api.rb +20 -0
- data/test/spec_sequel_adapter.rb +19 -0
- metadata +4 -4
data/README.md
CHANGED
@@ -256,14 +256,17 @@ Here are the methods to implement, most of them are just aliases for having a si
|
|
256
256
|
- `Model::backend_post( hash-of-values )` Generally equivalent to Model::new, it creates a new entry with provided values and without validating or saving
|
257
257
|
- `Model#backend_delete` Instance method that destroys the entry
|
258
258
|
- `Model#backend_put( hash-of-values )` Generally equivalent to Model::update, it updates an existing entry with provided values and without validating or saving
|
259
|
+
- `Model#backend_values` returns a Hash with the values of the entry
|
259
260
|
|
260
261
|
Others are slightly more sophisticated:
|
261
262
|
|
262
263
|
- `Model#backend_save?` Returns true if the entry is validated and saved. It generally triggers the error messages for the form as well.
|
263
264
|
- `Model#default_backend_columns` This the list of columns in the forms when the list of fields is not provided via `fields` option
|
265
|
+
- `Model#cloning_backend_columns` Default columns used when cloning (allows to get rid of fields like images that you may not wish to clone).
|
264
266
|
- `Model#backend_form( action_url, columns=nil, options={} )` It is only the wrapping of the form without the actual fields. Try to implement it like the Sequel one.
|
265
267
|
- `Model#backend_fields( columns )` These are the actual fields. There is a default behaviour that basically puts a `textarea` for everything. That works in most cases but this is meant to be overridden for a better solution. We recommend [Crushyform](https://rubygems.org/gems/sequel-crushyform) for Sequel because we did it so we know it plays well with BackendAPI, and also because you don't have anything more to do. BackendAPI knows you have [Crushyform](https://rubygems.org/gems/sequel-crushyform) and use it to create the fields.
|
266
268
|
- `Model#backend_delete_form( action_url, options={})` Basically sugar for Model#backend_form but with an empty array for columns, and these options `{:submit_text=>'X', :method=>'DELETE'}` predefined which you can override. We've seen before that it is for creating DELETE forms.
|
269
|
+
- `Model#backend_clone_form( action_url, options={})` Like delete form, but for cloning an entry.
|
267
270
|
- `Model#backend_show` What is sent when PUT or POST is successful and there is no `_destination`. Default is `'OK'`
|
268
271
|
- `Model::sort( array-of-ids )` It is used to do a bulk update of the position field, hence: re-order
|
269
272
|
|
@@ -295,6 +298,7 @@ CHANGE LOG
|
|
295
298
|
0.2.1 Have a title in forms + Only use `_method` if not POST
|
296
299
|
0.2.2 Backend form should accept a block for populating the fields
|
297
300
|
0.2.3 Send a 404 if the entry does not exist
|
301
|
+
0.3.0 Implement cloning functionality
|
298
302
|
|
299
303
|
COPYRIGHT
|
300
304
|
=========
|
data/example/basic_admin.rb
CHANGED
@@ -22,7 +22,8 @@ BASIC_ADMIN = proc{
|
|
22
22
|
api_inst_path = "%s/%s" % [api_model_path,m.id]
|
23
23
|
link = "<a href='%s?_destination=%s&_submit_text=UPDATE'>%s</a>\n" % [api_inst_path,escaped_path,m.to_label]
|
24
24
|
delete_form = m.backend_delete_form(api_inst_path, {:destination=>path})
|
25
|
-
|
25
|
+
clone_form = m.backend_clone_form(api_model_path, {:destination=>path})
|
26
|
+
link+clone_form+delete_form
|
26
27
|
end.join
|
27
28
|
[200,{'Content-Type'=>'text/html'},[title,create_link,list]]
|
28
29
|
}
|
data/lib/backend_api.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class BackendAPI
|
2
|
-
VERSION = [0,
|
2
|
+
VERSION = [0,3,0]
|
3
3
|
WRAP = <<-EOT
|
4
4
|
<!doctype html>
|
5
5
|
<html>
|
@@ -83,6 +83,11 @@ class BackendAPI
|
|
83
83
|
if !@model_name.nil? && ::Object.const_defined?(@model_class_name)
|
84
84
|
@model_class = Kernel.const_get(@model_class_name)
|
85
85
|
@model_instance = @model_class.backend_get(@id.to_i) unless @id.nil?
|
86
|
+
@clone_instance = @model_class.backend_get(@req['clone_id'].to_i) unless @req['clone_id'].nil?
|
87
|
+
unless @clone_instance.nil?
|
88
|
+
@req['fields'] ||= @clone_instance.cloning_backend_columns.map{|k|k.to_s}
|
89
|
+
@req['model'] = @clone_instance.backend_values.select{|k,v| @req['fields'].include?(k.to_s)}
|
90
|
+
end
|
86
91
|
@req['model'] ||= {}
|
87
92
|
send_404 if @model_instance.nil?&&!@id.nil?
|
88
93
|
else
|
@@ -18,6 +18,7 @@ module ::Sequel::Plugins::RackBackendApiAdapter
|
|
18
18
|
end
|
19
19
|
alias backend_delete destroy
|
20
20
|
alias backend_put set
|
21
|
+
alias backend_values values
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
@@ -47,7 +48,12 @@ module ::Sequel::Plugins::RackBackendApiAdapter
|
|
47
48
|
o
|
48
49
|
end
|
49
50
|
|
50
|
-
def backend_delete_form(url, opts={}); backend_form(url, [], {:submit_text=>'X', :method=>'DELETE'}.update(opts)); end
|
51
|
+
def backend_delete_form(url, opts={}); backend_form(url, [], {:submit_text=>'X', :method=>'DELETE'}.update(opts)){}; end
|
52
|
+
def backend_clone_form(url, opts={})
|
53
|
+
backend_form(url, [], {:submit_text=>'CLONE', :method=>'POST'}.update(opts)) do |out|
|
54
|
+
out << "<input type='hidden' name='clone_id' value='#{self.id}' />\n"
|
55
|
+
end
|
56
|
+
end
|
51
57
|
|
52
58
|
def backend_form_title
|
53
59
|
n = self.respond_to?(:to_label) ? self.to_label : self.backend_to_label
|
@@ -73,6 +79,7 @@ module ::Sequel::Plugins::RackBackendApiAdapter
|
|
73
79
|
|
74
80
|
# Can be overridden
|
75
81
|
def default_backend_columns; columns - [:id]; end
|
82
|
+
def cloning_backend_columns; default_backend_columns; end
|
76
83
|
def backend_show; 'OK'; end
|
77
84
|
|
78
85
|
end
|
data/rack-backend-api.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rack-backend-api'
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.3.0"
|
4
4
|
s.platform = Gem::Platform::RUBY
|
5
5
|
s.summary = "A Rack middleware that provides a simple API for your Admin section"
|
6
6
|
s.description = "The purpose of this Rack Middleware is to provide an API that interfaces with database actions in order to build a CMS."
|
data/test/spec_backend_api.rb
CHANGED
@@ -154,6 +154,26 @@ describe 'API Post' do
|
|
154
154
|
res.body.should==('<!-- '+compared.backend_form('/haiku',['title'], {:no_wrap=>'true'})+' -->')
|
155
155
|
res.body.should.match(/name='_no_wrap'.*value='true'/)
|
156
156
|
end
|
157
|
+
|
158
|
+
should 'be able to handle cloning with fields provided' do
|
159
|
+
res = req_lint(BackendAPI.new).post('/haiku', :params => {'clone_id' => '1', 'fields' => ['body']})
|
160
|
+
res.status.should==201
|
161
|
+
cloned = Haiku[1]
|
162
|
+
haiku = Haiku.order(:id).last
|
163
|
+
haiku.id.should.not==cloned.id
|
164
|
+
haiku.title.should==nil
|
165
|
+
haiku.body.should==cloned.body
|
166
|
+
end
|
167
|
+
|
168
|
+
should 'be able to handle cloning using cloning_backend_columns' do
|
169
|
+
res = req_lint(BackendAPI.new).post('/haiku', :params => {'clone_id' => '1'})
|
170
|
+
res.status.should==201
|
171
|
+
cloned = Haiku[1]
|
172
|
+
haiku = Haiku.order(:id).last
|
173
|
+
haiku.id.should.not==cloned.id
|
174
|
+
haiku.title.should==cloned.title
|
175
|
+
haiku.body.should==cloned.body
|
176
|
+
end
|
157
177
|
end
|
158
178
|
|
159
179
|
describe 'API Get' do
|
data/test/spec_sequel_adapter.rb
CHANGED
@@ -16,6 +16,10 @@ describe 'Sequel Adapter' do
|
|
16
16
|
Haiku.new.default_backend_columns.should==(Haiku.columns - [:id])
|
17
17
|
end
|
18
18
|
|
19
|
+
should 'Define Model#cloning_backend_columns' do
|
20
|
+
Haiku.new.cloning_backend_columns.should==(Haiku.columns - [:id])
|
21
|
+
end
|
22
|
+
|
19
23
|
should 'Make forms for the correct action' do
|
20
24
|
Haiku.new.backend_form('/url').should.match(/action='\/url'/)
|
21
25
|
end
|
@@ -82,6 +86,14 @@ describe 'Sequel Adapter' do
|
|
82
86
|
form.scan(/input/).size.should==4
|
83
87
|
end
|
84
88
|
|
89
|
+
should 'Have a backend_clone_form method - pure HTTP way of cloning records with HTTP POST method' do
|
90
|
+
form = Haiku.first.backend_clone_form('/url')
|
91
|
+
form.should.match(/name='_method' value='POST'/)
|
92
|
+
form.should.match(/<input type='submit' name='save' value='CLONE' \/>/)
|
93
|
+
form.should.match(/name='clone_id' value='#{Haiku.first.id}'/)
|
94
|
+
form.scan(/input/).size.should==4
|
95
|
+
end
|
96
|
+
|
85
97
|
should "Be able to sort entries with a list of IDs" do
|
86
98
|
TopFive.sort([2,3,1,5,4])
|
87
99
|
TopFive.order(:position).map(:flavour).should==['Vanilla','Chocolate','Strawberry','Apricot','Coconut']
|
@@ -110,6 +122,13 @@ describe 'Sequel Adapter' do
|
|
110
122
|
Author[1].backend_form('/url').should.match(/#{Regexp.escape(Author[1].backend_form_title)}/)
|
111
123
|
end
|
112
124
|
|
125
|
+
should 'Not include a title on delete and clone forms' do
|
126
|
+
form = Haiku.first.backend_delete_form('/url')
|
127
|
+
form.should.not.match(/<h2>/)
|
128
|
+
form = Haiku.first.backend_clone_form('/url')
|
129
|
+
form.should.not.match(/<h2>/)
|
130
|
+
end
|
131
|
+
|
113
132
|
should 'Yield the given block to populate the form fields' do
|
114
133
|
Author[1].backend_form('/url'){|out| out << '<!-- YIELDED -->'}.should.match(/<!-- YIELDED -->/)
|
115
134
|
Author[1].backend_form('/url', [:name]){|out|}.should.not.match(/#{Regexp.escape Author[1].crushyfield(:name)}/)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-backend-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 2
|
9
8
|
- 3
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mickael Riga
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-08-
|
18
|
+
date: 2011-08-25 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|