marley 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@ module Marley
4
4
  def initialize(model)
5
5
  @model=model
6
6
  if $request[:path][1].to_s.match(/^\d+$/) #references a specific instance by ID
7
- @instance=@model[$request[:path][1].to_i]
7
+ @instance=@model.list_dataset(:"#{@model.table_name}__id" => $request[:path][1].to_i).all[0]
8
8
  raise RoutingError unless @instance
9
9
  @method_name=$request[:path][2].sub(/[\?\&\+]$/,'') rescue nil #ditch trailing characters, if any
10
10
  if @method_name
@@ -1,38 +1,48 @@
1
-
2
1
  module Marley
3
2
  module Plugins
4
3
  class MessageThreading < Plugin
4
+ def apply(*klasses)
5
+ super
6
+ klasses.flatten.each do |klass|
7
+ Marley.plugin('orm_materialized_path').apply(klass)
8
+ end
9
+ end
5
10
  module ClassMethods
6
11
  def topics(params=nil)
7
12
  filters=[]
8
13
  if params && params[:tags]
9
14
  filters << {:id => MR::Tag.join(:messages_tags, :tag_id => :id).select(:message_id).filter(:tag => params[:tags])}
10
15
  end
11
- filters.inject(self.dataset.filter(:parent_id => nil)) {|ds,f| ds.filter(f)}
16
+ filters.inject(self.roots) {|ds,f| ds.filter(f)}
17
+ end
18
+ def list(params={})
19
+ reggae_instance_list(params)
12
20
  end
13
- def list(params=nil)
14
- (params.is_a?(Sequel::Dataset) ? params : topics(params)).eager(associations).all.map{|t| t.thread}
21
+ def reggae_instance_list(params={})
22
+ t=topics(params).all
23
+ if t.length==0
24
+ Marley::ReggaeMsg.new(:title => 'Nothing Found')
25
+ else
26
+ Marley::ReggaeInstanceList.new(
27
+ :name => resource_name,
28
+ :schema => t[0].reggae_schema(true) << [:resource,resource_name,RESTRICT_RO],
29
+ :items => t.map{|t| t.thread_vals}
30
+ )
31
+ end
15
32
  end
16
33
  end
17
34
  module InstanceMethods
35
+ def thread_vals;values_tree;end
36
+ def thread; tree;end
18
37
  def write_cols
19
- super.push(:topic_id, :parent_id)
20
- end
21
- def children
22
- self.class.filter(:parent_id => id).eager(associations)
23
- end
24
- def thread
25
- return reggae_instance if children.all.length==0
26
- foo=reggae_instance
27
- foo[2] = children.all.map{|m| m.thread}
28
- foo
38
+ new? ? super.push(:topic_id, :path) : super
29
39
  end
30
40
  def before_save
31
41
  super
32
42
  self.topic_id||=self.class.max(:topic_id).to_i+1
33
43
  end
34
44
  def reply
35
- self.class.new(self.values.dup.delete_if{|k,v| k==:id}.merge({:parent_id => self[:id],:title => "re: #{title}"}))
45
+ new_child(:title => "re: #{title}")
36
46
  end
37
47
  end
38
48
  end
@@ -43,11 +53,11 @@ module Marley
43
53
  self.reggae_link(:new, 'New Post'),
44
54
  self.reggae_link(:list, 'All Posts'),
45
55
  self.reggae_link(:recent_topics, 'Recent Topics'),
46
- Marley::ReggaeSection.new({:title => 'Topics Tagged With:', :navigation => MR::Tag.filter(:id => topics.join(:messages_tags).where(:messages__id => :message_id).select(:tag_id)).map{|t| reggae_link('list',t.tag,"#{resource_name}[tags]=#{t.tag}")}})
56
+ Marley::ReggaeSection.new({:title => 'Public Tags', :navigation => MR::PublicTag.filter(:id => topics.all.map{|t|}).map{|t| reggae_link('list',t.tag,"#{resource_name}[_public_tags]=#{t.tag}")}})
47
57
  ]
48
58
  end
49
59
  def recent_topics
50
- list(:date_created > Date.today - 2)
60
+ list(lambda {date_created > Date.today - 2})
51
61
  end
52
62
  end
53
63
  end
@@ -35,7 +35,7 @@ module Marley
35
35
  [:recipients] + super
36
36
  end
37
37
  Marley::Utils.many_to_many_join(self, MR::User)
38
- def self.list_dataset
38
+ def self.list_dataset(params={})
39
39
  super.filter(:messages__id => DB[:messages_users].filter(:user_id => current_user[:id]).select(:message_id))
