marley 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +2 -27
- data/Rakefile +3 -0
- data/TODO +11 -9
- data/lib/joints/basic_menu_system.rb +6 -23
- data/lib/joints/basic_messaging.rb +3 -3
- data/lib/joints/basic_user.rb +2 -2
- data/lib/joints/tagged_messaging.rb +4 -4
- data/lib/joints/tagging.rb +5 -9
- data/lib/marley.rb +21 -36
- data/lib/marley/joint.rb +4 -0
- data/lib/marley/reggae.rb +15 -10
- data/lib/marley/test_helpers.rb +1 -2
- data/lib/marley/utils.rb +36 -0
- data/lib/sequel/plugins/rest_convenience.rb +72 -76
- data/marley-0.3.0.gem +0 -0
- data/marley.gemspec +4 -2
- data/reggae.ebnf +11 -5
- data/test/tagged_messaging_tests.rb +4 -4
- data/test/test.sqlite3 +0 -0
- data/test/user_tests.rb +1 -1
- metadata +6 -5
- data/forum_tests.rb +0 -356
- data/lib/joints/user_based_navigation.rb +0 -39
data/README.rdoc
CHANGED
@@ -43,36 +43,11 @@ Marley activates both of them for Sequel::Model. This will soon change to an op
|
|
43
43
|
One of the things that the RestConvenience Sequel plugin does is add a #controller method to affected models. This method instantiates and returns a ModelController object for the model in question. At initialization, the Controller parses the request path to determine the model instances to which the request refers.
|
44
44
|
|
45
45
|
|
46
|
-
|
46
|
+
:include: rdoc/joints.rdoc
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
* Find a file named '_joint_name_' in the 'joints/' directory.
|
51
|
-
* Require that file.
|
52
|
-
* run its #smoke method.
|
53
|
-
|
54
|
-
The Joint#smoke method looks for 3 modules inside the joint's namespace: Resources, ClassMethods, and InstanceMethods.
|
55
|
-
|
56
|
-
* if the Resources module exists, Joint#smoke will copy all of its constants to Marley::Resources.
|
57
|
-
* If the ClassMethods module exists, Joint#smoke will cycle through the modules within it, and extend objects in Marley::Resources with the same name.
|
58
|
-
* If the InstanceMethods module exists, Joint#smoke will cycle through the modules within it, and call their #append_features with the corresponding objects in Marley::Resources with the same name.
|
59
|
-
|
60
|
-
For now, there are 5 joints included in the Marley distribution:
|
61
|
-
|
62
|
-
* Basic User
|
63
|
-
* Basic Messaging
|
64
|
-
* Basic Menu System
|
65
|
-
* Tagging
|
66
|
-
* Tagged Messaging
|
67
|
-
|
68
|
-
With a bit of configuration, these comprise the example forum application, which is in turn the targt for the test suite.
|
69
|
-
|
70
|
-
==Reggae
|
71
|
-
|
72
|
-
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.
|
48
|
+
:include: rdoc/reggae.rdoc
|
73
49
|
|
74
50
|
==Jamaica
|
75
51
|
|
76
52
|
The default Marley client is "Jamaica", which consists of JS/CSS for browsers. It sucks right now and I'm hoping somebody takes it over as a sub-project, but it does work - at least on FF.
|
77
53
|
|
78
|
-
|
data/Rakefile
CHANGED
data/TODO
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
-
|
4
|
-
-
|
5
|
-
|
3
|
+
- complete switchover to tdoc
|
4
|
+
- joint dependencies
|
5
|
+
- rename client to sth like output
|
6
|
+
- move all output there
|
7
|
+
- fix JS
|
6
8
|
- ditch Sequel dependency
|
9
|
+
- ORM as a Joint??
|
10
|
+
- automate sequel plugin loading in options
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
- better logging
|
12
|
+
-----------------
|
11
13
|
|
12
|
-
- hints for resources/columns
|
13
14
|
- better filtering options for posts
|
14
|
-
|
15
|
-
|
15
|
+
- better logging
|
16
|
+
- implement instance_list
|
17
|
+
- expose validation reflections to views
|
16
18
|
??? caching protocol for autocompleters/validation options
|
17
19
|
|
@@ -1,34 +1,17 @@
|
|
1
1
|
|
2
|
-
module Sequel::Plugins::RestSection
|
3
|
-
SECTION_PROPS='name','title','description','navigation'
|
4
|
-
module ClassMethods
|
5
|
-
SECTION_PROPS.each {|p| attr_accessor :"section_#{p}"}
|
6
|
-
def section
|
7
|
-
if SECTION_PROPS.find {|p| send(:"section_#{p}").to_s > ''}
|
8
|
-
Marley::ReggaeSection.new(SECTION_PROPS.inject({}) do |props,p|
|
9
|
-
prop=send(:"section_#{p}")
|
10
|
-
props[p.to_sym]=prop.class==Hash ? prop[$request[:user].class] : prop
|
11
|
-
props
|
12
|
-
end)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
2
|
module Marley
|
18
3
|
module Joints
|
19
4
|
class BasicMenuSystem < Joint
|
5
|
+
RestSection=Marley::Utils.rest_opts_mod('section',['name','title','description','navigation'],lambda {$request[:user].class})
|
20
6
|
def smoke
|
21
7
|
super
|
22
|
-
Sequel::Model.
|
8
|
+
Sequel::Model.extend RestSection
|
23
9
|
end
|
24
10
|
module Resources
|
25
11
|
class Menu
|
26
|
-
|
27
|
-
attr_accessor :sections
|
28
|
-
end
|
29
|
-
include Sequel::Plugins::RestSection::ClassMethods
|
12
|
+
include RestSection
|
30
13
|
def self.rest_get
|
31
|
-
new.
|
14
|
+
new.rest_section
|
32
15
|
end
|
33
16
|
def self.requires_user?
|
34
17
|
! $request[:path].to_a.empty?
|
@@ -44,8 +27,8 @@ module Marley
|
|
44
27
|
else
|
45
28
|
@section_title = "#{$request[:opts][:app_name]} Main Menu"
|
46
29
|
@section_description="Welcome to #{$request[:opts][:app_name]}, #{$request[:user].name}"
|
47
|
-
@section_navigation=(
|
48
|
-
if (resource=MR.const_get(rn)).respond_to?(:
|
30
|
+
@section_navigation=(MR.constants - [self.class.to_s.sub(/.*::/,'').to_sym]).map do |rn|
|
31
|
+
if (resource=MR.const_get(rn)).respond_to?(:rest_section) && (s=resource.rest_section) && s.title
|
49
32
|
[:link,{:title => s.title, :description =>s.description, :url => "#{resource.resource_name}/section" }]
|
50
33
|
end
|
51
34
|
end.compact
|
@@ -17,7 +17,7 @@ module Marley
|
|
17
17
|
super << [:text,:author,RESTRICT_RO,author.to_s]
|
18
18
|
end
|
19
19
|
def authorize_rest_get(meth)
|
20
|
-
current_user_role && (meth.nil? ||
|
20
|
+
current_user_role && (meth.nil? || self.class.actions_get.include?(meth))
|
21
21
|
end
|
22
22
|
def authorize_rest_put(meth); false; end
|
23
23
|
def after_initialize
|
@@ -38,7 +38,7 @@ module Marley
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
class PrivateMessage < Message
|
41
|
-
|
41
|
+
@actions_get=['reply','reply_all']
|
42
42
|
def rest_cols; super << :recipients; end
|
43
43
|
def current_user_role
|
44
44
|
super || (recipients.match(/\b#{$request[:user][:name]}\b/) && "recipient")
|
@@ -73,7 +73,7 @@ module Marley
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
class Post < Message
|
76
|
-
|
76
|
+
@actions_get=['reply']
|
77
77
|
def current_user_role
|
78
78
|
super || 'reader'
|
79
79
|
end
|
data/lib/joints/basic_user.rb
CHANGED
@@ -10,9 +10,9 @@ module Marley
|
|
10
10
|
attr_reader :menus
|
11
11
|
attr_accessor :old_password,:password, :confirm_password
|
12
12
|
def self.requires_user?
|
13
|
-
! ($request[:verb]=='rest_post')
|
13
|
+
! ($request[:verb]=='rest_post' || ($request[:verb]=='rest_get' && $request[:path][1]=='new'))
|
14
14
|
end
|
15
|
-
def self.
|
15
|
+
def self.rest_section
|
16
16
|
ReggaeSection.new( {:title => 'User Info', :name => self.to_s.sub(/.*::/,'').underscore, :navigation => []}) if $request[:user].class == self
|
17
17
|
end
|
18
18
|
def write_cols;[:name,:email,:password,:confirm_password,:old_password];end
|
@@ -39,7 +39,7 @@ module Marley
|
|
39
39
|
module Message
|
40
40
|
def rest_associations
|
41
41
|
if ! new?
|
42
|
-
[ respond_to?(:public_tags) ? :public_tags : nil, respond_to?(:user_tags) ? user_tags_dataset.
|
42
|
+
[ respond_to?(:public_tags) ? :public_tags : nil, respond_to?(:user_tags) ? user_tags_dataset.current_user_dataset : nil].compact
|
43
43
|
end
|
44
44
|
end
|
45
45
|
def new_tags
|
@@ -78,18 +78,18 @@ module Marley
|
|
78
78
|
end
|
79
79
|
class PrivateMessage < MJ::BasicMessaging::Resources::PrivateMessage
|
80
80
|
attr_accessor :tags
|
81
|
+
@actions_get= superclass.actions_get << 'new_tags'
|
81
82
|
@section_title='Private Messages'
|
82
83
|
@section_name='pms'
|
83
84
|
def self.section_navigation
|
84
85
|
$request[:user].user_tags.map{|t| [:link,{:url => "/private_message?private_message[tag]=#{t.tag}",:title => t.tag.humanize}]}.unshift(PrivateMessage.reggae_link('new'))
|
85
86
|
end
|
86
|
-
def get_actions; super << 'new_tags';end
|
87
87
|
def rest_schema
|
88
88
|
super << [:text, :tags, 0,tags]
|
89
89
|
end
|
90
90
|
def reply
|
91
91
|
r=super
|
92
|
-
r.tags=(user_tags_dataset.
|
92
|
+
r.tags=(user_tags_dataset.current_user_dataset.map{|t|t.tag} - RESERVED_PM_TAGS).join(',')
|
93
93
|
r
|
94
94
|
end
|
95
95
|
def after_create
|
@@ -104,7 +104,7 @@ module Marley
|
|
104
104
|
def self.section_navigation
|
105
105
|
MR::Tag.filter(:user_id => nil).map{|t| [:link,{:url => "/post?post[tag]=#{t.tag}",:title => t.tag.humanize}]}.unshift([:link,{:url => '/post?post[untagged]=true',:title => 'Untagged Messages'}]).unshift(Post.reggae_link('new'))
|
106
106
|
end
|
107
|
-
|
107
|
+
@actions_get=(superclass.actions_get << 'new_user_tags') << 'new_tags'
|
108
108
|
def rest_schema
|
109
109
|
(super << [:text, :tags, 0,tags] ) << [:text, :my_tags, 0,my_tags]
|
110
110
|
end
|
data/lib/joints/tagging.rb
CHANGED
@@ -5,7 +5,7 @@ module Marley
|
|
5
5
|
class Tag < Sequel::Model
|
6
6
|
def self.tagging_for(klass, user_class=nil,join_table=nil)
|
7
7
|
current_user_tags=Module.new do
|
8
|
-
def
|
8
|
+
def current_user_dataset
|
9
9
|
filter(:tags__user_id => $request[:user][:id])
|
10
10
|
end
|
11
11
|
end
|
@@ -13,22 +13,16 @@ module Marley
|
|
13
13
|
join_table||=:"#{tagged_class.table_name}_tags"
|
14
14
|
klass_key=:"#{tagged_class.table_name.to_s.singularize}_id"
|
15
15
|
tag_key=:tag_id
|
16
|
-
attr_accessor klass_key
|
17
16
|
if user_class
|
18
17
|
UserTag.many_to_many klass.underscore.to_sym,:class => "Marley::Resources::#{klass}", :join_table => join_table,:left_key => tag_key,:right_key => klass_key,:extend => current_user_tags
|
19
|
-
tagged_class.many_to_many :user_tags, :class => 'Marley::Resources::UserTag',:join_table => join_table,:left_key => klass_key,:right_key => tag_key, :extend => current_user_tags
|
18
|
+
tagged_class.many_to_many :user_tags, :class => 'Marley::Resources::UserTag',:join_table => join_table,:left_key => klass_key,:right_key => tag_key, :extend => [current_user_tags,Marley::RestActions]
|
20
19
|
Marley::Resources.const_get(user_class).one_to_many :user_tags, :class => 'Marley::Resources::UserTag'
|
21
20
|
UserTag.many_to_one user_class.underscore.to_sym,:class => "Marley::Resources::#{user_class}"
|
22
21
|
else
|
23
22
|
PublicTag.many_to_many klass.underscore.to_sym,:class => "Marley::Resources::#{klass}", :join_table => join_table,:left_key => tag_key,:right_key => klass_key
|
24
|
-
tagged_class.many_to_many :public_tags,:class => "Marley::Resources::PublicTag",:join_table => join_table,:left_key => klass_key,:right_key => tag_key
|
23
|
+
tagged_class.many_to_many :public_tags,:class => "Marley::Resources::PublicTag",:join_table => join_table,:left_key => klass_key,:right_key => tag_key, :extend => Marley::RestActions
|
25
24
|
end
|
26
25
|
end
|
27
|
-
def to_a
|
28
|
-
a=super
|
29
|
-
a[1][:delete_action]='remove_parent'
|
30
|
-
a
|
31
|
-
end
|
32
26
|
def validate
|
33
27
|
validates_presence :tag
|
34
28
|
validates_unique [:tag,:user_id]
|
@@ -50,9 +44,11 @@ module Marley
|
|
50
44
|
end
|
51
45
|
class PublicTag < Tag
|
52
46
|
set_dataset DB[:tags].filter(:user_id => nil)
|
47
|
+
@actions_delete='remove_parent'
|
53
48
|
end
|
54
49
|
class UserTag < Tag
|
55
50
|
set_dataset DB[:tags].filter(~{:user_id => nil})
|
51
|
+
@actions_delete='remove_parent'
|
56
52
|
end
|
57
53
|
end
|
58
54
|
end
|
data/lib/marley.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
require 'json/ext'
|
3
3
|
require 'json/add/core'
|
4
|
+
require 'marley/reggae'
|
5
|
+
require 'marley/utils'
|
4
6
|
require 'rack'
|
5
7
|
require 'rack/auth/basic'
|
6
8
|
require 'rack/builder'
|
9
|
+
require 'sequel'
|
7
10
|
require 'sequel/plugins/rest_convenience'
|
8
11
|
require 'sequel/plugins/rest_auth'
|
9
12
|
require 'marley/controllers'
|
10
|
-
require 'marley/reggae'
|
11
13
|
require 'logger'
|
12
14
|
Sequel.extension :inflector
|
13
15
|
|
@@ -20,34 +22,17 @@ Sequel::Model.plugin :timestamps, :create => :date_created, :update => :date_upd
|
|
20
22
|
log_fn='log/marley.log'
|
21
23
|
$log=Logger.new(File.exists?(log_fn) ? log_fn : $stdout)
|
22
24
|
|
23
|
-
# This is the main Marley namespace
|
24
25
|
module Marley
|
25
26
|
JOINT_DIRS=[File.expand_path("joints/",File.dirname(__FILE__)),"#{Dir.pwd}/joints"]
|
26
|
-
# @see config
|
27
27
|
DEFAULT_OPTS={:http_auth => true,:app_name => 'Application',:port => 1620,:default_user_class => :User, :auth_class => :User,:default_resource => 'Menu', :server => 'thin'}
|
28
28
|
RESP_CODES={'get' => 200,'post' => 201,'put' => 204,'delete' => 204}
|
29
29
|
|
30
|
-
# All constants in the Resources namespace should refer to public resources accessible to clients, subject, of course, to authentication/authorization.
|
31
|
-
#
|
32
|
-
# Resources MUST respond to one or more of #controller, #rest_get, #rest_post, #rest_put, #rest_delete
|
33
|
-
#
|
34
|
-
# If a Resource implements a #controller method, the method MUST return an object which responds to one or more of #rest_get, #rest_post, #rest_put, #rest_delete
|
35
30
|
module Resources
|
36
31
|
end
|
37
|
-
# The default namespace for Joints. Joints MUST implement a #smoke method
|
38
32
|
module Joints
|
39
33
|
end
|
40
34
|
require 'marley/joint' #this needs to happen after Marley::Resources is defined
|
41
35
|
|
42
|
-
# Override default Marley configuration
|
43
|
-
# @param [Hash] opts A hash containing Marley configuration options
|
44
|
-
# @option opts [Boolean] :http_auth Whether or not to use http authentication
|
45
|
-
# @option opts [String] :app_name Currently used by Jamaica to set page title
|
46
|
-
# @option opts [Number] :port Port on which to run the server
|
47
|
-
# @option opts [Object] :default_user_class The default class of the new user assigned to $request[:user] if no actual user is authenticated
|
48
|
-
# @option opts [Object] :auth_class The class used to authenticate requests. MUST respond to #authenticate
|
49
|
-
# @option opts [Object] :default_resource The resource called in response to a request to '/'
|
50
|
-
# @option opts [String] :server the Rack web server to be used.
|
51
36
|
def self.config(opts=nil)
|
52
37
|
@marley_opts||=DEFAULT_OPTS
|
53
38
|
@marley_opts.merge!(opts) if opts
|
@@ -55,17 +40,15 @@ module Marley
|
|
55
40
|
@marley_opts
|
56
41
|
end
|
57
42
|
|
58
|
-
# Loads a joint and and calls its #smoke method
|
59
|
-
# @param [String] joint_name The name of the joint to load and smoke - additional paramters passed through to the joint itself
|
60
43
|
def self.joint(joint_name, *opts)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
44
|
+
unless Marley::Joints.constants.include?(joint_name.camelize)
|
45
|
+
joint_d=JOINT_DIRS.find {|d| File.exists?("#{d}/#{joint_name}.rb") }
|
46
|
+
require "#{joint_d}/#{joint_name}"
|
47
|
+
@marley_opts && @marley_opts[:client] && @marley_opts[:client].joint(joint_d,joint_name)
|
48
|
+
end
|
49
|
+
Marley::Joints.const_get(joint_name.camelize).new(*opts).smoke
|
65
50
|
end
|
66
51
|
|
67
|
-
# Runs the server
|
68
|
-
# @param (see #config)
|
69
52
|
def self.run(opts={})
|
70
53
|
@marley_opts||=DEFAULT_OPTS
|
71
54
|
marley_opts=@marley_opts.merge!(opts)
|
@@ -75,7 +58,7 @@ module Marley
|
|
75
58
|
run(Marley::Router.new(marley_opts))
|
76
59
|
}.to_app,{:Port => @marley_opts[:port]})
|
77
60
|
end
|
78
|
-
class Router
|
61
|
+
class Router
|
79
62
|
def initialize(opts={},app=nil)
|
80
63
|
@opts=DEFAULT_OPTS.merge(opts)
|
81
64
|
end
|
@@ -104,16 +87,23 @@ module Marley
|
|
104
87
|
raise RoutingError unless Resources.constants.include?(rn)
|
105
88
|
@resource=Resources.const_get(rn)
|
106
89
|
raise AuthenticationError if @opts[:http_auth] && @resource.respond_to?('requires_user?') && @resource.requires_user? && $request[:user].new?
|
107
|
-
@controller
|
90
|
+
@controller=nil
|
91
|
+
@controller=@resource.controller if @resource.respond_to?(:controller)
|
92
|
+
@controller=@resource if @resource.respond_to?($request[:verb])
|
93
|
+
raise RoutingError unless @controller
|
108
94
|
json=@controller.send($request[:verb]).to_json
|
109
95
|
html=@opts[:client] ? @opts[:client].to_s(json) : json
|
110
96
|
resp_code=RESP_CODES[verb]
|
111
97
|
headers||={'Content-Type' => "#{$request[:content_type]}; charset=utf-8"}
|
112
98
|
[resp_code,headers,$request[:content_type].match(/json/) ? json : html]
|
113
99
|
rescue Sequel::ValidationFailed
|
114
|
-
ValidationError.new($!.errors).
|
100
|
+
ValidationError.new($!.errors).to_a
|
115
101
|
rescue
|
116
|
-
|
102
|
+
if $!.class.superclass==MarleyError
|
103
|
+
$!.to_a
|
104
|
+
else
|
105
|
+
p $!,$!.backtrace
|
106
|
+
end
|
117
107
|
ensure
|
118
108
|
$log.info $request.merge({:request => nil,:user => $request[:user] ? $request[:user].name : nil})
|
119
109
|
end
|
@@ -129,7 +119,7 @@ module Marley
|
|
129
119
|
def log_error
|
130
120
|
$log.fatal("#$!.message}\n#{$!.backtrace}")
|
131
121
|
end
|
132
|
-
def
|
122
|
+
def to_a
|
133
123
|
log_error
|
134
124
|
json=[:error,{:error_type => self.class.name.underscore.sub(/_error$/,'').sub(/^marley\//,''),:description => self.class.description, :error_details => self.class.details}].to_json
|
135
125
|
self.class.headers||={'Content-Type' => "#{$request[:content_type]}; charset=utf-8"}
|
@@ -166,11 +156,6 @@ module Marley
|
|
166
156
|
$log.fatal("path:#{$request[:path]}\n msg:#{$!.message}\n backtrace:#{$!.backtrace}")
|
167
157
|
end
|
168
158
|
end
|
169
|
-
module Utils
|
170
|
-
def self.hash_keys_to_syms(hsh)
|
171
|
-
hsh.inject({}) {|h,(k,v)| h[k.to_sym]= v.class==Hash ? hash_keys_to_syms(v) : v;h }
|
172
|
-
end
|
173
|
-
end
|
174
159
|
end
|
175
160
|
MR=Marley::Resources
|
176
161
|
MJ=Marley::Joints
|
data/lib/marley/joint.rb
CHANGED
@@ -5,6 +5,9 @@ module Marley
|
|
5
5
|
# - ClassMethods - Modules within this module will extend any constant in Marley::Resources with the same name.
|
6
6
|
# - InstanceMethods - Modules within this module will append their features to any constant in Marley::Resources with the same name.
|
7
7
|
class Joint
|
8
|
+
#def self.provides(*args)
|
9
|
+
# [:resources,:class_methods,:]
|
10
|
+
#end
|
8
11
|
def initialize(opts={})
|
9
12
|
config(opts)
|
10
13
|
end
|
@@ -20,6 +23,7 @@ module Marley
|
|
20
23
|
end
|
21
24
|
end
|
22
25
|
end
|
26
|
+
self
|
23
27
|
end
|
24
28
|
def config(opts)
|
25
29
|
@opts=(@opts || {}).merge(opts)
|
data/lib/marley/reggae.rb
CHANGED
@@ -1,4 +1,12 @@
|
|
1
1
|
|
2
|
+
RESTRICT_HIDE=1
|
3
|
+
RESTRICT_RO=2
|
4
|
+
RESTRICT_REQ=4
|
5
|
+
TYPE_INDEX=0
|
6
|
+
NAME_INDEX=1
|
7
|
+
RESTRICTIONS_INDEX=2
|
8
|
+
require 'sequel'
|
9
|
+
Sequel.extension :inflector
|
2
10
|
module Marley
|
3
11
|
# @see file:reggae.ebnf for Raggae sytax
|
4
12
|
class Reggae < Array
|
@@ -21,7 +29,7 @@ module Marley
|
|
21
29
|
attr_accessor :properties,:contents
|
22
30
|
# @param [Array] *args an array in Reggae syntax
|
23
31
|
def initialize(*args)
|
24
|
-
super
|
32
|
+
super
|
25
33
|
if is_resource?
|
26
34
|
@resource_type=self[0]=self[0].to_sym
|
27
35
|
self[1]=Utils.hash_keys_to_syms(self[1]) if self[1].class==Hash
|
@@ -29,11 +37,11 @@ module Marley
|
|
29
37
|
@contents=self[2 .. -1]
|
30
38
|
self.class.mk_prop_methods
|
31
39
|
else
|
32
|
-
replace(map {|r| Reggae.new(r).to_resource})
|
40
|
+
replace(map {|r| r.class==Array ? Reggae.new(r).to_resource : r})
|
33
41
|
end
|
34
42
|
end
|
35
43
|
def is_resource?
|
36
|
-
[String, Symbol].include?(self[0].class) && self[
|
44
|
+
[String, Symbol].include?(self[0].class) && Marley.constants.include?("reggae_#{self[0]}".camelcase)
|
37
45
|
end
|
38
46
|
def contents=(*args)
|
39
47
|
self[2]=*args
|
@@ -55,7 +63,7 @@ module Marley
|
|
55
63
|
def initialize(*args)
|
56
64
|
@resource_type=self.class.to_s.sub(/.*Reggae/,'').underscore.to_sym
|
57
65
|
if args[0].class==Hash
|
58
|
-
initialize [@resource_type,args[0]]
|
66
|
+
initialize [@resource_type,args[0],args[1 .. -1]]
|
59
67
|
else
|
60
68
|
super
|
61
69
|
end
|
@@ -71,7 +79,7 @@ module Marley
|
|
71
79
|
properties :title,:description,:url
|
72
80
|
end
|
73
81
|
class ReggaeInstance < ReggaeResource
|
74
|
-
properties :name,:new_rec,:schema,:search,:url,:
|
82
|
+
properties :name,:new_rec,:schema,:search,:url,:actions
|
75
83
|
attr_accessor :schema
|
76
84
|
def initialize(*args)
|
77
85
|
super
|
@@ -84,9 +92,6 @@ module Marley
|
|
84
92
|
params
|
85
93
|
end
|
86
94
|
end
|
87
|
-
def instance_action_url(action_name)
|
88
|
-
"#{url}#{action_name}" if get_actions.include?(action_name.to_s)
|
89
|
-
end
|
90
95
|
def col_value(col_name,col_value=nil)
|
91
96
|
col=@schema[col_name]
|
92
97
|
col.col_value=col_value if col_value
|
@@ -98,7 +103,7 @@ module Marley
|
|
98
103
|
end
|
99
104
|
end
|
100
105
|
class ReggaeInstanceList < ReggaeResource
|
101
|
-
properties :name,:description,:
|
106
|
+
properties :name,:description,:actions,:items
|
102
107
|
#not implemented yet
|
103
108
|
end
|
104
109
|
class ReggaeMsg < ReggaeResource
|
@@ -109,7 +114,7 @@ module Marley
|
|
109
114
|
end
|
110
115
|
class ReggaeSchema < Array
|
111
116
|
def initialize(*args)
|
112
|
-
super
|
117
|
+
super
|
113
118
|
replace(map{|spec| ReggaeColSpec.new(spec)})
|
114
119
|
end
|
115
120
|
def [](i)
|