marley 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/README.rdoc +3 -8
  2. data/lib/marley.rb +27 -131
  3. data/lib/marley/controllers.rb +12 -7
  4. data/lib/marley/core_ext.rb +8 -0
  5. data/lib/marley/errors.rb +51 -0
  6. data/lib/marley/joint.rb +14 -19
  7. data/lib/marley/joints/forum.rb +88 -0
  8. data/lib/marley/joints/messages.rb +86 -0
  9. data/lib/marley/joints/section.rb +63 -0
  10. data/lib/marley/joints/tags.rb +99 -0
  11. data/lib/marley/joints/user.rb +120 -0
  12. data/lib/marley/plugin.rb +39 -0
  13. data/lib/marley/plugins/orm_rest_convenience.rb +92 -0
  14. data/lib/marley/plugins/rest_convenience.rb +28 -0
  15. data/lib/marley/reggae.rb +5 -2
  16. data/lib/marley/resources.rb +10 -0
  17. data/lib/marley/router.rb +61 -0
  18. data/lib/marley/test_helpers.rb +12 -1
  19. data/lib/marley/utils.rb +57 -25
  20. data/rdoc/example_joint.rb +33 -0
  21. data/rdoc/example_plugin.rb +20 -0
  22. data/rdoc/forum_joint.rb +50 -0
  23. data/rdoc/forum_joint.rdoc +19 -0
  24. data/rdoc/hello.rb +14 -0
  25. data/rdoc/hello.rdoc +14 -0
  26. data/rdoc/joints.rdoc +69 -0
  27. data/rdoc/messages_joint.rb +34 -0
  28. data/rdoc/messages_joint.rdoc +18 -0
  29. data/rdoc/messages_joint/private_messages.rdoc +59 -0
  30. data/rdoc/messages_joint/public_messages.rdoc +65 -0
  31. data/rdoc/orm_rest_convenience_plugin.rb +28 -0
  32. data/rdoc/orm_rest_convenience_plugin.rdoc +99 -0
  33. data/rdoc/plugins.rdoc +35 -0
  34. data/rdoc/reggae.rb +3 -0
  35. data/rdoc/reggae.rdoc +11 -0
  36. data/rdoc/reggae/generate.rdoc +13 -0
  37. data/rdoc/reggae/parse.rdoc +44 -0
  38. data/rdoc/section_joint.rb +13 -0
  39. data/rdoc/section_joint.rdoc +19 -0
  40. data/rdoc/tags_joint.rb +16 -0
  41. data/rdoc/tags_joint.rdoc +22 -0
  42. data/rdoc/tags_joint/announcements.rdoc +64 -0
  43. data/rdoc/tags_joint/secrets.rdoc +65 -0
  44. data/rdoc/user_joint.rb +62 -0
  45. data/rdoc/user_joint.rdoc +13 -0
  46. data/rdoc/user_joint/exiting_users.rdoc +120 -0
  47. data/rdoc/user_joint/no_auth_provided.rdoc +34 -0
  48. data/reggae.ebnf +1 -1
  49. metadata +45 -37
  50. data/Favicon.ico +0 -0
  51. data/Rakefile +0 -14
  52. data/TODO +0 -19
  53. data/examples/blog.rb +0 -26
  54. data/examples/empty.sqlite3 +0 -0
  55. data/examples/forum.css +0 -3
  56. data/examples/forum.js +0 -23
  57. data/examples/forum.rb +0 -20
  58. data/examples/forum.sql +0 -42
  59. data/examples/forum.sqlite3 +0 -0
  60. data/examples/forum_test.sqlite3 +0 -0
  61. data/examples/run.sh +0 -14
  62. data/lib/client/jamaica.css +0 -270
  63. data/lib/client/jamaica.js +0 -353
  64. data/lib/client/jamaica.rb +0 -38
  65. data/lib/client/jquery-1.6.2.js +0 -8981
  66. data/lib/client/jquery.form.js +0 -814
  67. data/lib/joints/basic_menu_system.rb +0 -41
  68. data/lib/joints/basic_messaging.rb +0 -88
  69. data/lib/joints/basic_user.rb +0 -51
  70. data/lib/joints/tagged_messaging.rb +0 -122
  71. data/lib/joints/tagging.rb +0 -56
  72. data/lib/sequel/plugins/rest_auth.rb +0 -53
  73. data/lib/sequel/plugins/rest_convenience.rb +0 -87
  74. data/marley-0.4.0.gem +0 -0
  75. data/marley.gemspec +0 -17
  76. data/test/empty.sqlite3 +0 -0
  77. data/test/menu_tests.rb +0 -9
  78. data/test/tagged_messaging_tests.rb +0 -289
  79. data/test/test.sqlite3 +0 -0
  80. data/test/test_include.rb +0 -16
  81. data/test/user_tests.rb +0 -72
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'sequel'
3
+ require 'marley'
4
+ require 'marley/test_helpers'
5
+
6
+ DB=Sequel.sqlite('')
7
+ DB.create_table :users do
8
+ primary_key :id
9
+ text :name, :unique => true
10
+ text :user_type, :index => true
11
+ text :pw_hash
12
+ datetime :date_created, :index => true
13
+ text :description
14
+ end
15
+ DB.create_table :messages do
16
+ primary_key :id
17
+ integer :user_id, :index => true
18
+ text :message_type, :index => true
19
+ text :title, :index => true,:null => false
20
+ text :content
21
+ end
22
+ DB.create_table :messages_users do
23
+ primary_key :id
24
+ integer :user_id
25
+ integer :message_id
26
+ boolean :read, :index => true
27
+ index [:user_id, :message_id], :unique => true
28
+ end
29
+
30
+ Sequel::Model.plugin :validation_helpers
31
+ Marley.plugin('orm_rest_convenience').apply(Sequel::Model)
32
+ Marley.joint 'user'
33
+ Marley.plugin('current_user_methods').apply(Sequel::Model)
34
+ Marley.joint 'messages'
@@ -0,0 +1,18 @@
1
+
2
+ ==The Messages Joint
3
+
4
+ setup
5
+ DB[:users].delete
6
+ DB[:messages].delete
7
+ DB[:messages_users].delete
8
+ DB[:SQLITE_SEQUENCE].update(:seq => 0)
9
+ user_client=Marley::TestClient.new(:resource_name => 'user')
10
+ user=user_client.read({},:method => 'new').set_values(:password => 'asdfasdf', :confirm_password => 'asdfasdf')
11
+ (1 .. 5).each { |i|
12
+ user_client.create(user.set_values(:name => "user#{i}"))
13
+ instance_variable_set(:"@client#{i}", Marley::TestClient.new(:auth => ["user#{i}",'asdfasdf'] ))
14
+ }
15
+ end
16
+
17
+ examples:
18
+
@@ -0,0 +1,59 @@
1
+
2
+ ==Private Messages
3
+
4
+ setup
5
+ (1 .. 5).each { |i|
6
+ instance_variable_get(:"@client#{i}").resource_name='private_message'
7
+ }
8
+ end
9
+
10
+ example: user1 sends message to user2
11
+
12
+ >> @msg=@client1.read({},:method => 'new')
13
+ => [:instance, {:url=>"/private_message/", :schema=>[["text", :recipients, 0, ""], ["integer", :user_id, 3, 1], ["text", :title, 4, nil], ["text", :content, 0, nil]], :name=>"private_message", :new_rec=>true, :actions=>nil}, []]
14
+
15
+ >> @client1.create(@msg.set_values(:title => 'asdf',:recipients => 'xxx'),:code => 400)
16
+ => [:error, {:error_type=>"validation", :error_details=>{:recipients=>["xxx is not a valid message recipient"]}, :description=>nil}]
17
+ >> @client1.create(@msg.set_values(:title => 'asdf',:recipients => 'user2'))
18
+ => [:instance, {:url=>"/private_message/1", :schema=>[["text", :recipients, 2, "user2"], ["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 6, "asdf"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>{:get=>"reply"}}, []]
19
+
20
+ >> @client1.read
21
+ => []
22
+ >> @client3.read
23
+ => []
24
+ >> @client2.read
25
+ => [[:instance, {:url=>"/private_message/1", :schema=>[["text", :recipients, 2, "user2"], ["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 6, "asdf"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>{:get=>"reply"}}, []]]
26
+
27
+ example: user2 sends message to user3 and user4, each of which replies
28
+
29
+ >> @msg=@client2.read({},:method => 'new')
30
+ => [:instance, {:url=>"/private_message/", :schema=>[["text", :recipients, 0, ""], ["integer", :user_id, 3, 2], ["text", :title, 4, nil], ["text", :content, 0, nil]], :name=>"private_message", :new_rec=>true, :actions=>nil}, []]
31
+ >> @client2.create(@msg.set_values(:title => 'message1',:recipients => 'user3,user4'))
32
+ => [:instance, {:url=>"/private_message/1", :schema=>[["text", :recipients, 2, "user3,user4"], ["text", :author, 2, "user2"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 2], ["text", :title, 6, "message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>[:reply, :reply_all]}, []]
33
+ >> @client1.read
34
+ => []
35
+ >> @client2.read
36
+ => []
37
+ >> @client3.read
38
+ => [[:instance, {:url=>"/private_message/1", :schema=>[["text", :recipients, 2, "user3,user4"], ["text", :author, 2, "user2"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 2], ["text", :title, 6, "message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>[:reply, :reply_all]}, []]]
39
+ >> @orig=@client4.read
40
+ => [[:instance, {:url=>"/private_message/1", :schema=>[["text", :recipients, 2, "user3,user4"], ["text", :author, 2, "user2"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 2], ["text", :title, 6, "message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>[:reply, :reply_all]}, []]]
41
+
42
+ >> @u3r=@client3.read({},:url => @orig[0].url+'/reply')
43
+ => [:instance, {:url=>"/private_message/", :schema=>[["text", :recipients, 0, "user2"], ["integer", :user_id, 3, 3], ["text", :title, 4, "re: message1"], ["text", :content, 0, nil]], :name=>"private_message", :new_rec=>true, :actions=>nil}, []]
44
+ >> @u3ra=@client3.read({},:url => @orig[0].url+'/reply_all')
45
+ => [:instance, {:url=>"/private_message/", :schema=>[["text", :recipients, 0, "user2,user4"], ["integer", :user_id, 3, 3], ["text", :title, 4, "re: message1"], ["text", :content, 0, nil]], :name=>"private_message", :new_rec=>true, :actions=>nil}, []]
46
+
47
+ >> @client3.create(@u3r)
48
+ => [:instance, {:url=>"/private_message/2", :schema=>[["text", :recipients, 2, "user2"], ["text", :author, 2, "user3"], ["integer", :id, 2, 2], ["integer", :user_id, 3, 3], ["text", :title, 6, "re: message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>{:get=>"reply"}}, []]
49
+ >> @client2.read
50
+ => [[:instance, {:url=>"/private_message/2", :schema=>[["text", :recipients, 2, "user2"], ["text", :author, 2, "user3"], ["integer", :id, 2, 2], ["integer", :user_id, 3, 3], ["text", :title, 6, "re: message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>{:get=>"reply"}}, []]]
51
+
52
+ >> @client3.create(@u3ra)
53
+ => [:instance, {:url=>"/private_message/3", :schema=>[["text", :recipients, 2, "user2,user4"], ["text", :author, 2, "user3"], ["integer", :id, 2, 3], ["integer", :user_id, 3, 3], ["text", :title, 6, "re: message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>[:reply, :reply_all]}, []]
54
+ >> @client2.read
55
+ => [[:instance, {:url=>"/private_message/2", :schema=>[["text", :recipients, 2, "user2"], ["text", :author, 2, "user3"], ["integer", :id, 2, 2], ["integer", :user_id, 3, 3], ["text", :title, 6, "re: message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>{:get=>"reply"}}, []], [:instance, {:url=>"/private_message/3", :schema=>[["text", :recipients, 2, "user2,user4"], ["text", :author, 2, "user3"], ["integer", :id, 2, 3], ["integer", :user_id, 3, 3], ["text", :title, 6, "re: message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>[:reply, :reply_all]}, []]]
56
+
57
+ >> @client4.read
58
+ => [[:instance, {:url=>"/private_message/1", :schema=>[["text", :recipients, 2, "user3,user4"], ["text", :author, 2, "user2"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 2], ["text", :title, 6, "message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>[:reply, :reply_all]}, []], [:instance, {:url=>"/private_message/3", :schema=>[["text", :recipients, 2, "user2,user4"], ["text", :author, 2, "user3"], ["integer", :id, 2, 3], ["integer", :user_id, 3, 3], ["text", :title, 6, "re: message1"], ["text", :content, 2, nil]], :name=>"private_message", :new_rec=>false, :actions=>[:reply, :reply_all]}, []]]
59
+
@@ -0,0 +1,65 @@
1
+
2
+ ==Public Messages
3
+
4
+ setup
5
+ (1 .. 5).each { |i|
6
+ instance_variable_get(:"@client#{i}").resource_name='public_message'
7
+ }
8
+ end
9
+
10
+
11
+
12
+ example: user1 writes, edits, deletes post
13
+
14
+
15
+ >>@msg=@client1.read({},:method => 'new')
16
+ => [:instance, {:new_rec=>true, :actions=>nil, :url=>"/public_message/", :name=>"public_message", :schema=>[["integer", :user_id, 3, 1], ["text", :title, 4, nil], ["text", :content, 0, nil]]}, []]
17
+
18
+ >> @client1.create(@msg,:code => 400)
19
+ => [:error, {:error_type=>"validation", :description=>nil, :error_details=>{:title=>["is required"]}}]
20
+
21
+ >> @msg=@client1.create(@msg.set_values(:title => 'test'))
22
+ => [:instance, {:url=>"/public_message/1", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 4, "test"], ["text", :content, 0, nil]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply", :delete=>"/public_message/1"}}, []]
23
+
24
+ >> @client1.update(@msg.set_values(:content => 'asdf'),:url => @msg.url)
25
+ => [:instance, {:url=>"/public_message/1", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 4, "test"], ["text", :content, 0, "asdf"]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply", :delete=>"/public_message/1"}}, []]
26
+
27
+ >> @client1.del({},:url => @msg.url)
28
+ => [:instance, {:url=>"/public_message/1", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 4, "test"], ["text", :content, 0, "asdf"]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply", :delete=>"/public_message/1"}}, []]
29
+
30
+
31
+ example: two users, several messages
32
+ >> @u1msg=@client1.read({},:method => 'new')
33
+ => [:instance, {:new_rec=>true, :actions=>nil, :url=>"/public_message/", :name=>"public_message", :schema=>[["integer", :user_id, 3, 1], ["text", :title, 4, nil], ["text", :content, 0, nil]]}, []]
34
+ >> @u2msg=@client2.read({},:method => 'new')
35
+ => [:instance, {:new_rec=>true, :actions=>nil, :url=>"/public_message/", :name=>"public_message", :schema=>[["integer", :user_id, 3, 2], ["text", :title, 4, nil], ["text", :content, 0, nil]]}, []]
36
+
37
+ >> @u1m1=@client1.create(@u1msg.set_values(:title => 'usr1 msg1'))
38
+ => [:instance, {:url=>"/public_message/1", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 4, "usr1 msg1"], ["text", :content, 0, nil]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply", :delete=>"/public_message/1"}}, []]
39
+
40
+ >> @client3.read
41
+ => [[:instance, {:url=>"/public_message/1", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 6, "usr1 msg1"], ["text", :content, 2, nil]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply"}}, []]]
42
+
43
+ >> @u1m2=@client1.create(@u1msg.set_values(:title => 'usr1 msg2'))
44
+ => [:instance, {:url=>"/public_message/2", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 2], ["integer", :user_id, 3, 1], ["text", :title, 4, "usr1 msg2"], ["text", :content, 0, nil]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply", :delete=>"/public_message/2"}}, []]
45
+ >> @client3.read
46
+ => [[:instance, {:url=>"/public_message/1", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 6, "usr1 msg1"], ["text", :content, 2, nil]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply"}}, []], [:instance, {:url=>"/public_message/2", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 2], ["integer", :user_id, 3, 1], ["text", :title, 6, "usr1 msg2"], ["text", :content, 2, nil]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply"}}, []]]
47
+
48
+ >> @client3.update(@u1m1.set_values(:title => 'asdf'),:url => @u1m1.url,:code => 403)
49
+ => [:error, {:error_type=>"authorization", :error_details=>nil, :description=>"You are not authorized for this operation"}]
50
+ >> @client2.update(@u1m1.set_values(:title => 'asdf'),:url => @u1m1.url,:code => 403)
51
+ => [:error, {:error_type=>"authorization", :error_details=>nil, :description=>"You are not authorized for this operation"}]
52
+ >> @client1.update(@u1m1.set_values(:title => 'asdf'),:url => @u1m1.url)
53
+ => [:instance, {:url=>"/public_message/1", :schema=>[["text", :author, 2, "user1"], ["integer", :id, 2, 1], ["integer", :user_id, 3, 1], ["text", :title, 4, "asdf"], ["text", :content, 0, nil]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply", :delete=>"/public_message/1"}}, []]
54
+
55
+ >> @u2r1=@client2.read({},:url => @u1m1.url+'/reply')
56
+ => [:instance, {:url=>"/public_message/", :schema=>[["integer", :user_id, 3, 2], ["text", :title, 4, "re: asdf"], ["text", :content, 0, nil]], :name=>"public_message", :new_rec=>true, :actions=>nil}, []]
57
+
58
+ >> @client2.create(@u2r1.set_values(:content => 'xxxxxx'))
59
+ => [:instance, {:url=>"/public_message/3", :schema=>[["text", :author, 2, "user2"], ["integer", :id, 2, 3], ["integer", :user_id, 3, 2], ["text", :title, 4, "re: asdf"], ["text", :content, 0, "xxxxxx"]], :name=>"public_message", :new_rec=>false, :actions=>{:get=>"reply", :delete=>"/public_message/3"}}, []]
60
+
61
+
62
+
63
+
64
+
65
+
@@ -0,0 +1,28 @@
1
+
2
+ require 'rubygems'
3
+ require 'sequel'
4
+ require 'marley'
5
+ require 'marley/test_helpers'
6
+
7
+ DB=Sequel.sqlite('')
8
+ DB.create_table :users do
9
+ primary_key :id
10
+ text :name,:unique => true, :null => false
11
+ text :password, :null => false
12
+ text :description
13
+ end
14
+
15
+ Marley.config(:http_auth => false)
16
+ Marley.plugin('orm_rest_convenience').apply(Sequel::Model)
17
+ module Marley
18
+ module Resources
19
+ class User < Sequel::Model
20
+ def validate
21
+ validates_presence :name
22
+ validates_unique :name
23
+ validates_presence :description
24
+ validates_presence :password
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,99 @@
1
+
2
+ === Orm Rest Convenience
3
+
4
+ This plugin tries to be ORM agnostic but I've only tested it with Sequel. You are encouraged to fork this plugin and make it work with other ORM's.
5
+
6
+ setup
7
+ @client=Marley::TestClient.new(:resource_name => 'user')
8
+ end
9
+
10
+ examples:
11
+ => Marley::Resources::User
12
+ >> MR::User.resource_name
13
+ => "user"
14
+ >> MR::User.foreign_key_name
15
+ => :user_id
16
+ >> MR::User.reggae_link
17
+ => [:link, {:url=>"/user/", :title=>"User"},[]]
18
+ >> MR::User.reggae_link('new')
19
+ => [:link, {:url=>"/user/new", :title=>"New User"},[]]
20
+ >> MR::User.model_actions
21
+ => {:get => [:new,:list]}
22
+ >> @client.read
23
+ => []
24
+ >> @client.read({},{:method => 'new'})
25
+ => [:instance, {:url=>"/user/", :new_rec=>true, :actions=>nil, :schema=>[["text", :name, 4, nil], [:password, :password, 4, nil], ["text", :description, 0, nil]], :name=>"user"}, []]
26
+
27
+ >> @client.create({},:code => 400)
28
+ => [:error, {:description=>nil, :error_type=>"validation", :error_details=>{:description=>["is required"], :name=>["is required"], :password=>["is required"]}}]
29
+ >> @client.create({:'user[name]' => 'asdf',:'user[password]' => 'asdf', :'user[description]' => 'xxxx'})
30
+ => [:instance, {:url=>"/user/1", :schema=>[["integer", :id, 2, 1], ["text", :name, 4, "asdf"], [:password, :password, 4, "asdf"], ["text", :description, 0, "xxxx"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []]
31
+
32
+ >> MR::User[1].to_s
33
+ => "asdf"
34
+ >> MR::User[1].url
35
+ => "/user/1"
36
+ >> MR::User[1].reggae_link
37
+ => [:link, {:url=>"/user/1", :title=>""},[]]
38
+ >> MR::User[1].reggae_link('foobar')
39
+ => [:link, {:url=>"/user/1", :title=>"Foobar"},[]]
40
+ >> MR::User[1].rest_cols
41
+ => [:id, :name, :password, :description]
42
+ >> MR::User[1].write_cols
43
+ => [:name, :password, :description]
44
+ >> MR::User[1].hidden_cols
45
+ => []
46
+ >> MR::User[1].required_cols
47
+ => []
48
+ >> MR::User[1].reggae_schema
49
+ => [["integer", :id, 2, 1], ["text", :name, 4, "asdf"], [:password, :password, 4, "asdf"], ["text", :description, 0, "xxxx"]]
50
+ >> MR::User[1].reggae_instance
51
+ => [:instance, {:url=>"/user/1", :schema=>[["integer", :id, 2, 1], ["text", :name, 4, "asdf"], [:password, :password, 4, "asdf"], ["text", :description, 0, "xxxx"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []]
52
+
53
+ >> @client.create({:'user[name]' => 'asdf',:'user[password]' => 'asdf', :'user[description]' => 'xxxx'},:code => 400)
54
+ => [:error, {:description=>nil, :error_type=>"validation", :error_details=>{:name=>["is already taken"]}}]
55
+ >> @client.create({:'user[name]' => 'asd',:'user[password]' => 'asdf', :'user[description]' => 'xxxx'})
56
+ => [:instance, {:url=>"/user/2", :schema=>[["integer", :id, 2, 2], ["text", :name, 4, "asd"], [:password, :password, 4, "asdf"], ["text", :description, 0, "xxxx"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []]
57
+ >> @client.read
58
+ => [[:instance, {:url=>"/user/1", :schema=>[["integer", :id, 2, 1], ["text", :name, 4, "asdf"], [:password, :password, 4, "asdf"], ["text", :description, 0, "xxxx"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []], [:instance, {:url=>"/user/2", :schema=>[["integer", :id, 2, 2], ["text", :name, 4, "asd"], [:password, :password, 4, "asdf"], ["text", :description, 0, "xxxx"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []]]
59
+ >> @client.del({},:instance_id => 2)
60
+ => [:instance, {:url=>"/user/2", :schema=>[["integer", :id, 2, 2], ["text", :name, 4, "asd"], [:password, :password, 4, "asdf"], ["text", :description, 0, "xxxx"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []]
61
+ >> @client.read
62
+ => [[:instance, {:url=>"/user/1", :schema=>[["integer", :id, 2, 1], ["text", :name, 4, "asdf"], [:password, :password, 4, "asdf"], ["text", :description, 0, "xxxx"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []]]
63
+ >> @client.read({},:instance_id => 2, :code => 404)
64
+ => [:error, {:description=>"Not Found", :error_type=>"routing", :error_details=>nil}]
65
+ >> @client.update({:'user[description]' => 'ddd'},:instance_id => 1)
66
+ => [:instance, {:url=>"/user/1", :schema=>[["integer", :id, 2, 1], ["text", :name, 4, "asdf"], [:password, :password, 4, "asdf"], ["text", :description, 0, "ddd"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []]
67
+ >> @client.update({},:instance_id => 1)
68
+ => [:instance, {:url=>"/user/1", :schema=>[["integer", :id, 2, 1], ["text", :name, 4, "asdf"], [:password, :password, 4, "asdf"], ["text", :description, 0, "ddd"]], :new_rec=>false, :actions=>nil, :name=>"user"}, []]
69
+
70
+ >> MR::User.reject_cols![:new?][true] << 'name'
71
+ => [/^id$/, /_type$/, /date_(created|updated)/, "name"]
72
+ >> MR::User.new.rest_cols
73
+ => [:password, :description]
74
+ >> @client.read({}, :method => 'new')
75
+ => [:instance, {:new_rec=>true, :actions=>nil, :url=>"/user/", :schema=>[[:password, :password, 4, nil], ["text", :description, 0, nil]], :name=>"user"}, []]
76
+ >> @client.read
77
+ => [[:instance, {:new_rec=>false, :actions=>nil, :url=>"/user/1", :schema=>[["integer", :id, 2, 1], ["text", :name, 4, "asdf"], [:password, :password, 4, "asdf"], ["text", :description, 0, "ddd"]], :name=>"user"}, []]]
78
+ >> MR::User.reject_cols![:new?][false] << 'name'
79
+ => [/_type$/, "name"]
80
+ >> @client.read
81
+ => [[:instance, {:new_rec=>false, :actions=>nil, :url=>"/user/1", :schema=>[["integer", :id, 2, 1], [:password, :password, 4, "asdf"], ["text", :description, 0, "ddd"]], :name=>"user"}, []]]
82
+
83
+ >> MR::User.ro_cols![:new?][false] << 'description'
84
+ => [/^id$/, /_id$/, /date_(created|updated)/, "description"]
85
+ >> @client.read({},:method => 'new')
86
+ => [:instance, {:new_rec=>true, :actions=>nil, :url=>"/user/", :schema=>[[:password, :password, 4, nil], ["text", :description, 0, nil]], :name=>"user"}, []]
87
+ >> @client.read
88
+ => [[:instance, {:new_rec=>false, :actions=>nil, :url=>"/user/1", :schema=>[["integer", :id, 2, 1], [:password, :password, 4, "asdf"], ["text", :description, 2, "ddd"]], :name=>"user"}, []]]
89
+
90
+ >> MR::User.hidden_cols![:new?][true]=['password']
91
+ => ["password"]
92
+ >> @client.read({},:method => 'new')
93
+ => [:instance, {:new_rec=>true, :actions=>nil, :url=>"/user/", :schema=>[[:password, :password, 5, nil], ["text", :description, 0, nil]], :name=>"user"}, []]
94
+
95
+ >> MR::User.required_cols![:new?][true]=['description']
96
+ => ["description"]
97
+ >> @client.read({},:method => 'new')
98
+ => [:instance, {:new_rec=>true, :actions=>nil, :url=>"/user/", :schema=>[[:password, :password, 5, nil], ["text", :description, 4, nil]], :name=>"user"}, []]
99
+
data/rdoc/plugins.rdoc ADDED
@@ -0,0 +1,35 @@
1
+
2
+ == The Plugins System
3
+
4
+ Marley activates both of them for Sequel::Model. This will soon change to an option.
5
+
6
+ :include: rdoc/hello.rb
7
+
8
+ :include: rdoc/example_plugin.rb
9
+
10
+ setup
11
+ @client=Marley::TestClient.new(:resource_name => 'hello')
12
+ @plugin=Marley.plugin('example_plugin')
13
+ end
14
+ example: without the plugin, then with the plugin
15
+
16
+ >> MR.constants
17
+ => ["Hello"]
18
+ >> @client.read
19
+ => "\"Hello World!\""
20
+ >> @client.create({}, :code => 404)
21
+ => [:error, {:description=>"Not Found", :error_type=>"routing", :error_details=>nil}]
22
+
23
+ >> @plugin.apply('Hello')
24
+ => nil
25
+ >> @client.create({})
26
+ => " world"
27
+ >> @client.create({},:method => 'howdy')
28
+ => "howdy world"
29
+
30
+ == Included Plugins
31
+
32
+ Marley comes with 1 external plugin (there are others in the included Joints, described later):
33
+
34
+ :include: rdoc/orm_rest_convenience_plugin.rdoc
35
+
data/rdoc/reggae.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'marley/utils.rb'
2
+ require 'marley/reggae.rb'
3
+
data/rdoc/reggae.rdoc ADDED
@@ -0,0 +1,11 @@
1
+ ==Reggae
2
+
3
+ The server and client use a JSON based data representation format "Reggae." Reggae.ebnf describes the format in canonical form, and reggae.rb contains a Reggae parser and generator.
4
+
5
+ The Reggae class generates and parses Reggae JSON arrays. See reggae.ebnf for the syntax
6
+
7
+ setup
8
+ @reggae=Marley::Reggae
9
+ end
10
+
11
+
@@ -0,0 +1,13 @@
1
+
2
+ ===Reggae Generator
3
+
4
+ examples: generate an instance
5
+
6
+ >> @instance=Marley::ReggaeInstance.new({:name => 'foo',:schema => []})
7
+ => [:instance, {:schema=>[], :name=>"foo"}, []]
8
+
9
+ >> @link=Marley::ReggaeLink.new({:url => '/', :title => 'asdf'})
10
+ => [:link, {:url=>"/", :title=>"asdf"}, []]
11
+ >> @link.update(:url => '/asdf/')
12
+ => [:link, {:url=>"/asdf/", :title=>"asdf"}, []]
13
+
@@ -0,0 +1,44 @@
1
+
2
+ ===Reggae Parser
3
+
4
+ examples: leave non-Reggae arrays as is
5
+
6
+ >> Marley::Reggae.new([])
7
+ => []
8
+ >> Marley::Reggae.new(['asdf','ssss'])
9
+ => ["asdf", "ssss"]
10
+ >> Marley::Reggae.new(['asdf','ssss']).class
11
+ => Marley::Reggae
12
+ >> Marley::Reggae.new(['asdf',{}]).to_resource
13
+ => ["asdf", {}]
14
+ >> Marley::Reggae.new(['asdf',{}]).to_resource.class
15
+ => Marley::Reggae
16
+
17
+ examples: a simple Reggae Resource
18
+
19
+ >> Marley::Reggae.new(['resource',{}]).to_resource.class
20
+ => Marley::ReggaeResource
21
+
22
+ This also works:
23
+
24
+ >> Marley::Reggae.get_resource(['resource',{}]).class
25
+ => Marley::ReggaeResource
26
+
27
+ examples: parse a ReggaeSection
28
+
29
+ >> @section=Marley::Reggae.new([:section, {}]).to_resource
30
+ => [:section, {}]
31
+ >> @section.properties
32
+ => {}
33
+
34
+ examples: parse a ReggaeSection with a title
35
+
36
+ >> @section=Marley::Reggae.new([:section, {:title => 'asdf'}]).to_resource
37
+ => [:section, {:title=>"asdf"}]
38
+ >> @section.title
39
+ => "asdf"
40
+ >> @section.properties
41
+ => {:title=>"asdf"}
42
+
43
+
44
+
@@ -0,0 +1,13 @@
1
+
2
+ require 'messages_joint.rb'
3
+
4
+ Marley.joint('section')
5
+ Marley.plugin('section').apply(MR.constants)
6
+
7
+ module Marley
8
+ module Resources
9
+ def User.section_link
10
+ super.update(:title => 'Account',:url => current_user.url)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ == The Section Joint
2
+
3
+ setup
4
+ @client=Marley::TestClient.new
5
+ DB[:users].delete
6
+ DB[:messages].delete
7
+ DB[:messages_users].delete
8
+ DB[:SQLITE_SEQUENCE].update(:seq => 0)
9
+ user_client=Marley::TestClient.new(:resource_name => 'user')
10
+ user=user_client.read({},:method => 'new').set_values(:password => 'asdfasdf', :confirm_password => 'asdfasdf')
11
+ (1 .. 5).each { |i|
12
+ user_client.create(user.set_values(:name => "user#{i}"))
13
+ instance_variable_set(:"@client#{i}", Marley::TestClient.new(:auth => ["user#{i}",'asdfasdf'] ))
14
+ }
15
+ end
16
+
17
+
18
+ examples:
19
+