40
40
  end
41
41
  def current_user_role
@@ -5,7 +5,9 @@ module Marley
5
5
  def apply(*klasses)
6
6
  klasses.each do |klass|
7
7
  klass=MR.const_get(klass) if klass.is_a?(String)
8
+
8
9
  klass.derived_after_cols![:new?][:all] << @tag_col_name.to_sym
10
+ klass.extend @class_methods_mod
9
11
  @instance_methods_mod.send(:append_features,klass)
10
12
  Marley::Utils.many_to_many_join(klass, @tag_class)
11
13
  end
@@ -16,33 +18,29 @@ module Marley
16
18
  tag_col_name=@tag_col_name="_#{@tag_type}_tags"
17
19
  tag_class=@tag_class=MR.const_get(@tag_col_name.sub(/^_/,'').singularize.camelcase)
18
20
  tags_ds_name=@tags_ds_name="#{tag_col_name.sub(/^_/,'')}_dataset"
21
+ tags_meth=tag_class.resource_name.pluralize.to_sym
22
+ @class_methods_mod=Module.new do |m|
23
+ define_method(:list_dataset) {|*args|
24
+ super.eager_graph({tags_meth => proc{|ds| ds.filter(:tags__user_id => tag_class.associations.include?(:user) ? current_user[:id] : nil)}})
25
+ }
26
+ end
19
27
  @instance_methods_mod=Module.new do |m|
20
- attr_accessor tag_col_name
28
+ attr_writer tag_col_name
21
29
  define_method(:write_cols) {
22
30
  super << tag_col_name.to_sym
23
31
  }
24
-
25
- #list dataset should take care of most of this
26
-
27
- define_method("#{tag_col_name}_ds".to_sym) { #e.g. _private_tags_ds
28
- send(tags_ds_name).filter({:tags__user_id => (tag_class.associations.include?(:user) ? self.class.current_user[:id] : nil)})
29
- }
30
32
  define_method(tag_col_name.to_sym) { #e.g. _private_tags
31
- send("#{tag_col_name}_ds").map {|t| t.tag}.join(', ') unless new?
32
- }
33
- define_method("add#{tag_col_name}".to_sym) {|tags| #e.g. add_private_tags
34
- vals_hash={:user_id => (tag_class.associations.include?(:user) ? self.class.current_user[:id] : nil)}
35
- tags.to_s.split(',').each {|tag| self.send("add#{tag_col_name.singularize}",tag_class.find_or_create(vals_hash.update(:tag => tag))) }
33
+ send(tags_meth).map {|t| t.tag}.join(', ') unless new?
36
34
  }
37
35
  define_method("replace#{tag_col_name}".to_sym) { #e.g. replace_private_tags
38
- send("#{tag_col_name}_ds").each {|tag| send("remove#{tag_col_name}".singularize,tag)}
36
+ send(tags_meth).each {|tag| send("remove#{tag_col_name}".singularize,tag)}
39
37
  send("add#{tag_col_name}",instance_variable_get("@#{tag_col_name}"))
40
38
  }
41
39
  define_method(:after_save) {
42
40
  super
43
- methods.select {|m| m.match(/^replace_.+_tags/)}.each do |replace_method|
44
- send(replace_method)
45
- end
41
+ send("#{tags_meth}_dataset").filter({:tags__user_id => (tag_class.associations.include?(:user) ? self.class.current_user[:id] : nil)}).each {|tag| send("remove#{tag_col_name}".singularize,tag)}
42
+ vals_hash={:user_id => (tag_class.associations.include?(:user) ? self.class.current_user[:id] : nil)}
43
+ instance_variable_get("@#{tag_col_name}").to_s.split(/\s*,\s*/).each {|tag| self.send("add#{tag_col_name.singularize}",tag_class.find_or_create(vals_hash.update(:tag => tag))) }
46
44
  }
47
45
  end
48
46
  end
@@ -53,7 +51,7 @@ module Marley
53
51
  module Resources
54
52
  class Tag < Sequel::Model
55
53
  sti
56
- def self.list_dataset
54
+ def self.list_dataset(params={})
57
55
  dataset.order(:tag)
58
56
  end
59
57
  def validate
@@ -74,7 +72,7 @@ module Marley
74
72
  end
75
73
  class PrivateTag < Tag
76
74
  MR::User.join_to(self) if MR::User
77
- def self.list_dataset
75
+ def self.list_dataset(params={})
78
76
  current_user_ds.order(:tag)
79
77
  end
80
78
  end
