reststop 0.4.1 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -0
- data/LICENSE.txt +22 -165
- data/Manifest.txt +0 -2
- data/README.txt +29 -19
- data/Rakefile +0 -2
- data/examples/blog.rb +335 -280
- data/lib/reststop.rb +393 -408
- data/lib/reststop/version.rb +1 -1
- metadata +29 -9
- data/test/reststop_test.rb +0 -11
- data/test/test_helper.rb +0 -2
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 0.5.1 :: 2010-06-09
|
2
|
+
* Update to align with the post 2.0 enhancements in Camping related to Tilt support.
|
3
|
+
Since Tilt support is now checking for the existing of view methods and Tilt views
|
4
|
+
RESTstop needs to ensure that view methods can be looked up in Views:HTML as opposed to Views.
|
5
|
+
|
6
|
+
=== 0.5.0 :: 2010-04-07
|
7
|
+
|
8
|
+
* Major refactoring for compatibility with Camping 2.0. Thanks to Philippe Monnet
|
9
|
+
for completing the work.
|
10
|
+
|
1
11
|
=== 0.4.1 :: 2009-05-08
|
2
12
|
|
3
13
|
* Custom actions should now work again (needed to make some more changes for
|
data/LICENSE.txt
CHANGED
@@ -1,165 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
by the Library, but which is not otherwise based on the Library.
|
24
|
-
Defining a subclass of a class defined by the Library is deemed a mode
|
25
|
-
of using an interface provided by the Library.
|
26
|
-
|
27
|
-
A "Combined Work" is a work produced by combining or linking an
|
28
|
-
Application with the Library. The particular version of the Library
|
29
|
-
with which the Combined Work was made is also called the "Linked
|
30
|
-
Version".
|
31
|
-
|
32
|
-
The "Minimal Corresponding Source" for a Combined Work means the
|
33
|
-
Corresponding Source for the Combined Work, excluding any source code
|
34
|
-
for portions of the Combined Work that, considered in isolation, are
|
35
|
-
based on the Application, and not on the Linked Version.
|
36
|
-
|
37
|
-
The "Corresponding Application Code" for a Combined Work means the
|
38
|
-
object code and/or source code for the Application, including any data
|
39
|
-
and utility programs needed for reproducing the Combined Work from the
|
40
|
-
Application, but excluding the System Libraries of the Combined Work.
|
41
|
-
|
42
|
-
1. Exception to Section 3 of the GNU GPL.
|
43
|
-
|
44
|
-
You may convey a covered work under sections 3 and 4 of this License
|
45
|
-
without being bound by section 3 of the GNU GPL.
|
46
|
-
|
47
|
-
2. Conveying Modified Versions.
|
48
|
-
|
49
|
-
If you modify a copy of the Library, and, in your modifications, a
|
50
|
-
facility refers to a function or data to be supplied by an Application
|
51
|
-
that uses the facility (other than as an argument passed when the
|
52
|
-
facility is invoked), then you may convey a copy of the modified
|
53
|
-
version:
|
54
|
-
|
55
|
-
a) under this License, provided that you make a good faith effort to
|
56
|
-
ensure that, in the event an Application does not supply the
|
57
|
-
function or data, the facility still operates, and performs
|
58
|
-
whatever part of its purpose remains meaningful, or
|
59
|
-
|
60
|
-
b) under the GNU GPL, with none of the additional permissions of
|
61
|
-
this License applicable to that copy.
|
62
|
-
|
63
|
-
3. Object Code Incorporating Material from Library Header Files.
|
64
|
-
|
65
|
-
The object code form of an Application may incorporate material from
|
66
|
-
a header file that is part of the Library. You may convey such object
|
67
|
-
code under terms of your choice, provided that, if the incorporated
|
68
|
-
material is not limited to numerical parameters, data structure
|
69
|
-
layouts and accessors, or small macros, inline functions and templates
|
70
|
-
(ten or fewer lines in length), you do both of the following:
|
71
|
-
|
72
|
-
a) Give prominent notice with each copy of the object code that the
|
73
|
-
Library is used in it and that the Library and its use are
|
74
|
-
covered by this License.
|
75
|
-
|
76
|
-
b) Accompany the object code with a copy of the GNU GPL and this license
|
77
|
-
document.
|
78
|
-
|
79
|
-
4. Combined Works.
|
80
|
-
|
81
|
-
You may convey a Combined Work under terms of your choice that,
|
82
|
-
taken together, effectively do not restrict modification of the
|
83
|
-
portions of the Library contained in the Combined Work and reverse
|
84
|
-
engineering for debugging such modifications, if you also do each of
|
85
|
-
the following:
|
86
|
-
|
87
|
-
a) Give prominent notice with each copy of the Combined Work that
|
88
|
-
the Library is used in it and that the Library and its use are
|
89
|
-
covered by this License.
|
90
|
-
|
91
|
-
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
92
|
-
document.
|
93
|
-
|
94
|
-
c) For a Combined Work that displays copyright notices during
|
95
|
-
execution, include the copyright notice for the Library among
|
96
|
-
these notices, as well as a reference directing the user to the
|
97
|
-
copies of the GNU GPL and this license document.
|
98
|
-
|
99
|
-
d) Do one of the following:
|
100
|
-
|
101
|
-
0) Convey the Minimal Corresponding Source under the terms of this
|
102
|
-
License, and the Corresponding Application Code in a form
|
103
|
-
suitable for, and under terms that permit, the user to
|
104
|
-
recombine or relink the Application with a modified version of
|
105
|
-
the Linked Version to produce a modified Combined Work, in the
|
106
|
-
manner specified by section 6 of the GNU GPL for conveying
|
107
|
-
Corresponding Source.
|
108
|
-
|
109
|
-
1) Use a suitable shared library mechanism for linking with the
|
110
|
-
Library. A suitable mechanism is one that (a) uses at run time
|
111
|
-
a copy of the Library already present on the user's computer
|
112
|
-
system, and (b) will operate properly with a modified version
|
113
|
-
of the Library that is interface-compatible with the Linked
|
114
|
-
Version.
|
115
|
-
|
116
|
-
e) Provide Installation Information, but only if you would otherwise
|
117
|
-
be required to provide such information under section 6 of the
|
118
|
-
GNU GPL, and only to the extent that such information is
|
119
|
-
necessary to install and execute a modified version of the
|
120
|
-
Combined Work produced by recombining or relinking the
|
121
|
-
Application with a modified version of the Linked Version. (If
|
122
|
-
you use option 4d0, the Installation Information must accompany
|
123
|
-
the Minimal Corresponding Source and Corresponding Application
|
124
|
-
Code. If you use option 4d1, you must provide the Installation
|
125
|
-
Information in the manner specified by section 6 of the GNU GPL
|
126
|
-
for conveying Corresponding Source.)
|
127
|
-
|
128
|
-
5. Combined Libraries.
|
129
|
-
|
130
|
-
You may place library facilities that are a work based on the
|
131
|
-
Library side by side in a single library together with other library
|
132
|
-
facilities that are not Applications and are not covered by this
|
133
|
-
License, and convey such a combined library under terms of your
|
134
|
-
choice, if you do both of the following:
|
135
|
-
|
136
|
-
a) Accompany the combined library with a copy of the same work based
|
137
|
-
on the Library, uncombined with any other library facilities,
|
138
|
-
conveyed under the terms of this License.
|
139
|
-
|
140
|
-
b) Give prominent notice with the combined library that part of it
|
141
|
-
is a work based on the Library, and explaining where to find the
|
142
|
-
accompanying uncombined form of the same work.
|
143
|
-
|
144
|
-
6. Revised Versions of the GNU Lesser General Public License.
|
145
|
-
|
146
|
-
The Free Software Foundation may publish revised and/or new versions
|
147
|
-
of the GNU Lesser General Public License from time to time. Such new
|
148
|
-
versions will be similar in spirit to the present version, but may
|
149
|
-
differ in detail to address new problems or concerns.
|
150
|
-
|
151
|
-
Each version is given a distinguishing version number. If the
|
152
|
-
Library as you received it specifies that a certain numbered version
|
153
|
-
of the GNU Lesser General Public License "or any later version"
|
154
|
-
applies to it, you have the option of following the terms and
|
155
|
-
conditions either of that published version or of any later version
|
156
|
-
published by the Free Software Foundation. If the Library as you
|
157
|
-
received it does not specify a version number of the GNU Lesser
|
158
|
-
General Public License, you may choose any version of the GNU Lesser
|
159
|
-
General Public License ever published by the Free Software Foundation.
|
160
|
-
|
161
|
-
If the Library as you received it specifies that a proxy can decide
|
162
|
-
whether future versions of the GNU Lesser General Public License shall
|
163
|
-
apply, that proxy's public statement of acceptance of any version is
|
164
|
-
permanent authorization for you to choose that version for the
|
165
|
-
Library.
|
1
|
+
Copyright (c) 2010 the Contributors (see http://github.com/zuk/reststop/commits/master)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
= Reststop
|
2
2
|
|
3
3
|
<b>Reststop makes it easy to write RESTful[http://en.wikipedia.org/wiki/Representational_State_Transfer]
|
4
|
-
applications in Camping[http://
|
4
|
+
applications in Camping[http://github.com/camping/camping].</b>
|
5
5
|
|
6
|
-
For info and downloads please see http://
|
6
|
+
For info and downloads please see http://github.com/camping/reststop
|
7
7
|
|
8
8
|
|
9
|
-
*
|
10
|
-
*Copyright*:: Copyright (c)
|
11
|
-
*License*::
|
9
|
+
*Authors*:: Matt Zukowski and Philippe Monnet (see http://github.com/camping/reststop/commits/master)
|
10
|
+
*Copyright*:: Copyright (c) 2010 Urbacon Ltd.
|
11
|
+
*License*:: MIT License[http://en.wikipedia.org/wiki/MIT_License]
|
12
12
|
|
13
13
|
|
14
14
|
For an example of a complete Reststop-based Camping app, have a look at
|
15
|
-
http://
|
15
|
+
http://github.com/zuk/reststop/blob/master/examples/blog.rb
|
16
16
|
|
17
17
|
Reststop essentially gives you three things:
|
18
18
|
|
@@ -24,7 +24,7 @@ Reststop essentially gives you three things:
|
|
24
24
|
* destroy (DELETE)
|
25
25
|
* list (GET)
|
26
26
|
|
27
|
-
Custom actions are also possible. See the
|
27
|
+
Custom actions are also possible. See the Reststop::Controllers#REST method documentation for usage info.
|
28
28
|
|
29
29
|
<b>2. Camping views grouped by output format:</b>
|
30
30
|
|
@@ -102,15 +102,25 @@ but here's a simple example of RESTful interaction with Restr:
|
|
102
102
|
|
103
103
|
== License
|
104
104
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
105
|
+
Copyright (c) 2010 the Contributors (see http://github.com/camping/reststop/commits/master)
|
106
|
+
|
107
|
+
Permission is hereby granted, free of charge, to any person
|
108
|
+
obtaining a copy of this software and associated documentation
|
109
|
+
files (the "Software"), to deal in the Software without
|
110
|
+
restriction, including without limitation the rights to use,
|
111
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
112
|
+
copies of the Software, and to permit persons to whom the
|
113
|
+
Software is furnished to do so, subject to the following
|
114
|
+
conditions:
|
115
|
+
|
116
|
+
The above copyright notice and this permission notice shall be
|
117
|
+
included in all copies or substantial portions of the Software.
|
118
|
+
|
119
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
120
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
121
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
122
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
123
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
124
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
125
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
126
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
require 'rake/clean'
|
4
|
-
require 'rake/testtask'
|
5
4
|
require 'rake/packagetask'
|
6
5
|
require 'rake/gempackagetask'
|
7
6
|
require 'rake/rdoctask'
|
@@ -46,7 +45,6 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
|
46
45
|
p.summary = DESCRIPTION
|
47
46
|
p.url = HOMEPATH
|
48
47
|
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
49
|
-
p.test_globs = ["test/**/*_test.rb"]
|
50
48
|
p.clean_globs = CLEAN #An array of file patterns to delete on clean.
|
51
49
|
|
52
50
|
# == Optional
|
data/examples/blog.rb
CHANGED
@@ -1,345 +1,400 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
#
|
4
|
-
# This is a RESTful version of the Camping-based Blog application.
|
5
|
-
#
|
6
|
-
# The original version can be found here:
|
7
|
-
# http://code.whytheluckystiff.net/camping/browser/trunk/examples/blog.rb
|
8
|
-
#
|
9
|
-
|
10
3
|
require 'rubygems'
|
4
|
+
#require 'ruby-debug' # @techarch : commented out since only needed for local debugging
|
5
|
+
|
6
|
+
require 'markaby' # @techarch : added explicit require
|
7
|
+
require 'camping' # @techarch
|
8
|
+
require 'camping/session' # @techarch : added explicit require since session has changed in Camping 2.0
|
9
|
+
|
10
|
+
gem 'RedCloth' # @techarch : added since it is referenced in the Posts model
|
11
|
+
require 'redcloth' # @techarch : added
|
11
12
|
|
12
|
-
gem 'camping', '~>
|
13
|
-
gem '
|
13
|
+
#gem 'camping', '~> 2.0'
|
14
|
+
gem 'camping' , '>= 2.0' # @techarch : updated version
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
#gem 'reststop', '~> 0.3'
|
17
|
+
|
18
|
+
=begin # @techarch : commented out since only needed for local debugging
|
19
|
+
$: << '../../camping/lib'
|
20
|
+
$: << '../lib'
|
21
|
+
require 'camping-unabridged'
|
22
|
+
require 'camping/ar'
|
17
23
|
require 'camping/session'
|
24
|
+
=end
|
18
25
|
|
19
|
-
begin
|
26
|
+
#begin # @techarch : commented out since only needed for local debugging
|
20
27
|
# try to use local copy of library
|
21
|
-
require '../lib/
|
22
|
-
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
28
|
+
#require '../lib/reststop2'
|
29
|
+
$: << '../lib/'
|
30
|
+
require 'reststop.rb' # @techarch : adjusted so that it is located in the same current folder
|
31
|
+
#rescue LoadError
|
32
|
+
# # ... otherwise default to rubygem
|
33
|
+
# require 'reststop'
|
34
|
+
#end
|
35
|
+
|
27
36
|
Camping.goes :Blog
|
28
37
|
|
29
38
|
module Blog
|
30
|
-
|
39
|
+
include Camping::Session
|
40
|
+
include Reststop
|
41
|
+
|
42
|
+
Controllers.extend Reststop::Controllers
|
31
43
|
end
|
32
44
|
|
33
|
-
module Blog::
|
34
|
-
|
35
|
-
|
36
|
-
|
45
|
+
module Blog::Base
|
46
|
+
alias camping_render render
|
47
|
+
alias camping_lookup lookup # @techarch: required if camping > 2.0
|
48
|
+
alias camping_service service
|
49
|
+
include Reststop::Base
|
50
|
+
alias service reststop_service
|
51
|
+
alias render reststop_render
|
52
|
+
|
53
|
+
# Overrides the new Tilt-centric lookup method In camping
|
54
|
+
# RESTstop needs to have a first try at looking up the view
|
55
|
+
# located in the Views::HTML module.
|
56
|
+
def lookup(n)
|
57
|
+
T.fetch(n.to_sym) do |k|
|
58
|
+
t = Blog::Views::HTML.method_defined?(k) || camping_lookup(n)
|
59
|
+
end
|
37
60
|
end
|
38
|
-
|
39
|
-
|
61
|
+
end
|
62
|
+
|
63
|
+
module Blog::Models
|
64
|
+
class Post < Base
|
65
|
+
belongs_to :user
|
66
|
+
|
67
|
+
before_save do |record|
|
68
|
+
cloth = RedCloth.new(record.body)
|
69
|
+
cloth.hard_breaks = false
|
70
|
+
record.html_body = cloth.to_html
|
40
71
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
t.column :username, :string
|
57
|
-
t.column :body, :text
|
58
|
-
end
|
59
|
-
User.create :username => 'admin', :password => 'camping'
|
72
|
+
end
|
73
|
+
|
74
|
+
class Comment < Base; belongs_to :user; end
|
75
|
+
class User < Base; end
|
76
|
+
|
77
|
+
class BasicFields < V 1.1
|
78
|
+
def self.up
|
79
|
+
create_table :blog_posts, :force => true do |t|
|
80
|
+
t.integer :user_id, :null => false
|
81
|
+
t.string :title, :limit => 255
|
82
|
+
t.text :body, :html_body
|
83
|
+
t.timestamps
|
84
|
+
end
|
85
|
+
create_table :blog_users, :force => true do |t|
|
86
|
+
t.string :username, :password
|
60
87
|
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
88
|
+
create_table :blog_comments, :force => true do |t|
|
89
|
+
t.integer :post_id, :null => false
|
90
|
+
t.string :username
|
91
|
+
t.text :body, :html_body
|
92
|
+
t.timestamps
|
65
93
|
end
|
94
|
+
User.create :username => 'admin', :password => 'camping'
|
66
95
|
end
|
96
|
+
|
97
|
+
def self.down
|
98
|
+
drop_table :blog_posts
|
99
|
+
drop_table :blog_users
|
100
|
+
drop_table :blog_comments
|
101
|
+
end
|
102
|
+
end
|
67
103
|
end
|
68
104
|
|
69
105
|
module Blog::Controllers
|
106
|
+
extend Reststop::Controllers
|
107
|
+
class Index
|
108
|
+
def get
|
109
|
+
redirect '/posts'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class Login < R '/login' # @techarch : added explicit login controller
|
114
|
+
def get
|
115
|
+
render :_login
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
70
119
|
class Posts < REST 'posts'
|
120
|
+
# POST /posts
|
121
|
+
def create
|
122
|
+
require_login!
|
123
|
+
@post = Post.create :title => (input.post_title || input.title), # @techarch : allow for REST-client based update
|
124
|
+
:body => (input.post_body || input.body), # @techarch : allow for REST-client based update
|
125
|
+
:user_id => @state.user_id
|
126
|
+
redirect R(@post)
|
127
|
+
end
|
71
128
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
_error("Unauthorized", 401)
|
80
|
-
end
|
81
|
-
end
|
129
|
+
# GET /posts/1
|
130
|
+
# GET /posts/1.xml
|
131
|
+
def read(post_id)
|
132
|
+
@post = Post.find(post_id)
|
133
|
+
@comments = Models::Comment.find(:all, :conditions => ['post_id = ?', post_id])
|
134
|
+
render :view
|
135
|
+
end
|
82
136
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
137
|
+
# PUT /posts/1
|
138
|
+
def update(post_id)
|
139
|
+
require_login!
|
140
|
+
@post = Post.find(post_id)
|
141
|
+
@post.update_attributes :title => (input.post_title || input.title), # @techarch : allow for REST-client based update
|
142
|
+
:body => (input.post_body || input.body) # @techarch : allow for REST-client based update
|
143
|
+
redirect R(@post)
|
144
|
+
end
|
90
145
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
@post.update_attributes :title => input.post_title, :body => input.post_body
|
96
|
-
redirect R(@post)
|
97
|
-
else
|
98
|
-
_error("Unauthorized", 401)
|
99
|
-
end
|
100
|
-
end
|
146
|
+
# DELETE /posts/1
|
147
|
+
def delete(post_id)
|
148
|
+
require_login!
|
149
|
+
@post = Post.find post_id
|
101
150
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
if @post.destroy
|
108
|
-
redirect R(Posts)
|
109
|
-
else
|
110
|
-
_error("Unable to delete post #{@post.id}", 500)
|
111
|
-
end
|
112
|
-
else
|
113
|
-
_error("Unauthorized", 401)
|
114
|
-
end
|
151
|
+
if @post.destroy
|
152
|
+
redirect R(Posts)
|
153
|
+
else
|
154
|
+
_error("Unable to delete post #{@post.id}", 500)
|
115
155
|
end
|
156
|
+
end
|
116
157
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
# GET /posts/new
|
126
|
-
def new
|
127
|
-
unless @state.user_id.blank?
|
128
|
-
@user = User.find @state.user_id
|
129
|
-
@post = Post.new
|
130
|
-
end
|
131
|
-
render :add
|
132
|
-
end
|
158
|
+
# GET /posts
|
159
|
+
# GET /posts.xml
|
160
|
+
def list
|
161
|
+
@posts = Post.all(:order => 'updated_at DESC')
|
162
|
+
s=render :index
|
163
|
+
s
|
164
|
+
end
|
133
165
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
166
|
+
# GET /posts/new
|
167
|
+
def new
|
168
|
+
#@state.user_id = 1 # @techarch : commented out as was probably hard-coded for testing purpose
|
169
|
+
require_login!
|
170
|
+
@user = User.find @state.user_id # @techarch : added since we need the user info
|
171
|
+
@post = Post.new
|
172
|
+
render :add
|
173
|
+
end
|
174
|
+
|
175
|
+
# GET /posts/1/edit
|
176
|
+
def edit(post_id)
|
177
|
+
require_login!
|
178
|
+
@user = User.find @state.user_id # @techarch : added since we need the user info
|
179
|
+
@post = Post.find(post_id)
|
180
|
+
render :edit
|
181
|
+
end
|
151
182
|
end
|
152
183
|
|
153
184
|
class Comments < REST 'comments'
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
185
|
+
# POST /comments
|
186
|
+
def create
|
187
|
+
Models::Comment.create(:username => (input.post_username || input.username), # @techarch : allow for REST-client based update
|
188
|
+
:body => (input.post_body || input.body), # @techarch : allow for REST-client based update
|
189
|
+
:post_id => input.post_id)
|
190
|
+
redirect R(Posts, input.post_id)
|
191
|
+
end
|
160
192
|
end
|
161
|
-
|
193
|
+
|
162
194
|
class Sessions < REST 'sessions'
|
163
195
|
# POST /sessions
|
164
196
|
def create
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
197
|
+
@user = User.find_by_username_and_password(input.username, input.password)
|
198
|
+
|
199
|
+
if @user
|
200
|
+
@state.user_id = @user.id
|
201
|
+
redirect R(Posts)
|
202
|
+
else
|
203
|
+
@info = 'Wrong username or password.'
|
204
|
+
end
|
205
|
+
render :login
|
174
206
|
end
|
175
207
|
|
176
208
|
# DELETE /sessions
|
177
209
|
def delete
|
178
|
-
|
179
|
-
|
210
|
+
@state.user_id = nil
|
211
|
+
redirect R(Posts) # @techarch : changed redirect from Index (does not exist) to Posts
|
180
212
|
end
|
181
213
|
end
|
182
214
|
|
183
215
|
# You can use old-fashioned Camping controllers too!
|
184
216
|
class Style < R '/styles.css'
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
217
|
+
def get
|
218
|
+
@headers["Content-Type"] = "text/css; charset=utf-8"
|
219
|
+
@body = %{
|
220
|
+
body {
|
221
|
+
font-family: Utopia, Georga, serif;
|
222
|
+
}
|
223
|
+
h1.header {
|
224
|
+
background-color: #fef;
|
225
|
+
margin: 0; padding: 10px;
|
226
|
+
}
|
227
|
+
div.content {
|
228
|
+
padding: 10px;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
end
|
200
232
|
end
|
201
233
|
end
|
202
234
|
|
235
|
+
module Blog::Helpers
|
236
|
+
alias_method :_R, :R
|
237
|
+
remove_method :R
|
238
|
+
include Reststop::Helpers
|
239
|
+
|
240
|
+
def logged_in?
|
241
|
+
!!@state.user_id
|
242
|
+
end
|
243
|
+
|
244
|
+
def require_login!
|
245
|
+
unless logged_in?
|
246
|
+
redirect(R(Blog::Controllers::Login)) # @techarch: add explicit route
|
247
|
+
throw :halt
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
203
251
|
|
204
|
-
Markaby::Builder.set(:indent, 2)
|
205
252
|
|
206
253
|
module Blog::Views
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
div.content do
|
220
|
-
self << yield
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def index
|
227
|
-
if @posts.empty?
|
228
|
-
p 'No posts found.'
|
229
|
-
else
|
230
|
-
for post in @posts
|
231
|
-
_post(post)
|
232
|
-
end
|
233
|
-
end
|
234
|
-
p { a 'Add', :href => R(Posts, 'new') }
|
235
|
-
end
|
236
|
-
|
237
|
-
def login
|
238
|
-
p { b @login }
|
239
|
-
p { a 'Continue', :href => R(Posts, 'new') }
|
240
|
-
end
|
241
|
-
|
242
|
-
def logout
|
243
|
-
p "You have been logged out."
|
244
|
-
p { a 'Continue', :href => R(Posts) }
|
245
|
-
end
|
246
|
-
|
247
|
-
def add
|
248
|
-
if @user
|
249
|
-
_form(@post, :action => R(Posts))
|
250
|
-
else
|
251
|
-
_login
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
def edit
|
256
|
-
if @user
|
257
|
-
_form(@post, :action => R(@post), :method => :put)
|
258
|
-
else
|
259
|
-
_login
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
def view
|
264
|
-
_post(@post)
|
265
|
-
|
266
|
-
p "Comment for this post:"
|
267
|
-
for c in @comments
|
268
|
-
h1 c.username
|
269
|
-
p c.body
|
270
|
-
end
|
271
|
-
|
272
|
-
form :action => R(Comments), :method => 'post' do
|
273
|
-
label 'Name', :for => 'post_username'; br
|
274
|
-
input :name => 'post_username', :type => 'text'; br
|
275
|
-
label 'Comment', :for => 'post_body'; br
|
276
|
-
textarea :name => 'post_body' do; end; br
|
277
|
-
input :type => 'hidden', :name => 'post_id', :value => @post.id
|
278
|
-
input :type => 'submit'
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
# partials
|
283
|
-
def _login
|
284
|
-
form :action => R(Sessions), :method => 'post' do
|
285
|
-
label 'Username', :for => 'username'; br
|
286
|
-
input :name => 'username', :type => 'text'; br
|
287
|
-
|
288
|
-
label 'Password', :for => 'password'; br
|
289
|
-
input :name => 'password', :type => 'text'; br
|
290
|
-
|
291
|
-
input :type => 'submit', :name => 'login', :value => 'Login'
|
292
|
-
end
|
254
|
+
extend Reststop::Views
|
255
|
+
|
256
|
+
module HTML
|
257
|
+
include Blog::Controllers
|
258
|
+
include Blog::Views
|
259
|
+
|
260
|
+
def layout
|
261
|
+
html do
|
262
|
+
head do
|
263
|
+
title 'blog'
|
264
|
+
link :rel => 'stylesheet', :type => 'text/css',
|
265
|
+
:href => self/'/styles.css', :media => 'screen'
|
293
266
|
end
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
p do
|
299
|
-
[a("Edit", :href => R(Posts, post.id, 'edit')), a("View", :href => R(Posts, post.id, 'edit'))].join " | "
|
267
|
+
body do
|
268
|
+
h1.header { a 'blog', :href => R(Posts) }
|
269
|
+
div.content do
|
270
|
+
self << yield
|
300
271
|
end
|
301
272
|
end
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
form({:method => 'post'}.merge(opts)) do
|
312
|
-
label 'Title', :for => 'post_title'; br
|
313
|
-
input :name => 'post_title', :type => 'text',
|
314
|
-
:value => post.title; br
|
315
|
-
|
316
|
-
label 'Body', :for => 'post_body'; br
|
317
|
-
textarea post.body, :name => 'post_body'; br
|
318
|
-
|
319
|
-
input :type => 'hidden', :name => 'post_id', :value => post.id
|
320
|
-
input :type => 'submit'
|
321
|
-
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def index
|
277
|
+
if @posts.empty?
|
278
|
+
p 'No posts found.'
|
279
|
+
else
|
280
|
+
for post in @posts
|
281
|
+
_post(post)
|
322
282
|
end
|
283
|
+
end
|
284
|
+
p { a 'Add', :href => R(Posts, 'new') }
|
285
|
+
end
|
286
|
+
|
287
|
+
def login
|
288
|
+
p { b @login }
|
289
|
+
p { a 'Continue', :href => R(Posts, 'new') }
|
323
290
|
end
|
324
|
-
default_format :HTML
|
325
291
|
|
326
|
-
|
327
|
-
|
328
|
-
|
292
|
+
def logout
|
293
|
+
p "You have been logged out."
|
294
|
+
p { a 'Continue', :href => R(Posts) }
|
295
|
+
end
|
296
|
+
|
297
|
+
def add
|
298
|
+
if @user
|
299
|
+
_form(@post, :action => R(Posts))
|
300
|
+
else
|
301
|
+
_login
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def edit
|
306
|
+
if @user
|
307
|
+
_form(@post, :action => R(@post), :method => :put)
|
308
|
+
else
|
309
|
+
_login
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def view
|
314
|
+
_post(@post)
|
315
|
+
|
316
|
+
p "Comment for this post:"
|
317
|
+
for c in @comments
|
318
|
+
h1 c.username
|
319
|
+
p c.body
|
320
|
+
end
|
321
|
+
|
322
|
+
form :action => R(Comments), :method => 'post' do
|
323
|
+
label 'Name', :for => 'post_username'; br
|
324
|
+
input :name => 'post_username', :type => 'text'; br
|
325
|
+
label 'Comment', :for => 'post_body'; br
|
326
|
+
textarea :name => 'post_body' do; end; br
|
327
|
+
input :type => 'hidden', :name => 'post_id', :value => @post.id
|
328
|
+
input :type => 'submit'
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
# partials
|
333
|
+
def _login
|
334
|
+
p do
|
335
|
+
"(default: admin/camping)"
|
336
|
+
end
|
337
|
+
form :action => R(Sessions), :method => 'post' do
|
338
|
+
label 'Username', :for => 'username'; br
|
339
|
+
input :name => 'username', :type => 'text'; br
|
340
|
+
|
341
|
+
label 'Password', :for => 'password'; br
|
342
|
+
input :name => 'password', :type => 'text'; br
|
343
|
+
|
344
|
+
input :type => 'submit', :name => 'login', :value => 'Login'
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def _post(post)
|
349
|
+
h1 post.title
|
350
|
+
p post.body
|
351
|
+
p do
|
352
|
+
[a("Edit", :href => R(Posts, post.id, 'edit')), a("View", :href => R(Posts, post.id, 'edit'))].join " | "
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def _form(post, opts)
|
357
|
+
form(:action => R(Sessions), :method => 'delete') do
|
358
|
+
p do
|
359
|
+
span "You are logged in as #{@user.username}"
|
360
|
+
span " | "
|
361
|
+
button(:type => 'submit') {'Logout'}
|
329
362
|
end
|
330
|
-
|
331
|
-
def index
|
332
|
-
@posts.to_xml(:root => 'blog')
|
333
363
|
end
|
334
|
-
|
335
|
-
|
336
|
-
|
364
|
+
form({:method => 'post'}.merge(opts)) do
|
365
|
+
label 'Title', :for => 'post_title'; br
|
366
|
+
input :name => 'post_title', :type => 'text',
|
367
|
+
:value => post.title; br
|
368
|
+
|
369
|
+
label 'Body', :for => 'post_body'; br
|
370
|
+
textarea post.body, :name => 'post_body'; br
|
371
|
+
|
372
|
+
input :type => 'hidden', :name => 'post_id', :value => post.id
|
373
|
+
input :type => 'submit'
|
337
374
|
end
|
338
375
|
end
|
376
|
+
end
|
377
|
+
default_format :HTML
|
378
|
+
|
379
|
+
module XML
|
380
|
+
def layout
|
381
|
+
yield
|
382
|
+
end
|
383
|
+
|
384
|
+
def index
|
385
|
+
@posts.to_xml(:root => 'blog')
|
386
|
+
end
|
387
|
+
|
388
|
+
def view
|
389
|
+
@post.to_xml(:root => 'post')
|
390
|
+
end
|
391
|
+
end
|
339
392
|
end
|
340
393
|
|
341
394
|
def Blog.create
|
342
|
-
|
343
|
-
|
344
|
-
|
395
|
+
raise "You must configure the database first in 'config/database.yml'!" unless File.exist?('config/database.yml')
|
396
|
+
dbconfig = YAML.load(File.read('config/database.yml')) # @techarch
|
397
|
+
Camping::Models::Base.establish_connection dbconfig['development'] # @techarch
|
345
398
|
|
399
|
+
Blog::Models.create_schema :assume => (Blog::Models::Post.table_exists? ? 1.0 : 0.0)
|
400
|
+
end
|