marley 0.3.0 → 0.4.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.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)
|