@@ -0,0 +1,49 @@
1
+ module Marley
2
+ module Plugins
3
+ class OrmMaterializedPath < Plugin
4
+ @default_opts={:path_col => :path, :path_separator => '-'}
5
+ def apply(klasses)
6
+ super
7
+ end
8
+ def initialize(opts={})
9
+ super
10
+ [ClassMethods,InstanceMethods].each do |mod|
11
+ mod.const_set(:PATH_COL,@opts[:path_col])
12
+ mod.const_set(:SEP,@opts[:path_separator])
13
+ end
14
+ end
15
+ module ClassMethods
16
+ def roots(params={})
17
+ list_dataset.filter({PATH_COL => nil}.update(params))
18
+ end
19
+ def path_col_num
20
+ columns.index(PATH_COL)
21
+ end
22
+ end
23
+ module InstanceMethods
24
+ def tree_ds; self.class.list_dataset.filter(PATH_COL.like("#{children_path}%")); end
25
+ def _path;send(PATH_COL);end
26
+ def path_arr; _path.to_s.split(SEP).map &:to_i; end
27
+ def root_id; path_arr[0]; end
28
+ def parent_id; path_arr[-1]; end
29
+ def children_path;("#{_path}#{id}#{SEP}");end
30
+ def children_path_arr; children_path.split(SEP).map &:to_i; end
31
+ def new_child(vals={}); self.class.new({PATH_COL => children_path}.update(vals)); end
32
+ def depth; path_arr.length; end
33
+
34
+ def tree
35
+ res=block_given? ? (yield self) : [self,[]]
36
+ tree_ds.all.sort {|x,y| x.children_path_arr <=> y.children_path_arr}.each do |node|
37
+ node.path_arr.inject(res) {|arr,i| arr[-1]} << (block_given? ? (yield node) : [node,[]])
38
+ end
39
+ res
40
+ end
41
+ def values_tree
42
+ tree do |n|
43
+ foo=n.rest_cols.map{|c| n.send(c)} << []
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -9,13 +9,14 @@ module Marley
9
9
  @default_opts={
10
10
  :required_plugins => [:rest_convenience],
11
11
  :class_attrs =>[ [:model_actions,{:get => [:new, :list]}] ],
12
- :lazy_class_attrs => [ :new?,[:instance_actions,{:all => nil}],
13
- [:derived_before_cols,{:all => []}],
14
- [:derived_after_cols,{:all => []}],
15
- [:reject_cols,{true => [/^id$/,/_type$/,/date_(created|updated)/], false => [/_type$/]}],
16
- [:ro_cols,{true => [/^id$/,/_id$/], false => [/^id$/,/_id$/,/date_(created|updated)/]}],
17
- [:hidden_cols,{:all => [/_id$/]}],
18
- [:required_cols,{:all => []}] ]
12
+ :lazy_class_attrs => [ :new?,
13
+ [:instance_actions,{:all => nil}],
14
+ [:derived_before_cols,{:all => []}],
15
+ [:derived_after_cols,{:all => []}],
16
+ [:reject_cols,{true => [/^id$/,/_type$/,/date_(created|updated)/], false => [/_type$/]}],
17
+ [:ro_cols,{true => [/^id$/,/_id$/], false => [/^id$/,/_id$/,/date_(created|updated)/]}],
18
+ [:hidden_cols,{:all => [/_id$/]}],
19
+ [:required_cols,{:all => []}] ]
19
20
  }
20
21
  module ClassMethods
21
22
  def controller; Marley::ModelController.new(self); end
@@ -25,11 +26,24 @@ module Marley
25
26
 
26
27
  def foreign_key_name; :"#{(respond_to?(:table_name) ? table_name : resource_name).to_s.singularize}_id"; end
27
28
 
28
- def list_dataset
29
- dataset
29
+ def list_dataset(params={})
30
+ dataset.filter(params)
30
31
  end
31
32
  def list(params={})
32
- list_dataset.filter(params).all
33
+ list_dataset(params).all
34
+ end
35
+ def reggae_instance_list(params={})
36
+ items=list(params)
37
+ if items.length==0
38
+ Marley::ReggaeMessage.new(:title => 'Nothing Found')
39
+ else
40
+ cols=items[0].rest_cols
41
+ Marley::ReggaeInstanceList.new(
42
+ :name => resource_name,
43
+ :schema => items[0].reggae_schema(true),
44
+ :items => items.map{|i| cols.map{|c|i.send(c)}}
45
+ )
46
+ end
33
47
  end
34
48
  def sti
