rack-backend-api 0.2.3 → 0.3.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/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
  =========
@@ -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
- link+delete_form
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,3]
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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rack-backend-api'
3
- s.version = "0.2.3"
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."
@@ -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
@@ -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: 17
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
9
8
  - 3
10
- version: 0.2.3
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-19 00:00:00 +01:00
18
+ date: 2011-08-25 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies: []
21
21