marley 0.5.0 → 0.6.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.
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
@@ -1,41 +0,0 @@
1
-
2
- module Marley
3
- module Joints
4
- class BasicMenuSystem < Joint
5
- RestSection=Marley::Utils.rest_opts_mod('section',['name','title','description','navigation'],lambda {$request[:user].class})
6
- def smoke
7
- super
8
- Sequel::Model.extend RestSection
9
- end
10
- module Resources
11
- class Menu
12
- include RestSection
13
- def self.rest_get
14
- new.rest_section
15
- end
16
- def self.requires_user?
17
- ! $request[:path].to_a.empty?
18
- end
19
- def initialize
20
- @name='main'
21
- if $request[:user].new?
22
- u=$request[:user].to_a
23
- u[1].merge!({:description => 'If you don\'t already have an account, please create one here:'})
24
- @section_title="Welcome to #{$request[:opts][:app_name]}"
25
- @section_description='Login or signup here.'
26
- @section_navigation=[LOGIN_FORM,u]
27
- else
28
- @section_title = "#{$request[:opts][:app_name]} Main Menu"
29
- @section_description="Welcome to #{$request[:opts][:app_name]}, #{$request[:user].name}"
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
32
- [:link,{:title => s.title, :description =>s.description, :url => "#{resource.resource_name}/section" }]
33
- end
34
- end.compact
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,88 +0,0 @@
1
- require 'sanitize'
2
-
3
- module Marley
4
- module Joints
5
- class BasicMessaging < Joint
6
- module Resources
7
- class Message < Sequel::Model
8
- plugin :single_table_inheritance, :message_type, :model_map => lambda{|v| v ? MR.const_get(v.to_s) : ''}, :key_map => lambda{|klass|klass.name.sub(/.*::/,'')}
9
- # CHANGE NEEDED:tree is unnecessary, instead, select by thread_id, order by parent_id, inject [] for nesting. Should be much faster.
10
- plugin :tree
11
- many_to_one :author, :class => :'Marley::Resources::User'
12
- @owner_col=:author_id
13
- def rest_cols; [:id,:author_id,:message,:title,:parent_id]; end
14
- def write_cols; new? ? rest_cols - [:id] : []; end
15
- def required_cols; write_cols - [:parent_id]; end
16
- def rest_schema
17
- super << [:text,:author,RESTRICT_RO,author.to_s]
18
- end
19
- def authorize_rest_get(meth)
20
- current_user_role && (meth.nil? || self.class.actions_get.include?(meth))
21
- end
22
- def authorize_rest_put(meth); false; end
23
- def after_initialize
24
- super
25
- if new?
26
- self.thread_id=parent ? parent.thread_id : Message.select(:max.sql_function(:thread_id).as(:tid)).all[0][:tid].to_i + 1
27
- end
28
- end
29
- def before_save
30
- self.message=Sanitize.clean(self.message,:elements => %w[blockquote em strong ul ol li p code])
31
- end
32
- def validate
33
- validates_presence [:author,:message,:title]
34
- validates_type MR::User, :author
35
- end
36
- def thread
37
- children.length > 0 ? to_a << children.map{|m| m.thread} : to_a
38
- end
39
- end
40
- class PrivateMessage < Message
41
- @actions_get=['reply','reply_all']
42
- def rest_cols; super << :recipients; end
43
- def current_user_role
44
- super || (recipients.match(/\b#{$request[:user][:name]}\b/) && "recipient")
45
- end
46
- def authorize_rest_get(meth)
47
- super && ($request[:user]==author || self.recipients.match(/\b#{$request[:user].name}\b/))
48
- end
49
- def authorize_rest_post(meth)
50
- meth.to_s > '' && (author_id==$request[:user][:id] || recipients.match(/\b#{$request[:user][:name]}\b/))
51
- end
52
- def self.authorize_rest_post(asdf)
53
- true #may need to change this, for now auth is handled in validation
54
- end
55
- def reply
56
- self.class.new({:parent_id => self[:id],:author_id => $request[:user][:id],:recipients => author.name, :title => "re: #{title}"})
57
- end
58
- def reply_all
59
- foo=reply
60
- foo.recipients="#{author.name},#{recipients}".gsub(/\b(#{$request[:user][:name]})\b/,'').sub(',,',',')
61
- foo
62
- end
63
- def validate
64
- super
65
- validates_presence [:recipients]
66
- self.recipients.split(',').each do |recipient|
67
- if u=MR::User[:name => recipient]
68
- errors.add(:recipients, "You may only send PM's to Admins or Mods. #{recipient} is neither of those") unless (['Admin','Moderator'].include?(MR::User[:name => recipient].user_type) || [MR::Admin,MR::Moderator].include?($request[:user].class))
69
- else
70
- errors.add(:recipients, "Invalid user: #{recipient}")
71
- end
72
- end
73
- end
74
- end
75
- class Post < Message
76
- @actions_get=['reply']
77
- def current_user_role
78
- super || 'reader'
79
- end
80
- def authorize_rest_post(meth);true;end
81
- def reply
82
- self.class.new({:parent_id => self[:id],:author_id => $request[:user][:id], :title => "re: #{title}"})
83
- end
84
- end
85
- end
86
- end
87
- end
88
- end
@@ -1,51 +0,0 @@
1
- require 'digest/sha1'
2
- LOGIN_FORM= [:instance,{:url => 'login',:description => 'Existing users please log in here:',:new_rec => true,:schema => [[:text,'name',RESTRICT_REQ],[:password,'password',RESTRICT_REQ]]}]
3
- module Marley
4
- module Joints
5
- class BasicUser < Joint
6
- module Resources
7
- class User < Sequel::Model
8
- set_dataset :users
9
- plugin :single_table_inheritance, :user_type, :model_map => lambda{|v| MR.const_get(v.to_sym)}, :key_map => lambda{|klass|klass.name.sub(/.*::/,'')}
10
- attr_reader :menus
11
- attr_accessor :old_password,:password, :confirm_password
12
- def self.requires_user?
13
- ! ($request[:verb]=='rest_post' || ($request[:verb]=='rest_get' && $request[:path][1]=='new'))
14
- end
15
- def self.rest_section
16
- ReggaeSection.new( {:title => 'User Info', :name => self.to_s.sub(/.*::/,'').underscore, :navigation => []}) if $request[:user].class == self
17
- end
18
- def write_cols;[:name,:email,:password,:confirm_password,:old_password];end
19
- def rest_schema
20
- schema=super.delete_if {|c| [:pw_hash,:description,:active].include?(c[NAME_INDEX])}
21
- schema.push([:password,:old_password,0]) unless new?
22
- schema.push([:password,:password ,new? ? RESTRICT_REQ : 0],[:password,:confirm_password,new? ? RESTRICT_REQ : 0])
23
- schema
24
- end
25
- def self.authenticate(credentials)
26
- u=find(:name => credentials[0], :pw_hash => Digest::SHA1.hexdigest(credentials[1]))
27
- u.respond_to?(:user_type) ? Marley::Resources.const_get(u[:user_type].to_sym)[u[:id]] : u
28
- end
29
- def validate
30
- super
31
- validates_presence [:name]
32
- validates_unique [:name]
33
- if self.new? || self.old_password.to_s + self.password.to_s + self.confirm_password.to_s > ''
34
- errors[:password]=['Password must contain at least 8 characters'] if self.password.to_s.length < 8
35
- errors[:confirm_password]=['Passwords do not match'] unless self.password==self.confirm_password
36
- errors[:old_password]=['Old Password Incorrect'] if !self.new? && Digest::SHA1.hexdigest(self.old_password.to_s) != self.pw_hash
37
- end
38
- end
39
- def before_save
40
- if self.new? || self.old_password.to_s + self.password.to_s + self.confirm_password.to_s > ''
41
- self.pw_hash=Digest::SHA1.hexdigest(self.password)
42
- end
43
- end
44
- def create_msg
45
- [[:msg,{:title => 'Success!'},"Your login, '#{self.name}', has been sucessfully created. You can now log in."]]
46
- end
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,122 +0,0 @@
1
- Sequel::Plugins::ValidationHelpers::DEFAULT_OPTIONS.merge!(:presence => {:message => 'is required'})
2
- Sequel::Model.plugin :timestamps, :create => :date_created, :update => :date_updated
3
-
4
- Marley.joint 'basic_user',{:resources => []}
5
- Marley.joint 'tagging'
6
- Marley.joint 'basic_messaging',{:resources => ['Message']}
7
- module Marley
8
- module Joints
9
- class TaggedMessaging < Joint
10
- def smoke
11
- super
12
- MR::Tag.tagging_for('PrivateMessage', 'User') if MR.constants.include?('PrivateMessage')
13
- if MR.constants.include?('Post')
14
- MR::Tag.tagging_for('Post', 'User')
15
- MR::Tag.tagging_for('Post')
16
- end
17
- end
18
- module MessagePlugin
19
- module ClassMethods
20
- def list(params={})
21
- if associations.include?(:public_tags)
22
- specified_tags=params.delete(:tags)
23
- specified_user_tags=params.delete(:user_tags)
24
- else
25
- specified_user_tags=params.delete(:tags)
26
- end
27
- tag_ids=MR::PublicTag.filter(:tag => specified_tags.split(/\s*,\s*/)).select(:id) if specified_tags
28
- user_tag_ids=$request[:user].user_tags_dataset.filter(:tag => specified_user_tags.split(/\s*,\s*/)).select(:id) if specified_user_tags
29
- items=filter(params)
30
- #would love to make the following line more generic...
31
- items=filter("author_id=#{$request[:user][:id]} or recipients like('%#{$request[:user][:name]}%')".lit) if new.rest_cols.include?(:recipients)
32
- items=items.join(:messages_tags,:message_id => :id).filter(:tag_id => tag_ids) if specified_tags
33
- items=items.join(:messages_tags,:message_id => :id).filter(:tag_id => user_tag_ids) if specified_user_tags
34
- items.group(:thread_id).order(:max.sql_function(:date_created).desc,:max.sql_function(:date_updated).desc).map{|t|self[:parent_id => nil, :thread_id => t[:thread_id]].thread} rescue []
35
- end
36
- end
37
- module InstanceMethods
38
- def rest_associations
39
- if ! new?
40
- [ respond_to?(:public_tags) ? :public_tags : nil, respond_to?(:user_tags) ? user_tags_dataset.current_user_dataset : nil].compact
41
- end
42
- end
43
- def new_tags
44
- [:instance,{:name => 'tags',:url => "#{url}tags", :new_rec => true, :schema => [['number','message_id',RESTRICT_HIDE,id],['text','tags',RESTRICT_REQ]]}]
45
- end
46
- def new_user_tags
47
- [:instance,{:name => 'user_tags',:url => "#{url}user_tags", :new_rec => true, :schema => [['number','user_tags[message_id]',RESTRICT_HIDE,id],['text','user_tags[tags]',RESTRICT_REQ]]}]
48
- end
49
- def add_tags(tags,user=nil)
50
- if respond_to?(:public_tags)
51
- tags.to_s.split(',').each {|tag| add_public_tag(MR::PublicTag.find_or_create(:tag => tag))}
52
- else
53
- add_user_tags(tags,user)
54
- end
55
- end
56
- def add_user_tags(tags,user=nil) #does not conflict with add_user_tag
57
- user||=$request[:user][:id]
58
- if user.class==String
59
- user.split(',').each {|u| add_user_tags(tags,MR::User[:name => u][:id])}
60
- elsif user.class==Array
61
- user.each {|u| add_user_tags(tags,u)}
62
- elsif user.class==Fixnum
63
- tags.to_s.split(',').each {|tag| add_user_tag(MR::UserTag.find_or_create(:user_id => user, :tag => tag))}
64
- end
65
- end
66
- end
67
- end
68
- module Resources
69
- class User < MJ::BasicUser::Resources::User
70
- end
71
- class Admin < User
72
- def self.requires_user?;true;end
73
- end
74
- class Moderator < User
75
- def self.requires_user?;true;end
76
- end
77
- class PrivateMessage < MJ::BasicMessaging::Resources::PrivateMessage
78
- attr_accessor :tags
79
- @actions_get= superclass.actions_get << 'new_tags'
80
- @section_title='Private Messages'
81
- @section_name='pms'
82
- def self.section_navigation
83
- $request[:user].user_tags.map{|t| [:link,{:url => "/private_message?private_message[tag]=#{t.tag}",:title => t.tag.humanize}]}.unshift(PrivateMessage.reggae_link('new'))
84
- end
85
- def rest_schema
86
- super << [:text, :tags, 0,tags]
87
- end
88
- def reply
89
- r=super
90
- r.tags=(user_tags_dataset.current_user_dataset.map{|t|t.tag} - RESERVED_PM_TAGS).join(',')
91
- r
92
- end
93
- def after_create
94
- add_user_tags("inbox,#{tags}",recipients)
95
- add_user_tags("sent,#{recipients.match(/\b#{author.name}\b/) ? '' : tags}",author_id)
96
- end
97
- end
98
- class Post < MJ::BasicMessaging::Resources::Post
99
- attr_accessor :tags,:my_tags
100
- @section_title='Public Posts'
101
- @section_name='posts'
102
- def self.section_navigation
103
- 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'))
104
- end
105
- @actions_get=(superclass.actions_get << 'new_user_tags') << 'new_tags'
106
- def rest_schema
107
- (super << [:text, :tags, 0,tags] ) << [:text, :my_tags, 0,my_tags]
108
- end
109
- def reply
110
- r=super
111
- r.tags=self.tags
112
- r
113
- end
114
- def after_create
115
- add_tags(tags) if tags
116
- add_user_tags(my_tags) if my_tags
117
- end
118
- end
119
- end
120
- end
121
- end
122
- end
@@ -1,56 +0,0 @@
1
- module Marley
2
- module Joints
3
- class Tagging < Joint
4
- module Resources
5
- class Tag < Sequel::Model
6
- def self.tagging_for(klass, user_class=nil,join_table=nil)
7
- current_user_tags=Module.new do
8
- def current_user_dataset
9
- filter(:tags__user_id => $request[:user][:id])
10
- end
11
- end
12
- tagged_class=Marley::Resources.const_get(klass.to_sym)
13
- join_table||=:"#{tagged_class.table_name}_tags"
14
- klass_key=:"#{tagged_class.table_name.to_s.singularize}_id"
15
- tag_key=:tag_id
16
- if user_class
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
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]
19
- Marley::Resources.const_get(user_class).one_to_many :user_tags, :class => 'Marley::Resources::UserTag'
20
- UserTag.many_to_one user_class.underscore.to_sym,:class => "Marley::Resources::#{user_class}"
21
- else
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
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
24
- end
25
- end
26
- def validate
27
- validates_presence :tag
28
- validates_unique [:tag,:user_id]
29
- end
30
- def before_save
31
- super
32
- self.tag.downcase!
33
- self.tag.strip!
34
- end
35
- def after_save
36
- super
37
- assoc=methods.grep(/_id=$/) - ['user_id=']
38
- assoc.each do |a|
39
- if c=self.send(a.sub(/=$/,''))
40
- send "add_#{a.sub(/_id=/,'')}", Marley::Resources.const_get(a.sub(/_id=/,'').camelize.to_sym)[c]
41
- end
42
- end
43
- end
44
- end
45
- class PublicTag < Tag
46
- set_dataset DB[:tags].filter(:user_id => nil)
47
- @actions_delete='remove_parent'
48
- end
49
- class UserTag < Tag
50
- set_dataset DB[:tags].filter(~{:user_id => nil})
51
- @actions_delete='remove_parent'
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,53 +0,0 @@
1
-
2
- module Sequel::Plugins::RestAuthorization
3
- module ClassMethods
4
- attr_accessor :owner_col, :allowed_get_methods
5
- def inherited(c)
6
- super
7
- c.owner_col=@owner_col
8
- c.allowed_get_methods=@allowed_get_methods
9
- end
10
- def requires_user?(verb=nil,meth=nil);true;end
11
- def authorize(meth)
12
- if respond_to?(auth_type="authorize_#{$request[:verb]}")
13
- send(auth_type,meth)
14
- else
15
- case $request[:verb]
16
- when 'rest_put','rest_delete'
17
- false
18
- when 'rest_post'
19
- new($request[:post_params][resource_name.to_sym]||{}).current_user_role=='owner' && meth.nil?
20
- when 'rest_get'
21
- methods=@allowed_get_methods || ['section','list','new']
22
- (methods.class==Hash ? methods[$request[:user].class] : methods).include?(meth)
23
- end
24
- end
25
- end
26
- end
27
- module InstanceMethods
28
- def after_initialize
29
- super
30
- send("#{self.class.owner_col}=",$request[:user][:id]) if $request && self.class.owner_col && new?
31
- end
32
- def requires_user?(verb=nil,meth=nil);true;end
33
- def authorize(meth)
34
- if respond_to?(auth_type="authorize_#{$request[:verb]}")
35
- send(auth_type,meth)
36
- else
37
- current_user_role=='owner'
38
- end
39
- end
40
- def current_user_role
41
- "owner" if owners.include?($request[:user])
42
- end
43
- def owners
44
- if self.class.to_s.match(/User$/)||self.class.superclass.to_s.match(/User$/)
45
- [self]
46
- elsif @owner_col
47
- [User[send(@owner_col)]]
48
- else
49
- self.class.association_reflections.select {|k,v| v[:type]==:many_to_one}.map {|a| self.send(a[0]) && self.send(a[0]).owners}.flatten.compact
50
- end
51
- end
52
- end
53
- end
@@ -1,87 +0,0 @@
1
-
2
- module Sequel
3
- module Plugins::RestConvenience
4
- module ClassMethods
5
- include Marley::RestActions
6
- def controller
7
- Marley::ModelController.new(self)
8
- end
9
- def resource_name
10
- self.name.sub(/.*::/,'').underscore
11
- end
12
- def reggae_link(action=nil)
13
- [:link,{:url => "/#{self.resource_name}/#{action}",:title => "#{action.humanize} #{self.resource_name.humanize}".strip}]
14
- end
15
- def list(params=nil)
16
- user=$request[:user]
17
- if user.respond_to?(otm=self.resource_name.pluralize)
18
- if user.method(otm).arity==0
19
- if (relationship=user.send(otm)).respond_to?(:filter)
20
- relationship.filter($request[:get_params][resource_name.to_sym] || {}).all
21
- else
22
- user.send(otm)
23
- end
24
- else
25
- user.send(otm,$request[:get_params][resource_name.to_sym])
26
- end
27
- else
28
- raise Marley::AuthorizationError
29
- end
30
- end
31
- def autocomplete(input_content)
32
- filter(:name.like("#{input_content.strip}%")).map {|rec| [rec.id, rec.name]}
33
- end
34
- end
35
- module InstanceMethods
36
- include Marley::RestActions
37
- def edit; self; end
38
- def rest_cols
39
- columns.reject do |c|
40
- if new?
41
- c.to_s.match(/(^id$)|(_type$)|(date_(created|updated))/)
42
- else
43
- c.to_s.match(/_type$/)
44
- end
45
- end
46
- end
47
- def hidden_cols
48
- columns.select {|c| c.to_s.match(/(_id$)/)}
49
- end
50
- def write_cols
51
- rest_cols.reject {|c| c.to_s.match(/(^id$)|(date_(created|updated))/)}
52
- end
53
- def required_cols;[];end
54
- def rest_schema
55
- rest_cols.map do |col_name|
56
- db_spec=db_schema.to_hash[col_name]
57
- col_type=db_spec ? db_spec[:db_type].downcase : col_name
58
- restrictions=0
59
- restrictions|=RESTRICT_HIDE if hidden_cols.include?(col_name)
60
- restrictions|=RESTRICT_RO unless write_cols.include?(col_name)
61
- restrictions|=RESTRICT_REQ if required_cols.include?(col_name) || (db_spec && !db_spec[:allow_null])
62
- [col_type, col_name, restrictions,send(col_name)]
63
- end
64
- end
65
- def to_s
66
- respond_to?('name') ? name : id.to_s
67
- end
68
- def to_a
69
- a=Marley::ReggaeInstance.new( {:name => self.class.resource_name,:url => url ,:new_rec => self.new?,:schema => rest_schema,:actions => self.class.rest_actions})
70
- a.contents=self.class.associations.map do |assoc|
71
- assoc=send("#{assoc}_dataset")
72
- (assoc.respond_to?(:current_user_dataset) ? assoc.current_user_dataset : assoc).map{|instance| instance.to_a} if assoc.respond_to?(:rest_actions)
73
- end.compact unless new?
74
- a
75
- end
76
- def to_json(*args)
77
- to_a.to_json
78
- end
79
- def url(action=nil)
80
- "/#{self.class.resource_name}/#{self[:id]}/#{action}".sub('//','/')
81
- end
82
- def reggae_link(action=nil)
83
- [:link,{:url => url,:title => "#{action.humanize}"}]
84
- end
85
- end
86
- end
87
- end