35
49
  plugin :single_table_inheritance, :"#{self.to_s.sub(/.*::/,'').underscore}_type", :model_map => lambda{|v| MR.const_get(v.to_sym)}, :key_map => lambda{|klass|klass.name.sub(/.*::/,'')}
@@ -50,17 +64,23 @@ module Marley
50
64
 
51
65
  def rest_associations;[];end
52
66
 
53
- def reggae_schema
67
+ def reggae_schema(list_schema=false)
54
68
  Marley::ReggaeSchema.new(
55
69
  rest_cols.map do |col_name|
56
70
  db_spec=db_schema.to_hash[col_name]
57
71
  col_type=db_spec ? db_spec[:db_type].downcase : "text"
58
72
  col_type=:password if col_name.to_s.match(/password/)
59
- restrictions=0
60
- restrictions|=RESTRICT_HIDE if hidden_cols.include?(col_name)
61
- restrictions|=RESTRICT_RO unless write_cols.include?(col_name)
62
- restrictions|=RESTRICT_REQ if required_cols.include?(col_name) || (db_spec && !db_spec[:allow_null])
63
- [col_type, col_name, restrictions,send(col_name)]
73
+ if list_schema
74
+ restrictions=RESTRICT_RO
75
+ restrictions|=RESTRICT_HIDE if hidden_cols.include?(col_name)
76
+ [col_type, col_name, restrictions]
77
+ else
78
+ restrictions=0
79
+ restrictions|=RESTRICT_HIDE if hidden_cols.include?(col_name)
80
+ restrictions|=RESTRICT_RO unless write_cols.include?(col_name)
81
+ restrictions|=RESTRICT_REQ if required_cols.include?(col_name) || (db_spec && !db_spec[:allow_null])
82
+ [col_type, col_name, restrictions,send(col_name)]
83
+ end
64
84
  end
65
85
  )
66
86
  end
@@ -107,8 +107,7 @@ module Marley
107
107
  end
108
108
  end
109
109
  class ReggaeInstanceList < ReggaeResource
110
- properties :name,:description,:actions,:items
111
- #not implemented yet
110
+ properties :name,:description,:actions,:group_actions,:items
112
111
  end
113
112
  class ReggaeMsg < ReggaeResource
114
113
  properties :title,:description
@@ -56,10 +56,10 @@ module Marley
56
56
  def self.sti(klass)
57
57
  klass.plugin :single_table_inheritance, :"#{klass.to_s.sub(/.*::/,'').underscore}_type", :model_map => lambda{|v| MR.const_get(v.to_sym)}, :key_map => lambda{|clss|clss.name.sub(/.*::/,'')}
58
58
  end
59
- def self.many_to_many_join(lclass, rclass)
59
+ def self.many_to_many_join(lclass, rclass,lopts={},ropts={})
60
60
  join_table=[lclass.table_name.to_s,rclass.table_name.to_s ].sort.join('_').to_sym
61
- lclass.many_to_many(rclass.resource_name.pluralize.to_sym,:join_table => join_table,:class =>rclass, :left_key => lclass.foreign_key_name, :right_key => rclass.foreign_key_name)
62
- rclass.many_to_many(lclass.resource_name.pluralize.to_sym,:join_table => join_table, :class =>lclass,:left_key => rclass.foreign_key_name, :right_key => lclass.foreign_key_name)
61
+ lclass.many_to_many(rclass.resource_name.pluralize.to_sym,{:join_table => join_table,:class =>rclass, :left_key => lclass.foreign_key_name, :right_key => rclass.foreign_key_name}).update(lopts)
62
+ rclass.many_to_many(lclass.resource_name.pluralize.to_sym,{:join_table => join_table, :class =>lclass,:left_key => rclass.foreign_key_name, :right_key => lclass.foreign_key_name}.update(ropts))
63
63
  end
64
64
  def self.hash_keys_to_syms(hsh)
65
65
  hsh.inject({}) {|h,(k,v)| h[k.to_sym]= v.class==Hash ? hash_keys_to_syms(v) : v;h }
@@ -14,7 +14,7 @@ end
14
14
  DB.create_table :messages do
15
15
  primary_key :id
16
16
  integer :topic_id, :index => true
17
- integer :parent_id, :index => true
17
+ text :path, :index => true
18
18
  integer :user_id, :index => true
19
19
  datetime :date_created, :index => true
20
20
  text :message_type, :index => true
@@ -31,6 +31,7 @@ end
31
31
  DB.create_table :tags do
32
32
  primary_key :id
33
33
  integer :user_id,:index => true
34
+ text :tag_type, :index => true
34
35
  text :tag,:index => true
35
36
  end
36
37
  DB.create_table :messages_tags do
@@ -27,7 +27,7 @@ FactoryGirl.define do
27
27
  _public_tags ''
28
28
  _private_tags ''
29
29
  end
30
- factory :private_message,:class => MR::PublicMessage do |n|
30
+ factory :private_message,:class => MR::PrivateMessage do |n|
31
31
  user
32
32
  recipients ''
33
33
  title
@@ -46,8 +46,15 @@ USERS.times do
46
46
  FactoryGirl.create(:user) do |u|
47
47
  $request={:user => u}
48
48
  TOPICS.times do
49
- FactoryGirl.create(:post,:user_id => u[:id])
49
+ FactoryGirl.create(:post,:user_id => u[:id],:_public_tags => (1 .. TAGS).to_a.map{|i| "tag#{i}"}.join(','))
50
50
  end
51
51
  end
52
52
  end
53
+ REPLIES.each do |r|
54
+ MR::PublicMessage.all.each do |m|
55
+ rep=m.reply
56
+ rep.user_id=m[:id].modulo USERS
57
+ rep.save
58
+ end
59
+ end
53
60
 
@@ -0,0 +1,21 @@
1
+
2
+ require 'marley'
3
+ require 'marley/test_helpers'
4
+
5
+ DB=Sequel.sqlite('')
6
+ DB.create_table :trees do
7
+ primary_key :id
8
+ text :name, :index => true
9
+ text :path, :index => true
10
+ end
11
+
12
+ Marley.plugin('orm_rest_convenience').apply(Sequel::Model)
13
+ Marley.config {}
14
+ module Marley
15
+ module Resources
16
+ class Tree < Sequel::Model
17
+ Marley.plugin('orm_materialized_path').apply(self)
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,48 @@
1
+
2
+
3
+ examples:
4
+
5
+ >> MR::Tree.new(:name => 'asdf').save.reggae_instance
6
+ => [:instance, {:schema=> [[:integer, :id, 2, 1], [:text, :name, 0, "asdf"], [:text, :path, 0, nil]], :url=>"/tree/1", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
7
+ >> MR::Tree[1].new_child.reggae_instance
8
+ => [:instance, {:schema=>[[:text, :name, 0, nil], [:text, :path, 0, "1-"]], :url=>"/tree/", :new_rec=>true, :name=>"tree", :actions=>nil}, nil]
9
+ >> MR::Tree[1].new_child.save.reggae_instance
10
+ => [:instance, {:schema=> [[:integer, :id, 2, 2], [:text, :name, 0, nil], [:text, :path, 0, "1-"]], :url=>"/tree/2", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
11
+ >> MR::Tree[1].new_child.save.reggae_instance
12
+ => [:instance, {:schema=> [[:integer, :id, 2, 3], [:text, :name, 0, nil], [:text, :path, 0, "1-"]], :url=>"/tree/3", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
13
+ >> MR::Tree[1].new_child.save.reggae_instance
14
+ => [:instance, {:schema=> [[:integer, :id, 2, 4], [:text, :name, 0, nil], [:text, :path, 0, "1-"]], :url=>"/tree/4", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
15
+ >> MR::Tree[2].new_child.save.reggae_instance
16
+ => [:instance, {:schema=> [[:integer, :id, 2, 5], [:text, :name, 0, nil], [:text, :path, 0, "1-2-"]], :url=>"/tree/5", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
17
+ >> MR::Tree[5].new_child.save.reggae_instance
18
+ => [:instance, {:schema=> [[:integer, :id, 2, 6], [:text, :name, 0, nil], [:text, :path, 0, "1-2-5-"]], :url=>"/tree/6", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
19
+ >> MR::Tree[3].new_child.save.reggae_instance
20
+ => [:instance, {:schema=> [[:integer, :id, 2, 7], [:text, :name, 0, nil], [:text, :path, 0, "1-3-"]], :url=>"/tree/7", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
21
+
22
+ >> MR::Tree[3].new_child.save.reggae_instance
23
+ => [:instance, {:schema=> [[:integer, :id, 2, 8], [:text, :name, 0, nil], [:text, :path, 0, "1-3-"]], :url=>"/tree/8", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
24
+ >> MR::Tree[3].new_child.save.reggae_instance
25
+ => [:instance, {:schema=> [[:integer, :id, 2, 9], [:text, :name, 0, nil], [:text, :path, 0, "1-3-"]], :url=>"/tree/9", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
26
+ >> MR::Tree[3].new_child.save.reggae_instance
27
+ => [:instance, {:schema=> [[:integer, :id, 2, 10], [:text, :name, 0, nil], [:text, :path, 0, "1-3-"]], :url=>"/tree/10", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
28
+
29
+ >> MR::Tree[1].new_child.save.reggae_instance
30
+ => [:instance, {:schema=> [[:integer, :id, 2, 11], [:text, :name, 0, nil], [:text, :path, 0, "1-"]], :url=>"/tree/11", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
31
+ >> MR::Tree[1].new_child.save.reggae_instance
32
+ => [:instance, {:schema=> [[:integer, :id, 2, 12], [:text, :name, 0, nil], [:text, :path, 0, "1-"]], :url=>"/tree/12", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
33
+ >> MR::Tree[2].new_child.save.reggae_instance
34
+ => [:instance, {:schema=> [[:integer, :id, 2, 13], [:text, :name, 0, nil], [:text, :path, 0, "1-2-"]], :url=>"/tree/13", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
35
+ >> MR::Tree[5].new_child.save.reggae_instance
36
+ => [:instance, {:schema=> [[:integer, :id, 2, 14], [:text, :name, 0, nil], [:text, :path, 0, "1-2-5-"]], :url=>"/tree/14", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
37
+ >> MR::Tree[3].new_child.save.reggae_instance
38
+ => [:instance, {:schema=> [[:integer, :id, 2, 15], [:text, :name, 0, nil], [:text, :path, 0, "1-3-"]], :url=>"/tree/15", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
39
+
40
+ >> MR::Tree[7].new_child.save.reggae_instance
41
+ => [:instance, {:schema=> [[:integer, :id, 2, 16], [:text, :name, 0, nil], [:text, :path, 0, "1-3-7-"]], :url=>"/tree/16", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
42
+ >> MR::Tree[13].new_child.save.reggae_instance
43
+ => [:instance, {:schema=> [[:integer, :id, 2, 17], [:text, :name, 0, nil], [:text, :path, 0, "1-2-13-"]], :url=>"/tree/17", :new_rec=>false, :name=>"tree", :actions=>nil}, []]
44
+
45
+ >> MR::Tree[1].values_tree
46
+ => [1, "asdf", nil, [[2, nil, "1-", [], [5, nil, "1-2-", [], [6, nil, "1-2-5-", []], [14, nil, "1-2-5-", []]], [13, nil, "1-2-", [], [17, nil, "1-2-13-", []]]], [3, nil, "1-", [], [7, nil, "1-3-", [], [16, nil, "1-3-7-", []]], [8, nil, "1-3-", []], [9, nil, "1-3-", []], [10, nil, "1-3-", []], [15, nil, "1-3-", []]], [4, nil, "1-", []], [11, nil, "1-", []], [12, nil, "1-", []]]]
47
+
48
+
@@ -29,7 +29,9 @@ example: without the plugin, then with the plugin
29
29
 
30
30
  == Included Plugins
31
31
 
32
- Marley comes with 1 external plugin (there are others in the included Joints, described later):
32
+ Marley comes with 2 plugins (there are others in the included Joints, described later):
33
33
 
34
34
  :include: rdoc/orm_rest_convenience_plugin.rdoc
35
35
 
36
+ :include: rdoc/orm_materialized_path_plugin.rdoc
37
+
@@ -31,7 +31,6 @@ examples: announcements with private and public tags
31
31
  => [[:instance, {:url=>"/announcement/1", :new_rec=>false, :actions=>{:delete=>"/announcement/1"}, :schema=>[[:integer, :id, 2, 1], [:integer, :user_id, 3, 1], [:text, :name, 4, "user1 ann1"], [:text, :message, 0, "user1ann1 msg"], [:text, :_private_tags, 0, "aaa, bbb"], [:text, :_public_tags, 0, "ppp"]], :name=>"announcement"}, []], [:instance, {:url=>"/announcement/2", :new_rec=>false, :actions=>nil, :schema=>[[:integer, :id, 2, 2], [:integer, :user_id, 3, 2], [:text, :name, 6, "user2 ann1"], [:text, :message, 2, "user2ann1 msg"], [:text, :_private_tags, 0, ""], [:text, :_public_tags, 0, "yyy, zzz"]], :name=>"announcement"}, []]]
32
32
  >> @client2.read
33
33
  => [[:instance, {:url=>"/announcement/1", :new_rec=>false, :actions=>nil, :schema=>[[:integer, :id, 2, 1], [:integer, :user_id, 3, 1], [:text, :name, 6, "user1 ann1"], [:text, :message, 2, "user1ann1 msg"], [:text, :_private_tags, 0, ""], [:text, :_public_tags, 0, "ppp"]], :name=>"announcement"}, []], [:instance, {:url=>"/announcement/2", :new_rec=>false, :actions=>{:delete=>"/announcement/2"}, :schema=>[[:integer, :id, 2, 2], [:integer, :user_id, 3, 2], [:text, :name, 4, "user2 ann1"], [:text, :message, 0, "user2ann1 msg"], [:text, :_private_tags, 0, "xxx"], [:text, :_public_tags, 0, "yyy, zzz"]], :name=>"announcement"}, []]]
34
-
35
34
  >> @ann1client1=@client1.read({},:instance_id => 1)
36
35
  => [:instance, {:url=>"/announcement/1", :new_rec=>false, :actions=>{:delete=>"/announcement/1"}, :schema=>[[:integer, :id, 2, 1], [:integer, :user_id, 3, 1], [:text, :name, 4, "user1 ann1"], [:text, :message, 0, "user1ann1 msg"], [:text, :_private_tags, 0, "aaa, bbb"], [:text, :_public_tags, 0, "ppp"]], :name=>"announcement"}, []]
37
36
  :_public_tags, 0, "ppp"]], :name=>"announcement"}, []]
@@ -30,9 +30,9 @@ examples:
30
30
  => [:instance, {:schema=>[[:integer, :id, 2, 1], [:integer, :user_id, 3, 1], [:text, :name, 4, "user1 secret1"], [:text, :message, 0, nil], [:text, :_private_tags, 0, "foo"]], :url=>"/secret/1", :new_rec=>false, :actions=>nil, :name=>"secret"}, []]
31
31
 
32
32
  >> DB[:tags].all
33
- => [{:tag=>"xxxxxx", :id=>1, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"sss", :id=>2, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"sss", :id=>3, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"zzz", :id=>4, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"aaa", :id=>5, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"foo", :id=>6, :tag_type=>"PrivateTag", :user_id=>1}]
33
+ => [{:tag=>"xxxxxx", :id=>1, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"sss", :id=>2, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"zzz", :id=>3, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"aaa", :id=>4, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"foo", :id=>5, :tag_type=>"PrivateTag", :user_id=>1}]
34
34
  >> DB[:messages_tags].all
35
- => [{:tag_id=>6, :message_id=>1, :id=>7}]
35
+ => [{:tag_id=>5, :message_id=>1, :id=>7}]
36
36
 
37
37
 
38
38
 
@@ -58,8 +58,8 @@ examples:
58
58
  => [:instance, {:schema=>[[:integer, :id, 2, 2], [:integer, :user_id, 3, 2], [:text, :name, 4, "user2 secret"], [:text, :message, 0, nil], [:text, :_private_tags, 0, "boo"]], :url=>"/secret/2", :new_rec=>false, :actions=>nil, :name=>"secret"}, []]
59
59
 
60
60
  >> DB[:tags].all
61
- => [{:tag=>"xxxxxx", :id=>1, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"sss", :id=>2, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"sss", :id=>3, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"zzz", :id=>4, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"aaa", :id=>5, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"foo", :id=>6, :tag_type=>"PrivateTag",:user_id=>1}, {:tag=>"foo", :id=>7, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"bar", :id=>8, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"bar", :id=>9, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"baz", :id=>10, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"bat", :id=>11, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"boo", :id=>12, :tag_type=>"PrivateTag", :user_id=>2}]
61
+ => [{:tag=>"xxxxxx", :id=>1, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"sss", :id=>2, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"zzz", :id=>3, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"aaa", :id=>4, :tag_type=>"PrivateTag", :user_id=>1}, {:tag=>"foo", :id=>5, :tag_type=>"PrivateTag",:user_id=>1}, {:tag=>"foo", :id=>6, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"bar", :id=>7, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"baz", :id=>8, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"bat", :id=>9, :tag_type=>"PrivateTag", :user_id=>2}, {:tag=>"boo", :id=>10, :tag_type=>"PrivateTag", :user_id=>2}]
62
62
  >> DB[:messages_tags].all
63
- => [{:tag_id=>6, :message_id=>1, :id=>7}, {:tag_id=>12, :message_id=>2, :id=>14}]
63
+ => [{:tag_id=>5, :message_id=>1, :id=>7}, {:tag_id=>10, :message_id=>2, :id=>14}]
64
64
 
65
65
 
@@ -40,7 +40,7 @@ module Marley
40
40
  end
41
41
  class Secret < Message
42
42
  User.join_to(self)
43
- def self.list_dataset
43
+ def self.list_dataset(params={})
44
44
  current_user_ds
45
45
  end
46
46
  end
@@ -63,8 +63,9 @@ example: user1 reading/writing secrets
63
63
  => [[:instance, {:new_rec=>false, :actions=>nil, :schema=>[[:integer, :id, 2, 1], [:integer, :user_id, 3, 1], [:text, :name, 4, "this is my secret"], [:text, :message, 0, nil]], :name=>"secret", :url=>"/secret/1"}, []]]
64
64
  >> @client.read({},:auth => @user2_auth)
65
65
  => []
66
- >> @client.read({},:auth => @user2_auth,:instance_id => 1, :code => 403)
67
- => [:error, {:error_type=>"authorization", :error_details=>nil, :description=>"You are not authorized for this operation"}]
66
+ >> @client.read({},:auth => @user2_auth,:instance_id => 1, :code => 404)
67
+ => [:error, {:error_type=>"routing", :description=>"Not Found", :error_details=>nil}]
68
+
68
69
 
69
70
  example: user2 reading/writing secrets
70
71
  >> @client.auth=@user2_auth
@@ -80,8 +81,8 @@ example: user2 reading/writing secrets
80
81
 
81
82
  >> @client.read({}, :auth => @user1_auth)
82
83
  => []
83
- >> @client.read({}, :auth => @user1_auth, :instance_id => 1,:code => 403)
84
- => [:error, {:error_type=>"authorization", :error_details=>nil, :description=>"You are not authorized for this operation"}]
84
+ >> @client.read({}, :auth => @user1_auth, :instance_id => 1,:code => 404)
85
+ => [:error, {:error_type=>"routing", :description=>"Not Found", :error_details=>nil}]
85
86
 
86
87
  examples: announcements
87
88
  >> @client.auth=@user1_auth
@@ -17,7 +17,7 @@ link_property ::= 'title' | 'description' | 'url'
17
17
 
18
18
  instance_property ::= 'name' | 'url' | 'new_rec' | 'search' | 'schema' | 'actions'
19
19
 
20
- instance_list_property ::='title' | 'description' | 'schema' | 'actions' | 'items'
20
+ instance_list_property ::='title' | 'description' | 'schema' | 'actions' | 'group_actions' | 'items'
21
21
 
22
22
  msg_property ::= 'title' | 'description'
23
23
 
@@ -41,6 +41,8 @@ items_value ::= '[' '[' col_value (',' col_value)* ']' (',' '[' col_value (',' c
41
41
 
42
42
  actions_value ::= '{' '"' ('get' | 'post' | 'put' | 'delete') '"' ':' methods (',' '"' ('get' | 'post' | 'put' | 'delete') '"' ':' methods )* '}'
43
43
 
44
+ group_actions_value ::= actions_value
45
+
44
46
  methods::= '[' ( get_method (',' get_method)* | post_method (',' post_method)* | put_method (',' put_method)* | delete_method (',' delete_method)* ) ']'
45
47
 
46
48
  get_action ::= string_literal
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marley
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Herb Daily
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2012-03-24 00:00:00 -03:00
12
+ date: 2012-03-29 00:00:00 -03:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -98,6 +98,7 @@ files:
98
98
  - lib/marley/joint.rb
99
99
  - lib/marley/plugins/orm_rest_convenience.rb
100
100
  - lib/marley/plugins/rest_convenience.rb
101
+ - lib/marley/plugins/orm_materialized_path.rb
101
102
  - lib/marley/controllers.rb
102
103
  - lib/marley/errors.rb
103
104
  - lib/marley/reggae.rb
@@ -109,6 +110,7 @@ files:
109
110
  - rdoc/user_joint/no_auth_provided.rdoc
110
111
  - rdoc/user_joint/exiting_users.rdoc
111
112
  - rdoc/messages_joint.rb
113
+ - rdoc/orm_materialized_path_plugin.rb
112
114
  - rdoc/messages_joint.rdoc
113
115
  - rdoc/hello.rb
114
116
  - rdoc/section_joint.rdoc
@@ -122,6 +124,7 @@ files:
122
124
  - rdoc/orm_rest_convenience_plugin.rdoc
123
125
  - rdoc/reggae/generate.rdoc
124
126
  - rdoc/reggae/parse.rdoc
127
+ - rdoc/orm_materialized_path_plugin.rdoc
125
128
  - rdoc/user_joint.rb
126
129
  - rdoc/joints.rdoc
127
130
  - rdoc/hello.rdoc