zena 1.0.0.beta2 → 1.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. data/.gitignore +2 -0
  2. data/History.txt +12 -0
  3. data/app/controllers/application_controller.rb +0 -1
  4. data/app/controllers/columns_controller.rb +11 -1
  5. data/app/controllers/nodes_controller.rb +79 -19
  6. data/app/controllers/versions_controller.rb +0 -2
  7. data/app/controllers/virtual_classes_controller.rb +19 -6
  8. data/app/models/column.rb +5 -1
  9. data/app/models/comment.rb +1 -6
  10. data/app/models/node.rb +21 -3
  11. data/app/models/role.rb +21 -0
  12. data/app/models/site.rb +7 -2
  13. data/app/models/template.rb +3 -3
  14. data/app/models/text_document.rb +4 -4
  15. data/app/models/user.rb +21 -8
  16. data/app/views/columns/_li.html.erb +1 -0
  17. data/app/views/nodes/_groups.rhtml +1 -1
  18. data/app/views/sites/_form.erb +3 -1
  19. data/app/views/sites/_li.erb +1 -0
  20. data/app/views/sites/index.erb +1 -1
  21. data/app/views/virtual_classes/_form.erb +11 -2
  22. data/app/views/virtual_classes/_li.erb +5 -2
  23. data/bin/zena +1 -1
  24. data/bricks/math/lib/bricks/math.rb +1 -1
  25. data/bricks/mongrel/README +3 -0
  26. data/bricks/mongrel/zena/deploy.rb +56 -0
  27. data/bricks/passenger/README +3 -0
  28. data/bricks/passenger/zena/deploy.rb +49 -0
  29. data/config/bricks.yml +6 -0
  30. data/config/deploy.rb +24 -18
  31. data/config/gems.yml +3 -3
  32. data/db/migrate/20100915062903_add_api_group_id_to_site.rb +9 -0
  33. data/lib/tasks/zena.rake +39 -35
  34. data/lib/zena.rb +5 -6
  35. data/lib/zena/acts/enrollable.rb +37 -6
  36. data/lib/zena/app.rb +4 -2
  37. data/lib/zena/deploy.rb +110 -150
  38. data/lib/zena/deploy/awstats.conf.rhtml +4 -4
  39. data/lib/zena/deploy/httpd.rhtml +2 -1
  40. data/lib/zena/deploy/stats.vhost.rhtml +7 -7
  41. data/lib/zena/deploy/vhost.rhtml +1 -1
  42. data/lib/zena/deploy/vhost_www.rhtml +4 -4
  43. data/lib/zena/foxy_parser.rb +6 -5
  44. data/lib/zena/info.rb +1 -1
  45. data/lib/zena/integration/test_case.rb +8 -3
  46. data/lib/zena/parser.rb +11 -11
  47. data/lib/zena/parser/zafu_tags.rb +2 -2
  48. data/lib/zena/remote.rb +16 -0
  49. data/lib/zena/remote/connection.rb +67 -0
  50. data/lib/zena/remote/interface.rb +405 -0
  51. data/lib/zena/remote/klass.rb +14 -0
  52. data/lib/zena/remote/mock.rb +58 -0
  53. data/lib/zena/remote/node.rb +76 -0
  54. data/lib/zena/routes.rb +2 -1
  55. data/lib/zena/use.rb +9 -4
  56. data/lib/zena/use/ajax.rb +3 -3
  57. data/lib/zena/use/authlogic.rb +8 -1
  58. data/lib/zena/use/context.rb +22 -21
  59. data/lib/zena/use/dates.rb +26 -3
  60. data/lib/zena/use/display.rb +33 -5
  61. data/lib/zena/use/forms.rb +90 -12
  62. data/lib/zena/use/fulltext.rb +1 -1
  63. data/lib/zena/use/i18n.rb +118 -31
  64. data/lib/zena/use/query_builder.rb +7 -5
  65. data/lib/zena/use/query_node.rb +30 -4
  66. data/lib/zena/use/rendering.rb +1 -1
  67. data/lib/zena/use/search.rb +10 -7
  68. data/lib/zena/use/urls.rb +3 -3
  69. data/lib/zena/use/zafu_attributes.rb +2 -2
  70. data/lib/zena/use/zafu_eval.rb +1 -1
  71. data/lib/zena/use/zafu_safe_definitions.rb +1 -0
  72. data/lib/zena/use/zafu_templates.rb +1 -1
  73. data/lib/zena/zafu_compiler.rb +5 -1
  74. data/public/javascripts/zena.js +4 -4
  75. data/public/stylesheets/admin.css +1 -0
  76. data/test/custom_queries/complex.host.yml +3 -3
  77. data/test/fixtures/files/translations_fr.yml +4 -1
  78. data/test/functional/application_controller_test.rb +2 -2
  79. data/test/functional/nodes_controller_test.rb +57 -5
  80. data/test/functional/users_controller_test.rb +10 -9
  81. data/test/functional/virtual_classes_controller_test.rb +48 -0
  82. data/test/integration/navigation_test.rb +13 -1
  83. data/test/integration/query_node/filters.yml +5 -0
  84. data/test/integration/query_node_test.rb +1 -1
  85. data/test/integration/zafu_compiler/ajax.yml +13 -19
  86. data/test/integration/zafu_compiler/basic.yml +0 -72
  87. data/test/integration/zafu_compiler/complex.yml +1 -1
  88. data/test/integration/zafu_compiler/complex_ok.yml +19 -0
  89. data/test/integration/zafu_compiler/dates.yml +62 -1
  90. data/test/integration/zafu_compiler/display.yml +4 -4
  91. data/test/integration/zafu_compiler/forms.yml +19 -7
  92. data/test/integration/zafu_compiler/i18n.yml +56 -1
  93. data/test/integration/zafu_compiler/later.yml +23 -1
  94. data/test/integration/zafu_compiler/relations.yml +1 -1
  95. data/test/integration/zafu_compiler/roles.yml +29 -1
  96. data/test/integration/zafu_compiler/safe_definitions.yml +1 -1
  97. data/test/integration/zafu_compiler/zafu_attributes.yml +2 -1
  98. data/test/integration/zafu_compiler_test.rb +5 -3
  99. data/test/sites/zena/columns.yml +3 -0
  100. data/test/sites/zena/roles.yml +0 -1
  101. data/test/sites/zena/sites.yml +1 -0
  102. data/test/sites/zena/versions.yml +2 -0
  103. data/test/unit/node_test.rb +27 -9
  104. data/test/unit/relation_proxy_test.rb +7 -4
  105. data/test/unit/remote_test.rb +379 -0
  106. data/test/unit/user_test.rb +47 -0
  107. data/test/unit/zena/acts/enrollable_test.rb +36 -7
  108. data/test/unit/zena/acts/serializable_test.rb +14 -2
  109. data/test/unit/zena/use/i18n_test.rb +32 -5
  110. data/test/unit/zena/use/query_node_test.rb +13 -1
  111. data/zena.gemspec +25 -11
  112. metadata +24 -10
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
1
  .DS_Store
2
+ *.swp
3
+ *.gem
2
4
  restart.txt
3
5
  config/deploy_config.rb
4
6
  config/database.yml
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
+ == 1.0.0.beta3 2010-09-17
2
+
3
+ * major changes
4
+ * created Zena::Remote API
5
+ * fixed Ajax operations and tests
6
+ * fixed forms to create/update new objects
7
+ * added dynamic translations
8
+ * better querybuilder integration relative to SELECT clauses
9
+ * fixed date parsing
10
+ * added safe 'send' method
11
+ * added support to create and update Roles
12
+
1
13
  == 1.0.0.beta2 2010-07-24
2
14
 
3
15
  * major changes
@@ -3,5 +3,4 @@ class ApplicationController < ActionController::Base
3
3
 
4
4
  include Zena::App
5
5
 
6
- include Zafu::ControllerMethods
7
6
  end
@@ -7,8 +7,18 @@ class ColumnsController < ApplicationController
7
7
  # GET /columns
8
8
  # GET /columns.xml
9
9
  def index
10
+ roles = {}
10
11
  secure(Column) do
11
- @columns = Column.paginate(:all, :order => 'name', :per_page => 20, :page => params[:page])
12
+ @columns = Column.paginate(:all, :order => 'role_id ASC, name ASC', :per_page => 20, :page => params[:page]).sort! do |a, b|
13
+ role_a = (roles[a.role_id] ||= a.role).name
14
+ role_b = (roles[b.role_id] ||= b.role).name
15
+
16
+ if role_a == role_b
17
+ a.name <=> b.name
18
+ else
19
+ role_a <=> role_b
20
+ end
21
+ end
12
22
  end
13
23
 
14
24
  @column = Column.new
@@ -3,22 +3,23 @@
3
3
 
4
4
  basepath class and zip optional mode format
5
5
 
6
- /projects/art/ project24 -print .html
6
+ /projects/art/ project24 _print .html
7
7
 
8
8
  Examples:
9
9
  /current/art/project24.html << a project inside the 'art' page
10
10
  /note24.html << a Note's page
11
11
  /note24_print.html << a Note in 'print' mode
12
- /current/art.html << 'art' page (this page has custom base set = no class or zip shown)
13
- /current/art-print.html << 'art' page in 'print' mode
12
+ /current/art.html << 'art' page (this page has custom base set, this means no class or zip shown)
13
+ /current/art_print.html << 'art' page in 'print' mode
14
14
  /current/art/project24/image28.html << image page (for comments, etc)
15
- /current/art/project24/image28.jpg << full image
16
- /current/art/project24/image28_pv.jpg << image in the 'pv' format
17
- /current/art/project24/image28_pv.html << image page in 'print' mode
15
+ /current/art/project24/image28.jpg << full image data
16
+ /current/art/project24/image28_pv.jpg << image in the 'pv' image format
17
+ /current/art/project24/image28_print.html << image page in 'print' mode
18
18
 
19
19
  =end
20
20
  class NodesController < ApplicationController
21
21
  before_filter :check_is_admin, :only => [:export]
22
+ before_filter :check_api_group
22
23
  before_filter :find_node, :except => [:index, :create, :not_found, :catch_all, :search]
23
24
  before_filter :check_can_drive, :only => [:edit]
24
25
  before_filter :check_path, :only => [:index, :show]
@@ -50,15 +51,46 @@ class NodesController < ApplicationController
50
51
  raise ActiveRecord::RecordNotFound
51
52
  end
52
53
 
54
+ # Find nodes starting from root node
53
55
  def search
54
- do_search
55
56
  respond_to do |format|
56
- format.html { render_and_cache :mode => '+search', :cache => false }
57
- format.xml { render :xml => @nodes ? @nodes.to_xml : []}
58
- format.js
57
+ format.html do
58
+ begin
59
+ do_search
60
+ rescue QueryBuilder::Error => err
61
+ flash[:error] = err.message
62
+ end
63
+ render_and_cache :mode => '+search', :cache => false
64
+ end
65
+
66
+ format.xml do
67
+ begin
68
+ do_search
69
+ if @nodes.kind_of?(Fixnum)
70
+ # count
71
+ render :xml => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<count type=\"integer\">#{@nodes}</count>\n"
72
+ elsif @nodes
73
+ render :xml => Array(@nodes).to_xml(:root => 'nodes')
74
+ else
75
+ render :xml => [].to_xml(:root => 'nodes')
76
+ end
77
+ rescue QueryBuilder::Error => err
78
+ render :xml => [{:message => err.message}].to_xml(:root => 'errors'), :status => 401
79
+ end
80
+ end
81
+
82
+ format.js do
83
+ do_search
84
+ render :action => 'search'
85
+ end
59
86
  end
60
87
  end
61
88
 
89
+ # Find nodes starting from a given node
90
+ def find
91
+ search
92
+ end
93
+
62
94
  # this should not be needed.... but format.js never gets called otherwize.
63
95
  def asearch
64
96
  do_search
@@ -180,7 +212,7 @@ class NodesController < ApplicationController
180
212
  flash[:notice] = 'Node was successfully created.'
181
213
  format.html { redirect_to zen_path(@node) }
182
214
  format.js
183
- format.xml { render :xml => @node, :status => :created, :location => node_url(@node) }
215
+ format.xml { render :xml => @node.to_xml(:root => 'node'), :status => :created, :location => node_url(@node) }
184
216
  else
185
217
  format.html { render :action => "new" }
186
218
  format.js
@@ -312,13 +344,19 @@ class NodesController < ApplicationController
312
344
  end
313
345
  end
314
346
  end # parent iframe (upload)
315
- elsif @node.errors.empty?
347
+ else
316
348
  respond_to do |format|
317
349
  format.html do
318
- if params[:edit] == 'popup'
319
- redirect_to edit_node_version_path(:node_id => @node[:zip], :id => 0, :close => (params[:validate] ? true : nil))
350
+ if @node.errors.empty?
351
+ if params[:edit] == 'popup'
352
+ redirect_to edit_node_version_path(:node_id => @node[:zip], :id => 0, :close => (params[:validate] ? true : nil))
353
+ else
354
+ redirect_to zen_path(@node, :mode => params[:mode])
355
+ end
320
356
  else
321
- redirect_to zen_path(@node, :mode => params[:mode])
357
+ # FIXME: Render referring page would be better
358
+ # Get mode and details from request.referer
359
+ render_and_cache :mode => 'edit', :cache => false
322
360
  end
323
361
  end # html
324
362
 
@@ -564,6 +602,13 @@ class NodesController < ApplicationController
564
602
  end
565
603
 
566
604
  def do_search
605
+ if @node
606
+ default_scope = 'self'
607
+ else
608
+ @node = current_site.root_node
609
+ default_scope = 'site'
610
+ end
611
+
567
612
  unless query_params = params[:q]
568
613
  query_params = params.dup
569
614
  %w{controller action format}.each do |key|
@@ -571,10 +616,18 @@ class NodesController < ApplicationController
571
616
  end
572
617
  end
573
618
 
574
- @node = current_site.root_node
575
- @search_per_page = params[:per_page] ? params[:per_page].to_i : 20
576
- @nodes = secure(Node) { Node.search_records(query_params, :node => @node, :page => params[:page], :per_page => @search_per_page) }
577
- @search_count = 100 # FIXME: @nodes ? @nodes.total_entries : 0
619
+ if request.format != Mime::XML || params[:page] || params[:per_page]
620
+ @search_per_page = params[:per_page] ? params[:per_page].to_i : 20
621
+ @nodes = secure(Node) { Node.search_records(query_params, :node => @node, :default => {:scope => default_scope}, :page => params[:page], :per_page => @search_per_page) }
622
+ @search_count = 100 # FIXME: @nodes ? @nodes.total_entries : 0
623
+ else
624
+ # XML without pagination
625
+ @nodes = secure(Node) { Node.search_records(query_params, :node => @node, :default => {:scope => default_scope}) }
626
+ end
627
+
628
+ if @nodes.kind_of?(Node)
629
+ @nodes = [@nodes]
630
+ end
578
631
  end
579
632
 
580
633
  # Document data do not change session[:lang] and can point at cached content (no nee to redirect to AUTHENTICATED_PREFIX).
@@ -608,5 +661,12 @@ class NodesController < ApplicationController
608
661
  def check_can_drive
609
662
  raise ActiveRecord::RecordNotFound unless @node.can_drive?
610
663
  end
664
+
665
+ def check_api_group
666
+ return true if request.format != Mime::XML || visitor.api_authorized?
667
+
668
+ render :xml => [{:message => 'Not in API group.'}].to_xml(:root => 'errors'), :status => 401
669
+ false
670
+ end
611
671
  end
612
672
 
@@ -111,8 +111,6 @@ class VersionsController < ApplicationController
111
111
  source[k] || '').format_as(:html).gsub(/(\s+)<\/del>/, '</del>\1')
112
112
  end
113
113
 
114
- puts target.inspect
115
-
116
114
  show
117
115
  end
118
116
 
@@ -6,7 +6,7 @@ class VirtualClassesController < ApplicationController
6
6
 
7
7
  def index
8
8
  secure(VirtualClass) do
9
- @virtual_classes = VirtualClass.paginate(:all, :order => 'kpath', :per_page => 20, :page => params[:page])
9
+ @virtual_classes = Role.paginate(:all, :order => 'kpath', :per_page => 20, :page => params[:page])
10
10
  end
11
11
 
12
12
  last_kpath = @virtual_classes.last.kpath
@@ -16,7 +16,17 @@ class VirtualClassesController < ApplicationController
16
16
  end
17
17
  end
18
18
 
19
- @virtual_classes.sort! {|a, b| a.kpath <=> b.kpath }
19
+ @virtual_classes.sort! do |a, b|
20
+ if a.kpath == b.kpath
21
+ # Order VirtualClass first
22
+ b_type = b.kind_of?(Role) ? b.class.to_s : 'V' # sort real classes like VirtualClass
23
+ a_type = a.kind_of?(Role) ? a.class.to_s : 'V'
24
+
25
+ b_type <=> a_type
26
+ else
27
+ a.kpath <=> b.kpath
28
+ end
29
+ end
20
30
 
21
31
  @virtual_class = VirtualClass.new('')
22
32
 
@@ -80,7 +90,12 @@ class VirtualClassesController < ApplicationController
80
90
  end
81
91
 
82
92
  def create
83
- @virtual_class = VirtualClass.new(params[:virtual_class])
93
+ type = params[:virtual_class].delete(:type)
94
+ if type == 'Role'
95
+ @virtual_class = Role.new(params[:virtual_class])
96
+ else
97
+ @virtual_class = VirtualClass.new(params[:virtual_class])
98
+ end
84
99
 
85
100
  respond_to do |format|
86
101
  if @virtual_class.save
@@ -97,8 +112,6 @@ class VirtualClassesController < ApplicationController
97
112
  end
98
113
 
99
114
  def update
100
- @virtual_class = VirtualClass.find(params[:id])
101
-
102
115
  respond_to do |format|
103
116
  if @virtual_class.update_attributes(params[:virtual_class])
104
117
  flash[:notice] = 'VirtualClass was successfully updated.'
@@ -125,6 +138,6 @@ class VirtualClassesController < ApplicationController
125
138
 
126
139
  protected
127
140
  def find_virtual_class
128
- @virtual_class = secure!(VirtualClass) { VirtualClass.find(params[:id])}
141
+ @virtual_class = secure!(VirtualClass) { Role.find(params[:id])}
129
142
  end
130
143
  end
data/app/models/column.rb CHANGED
@@ -12,11 +12,15 @@ class Column < ActiveRecord::Base
12
12
  validates_uniqueness_of :name, :scope => :site_id
13
13
  validate :name_not_in_models
14
14
 
15
+ safe_method :name => String
16
+
15
17
  class << self
16
18
  include Zena::Acts::Secure
17
19
 
18
20
  def roles_for_form
19
- secure(Role) { Role.all(:order => 'kpath ASC') }.map {|r| [r.name, r.id]}
21
+ secure(Role) { Role.all(:order => 'name ASC') }.map do |role|
22
+ [role.name, role.id]
23
+ end
20
24
  end
21
25
 
22
26
  # Import a hash of virtual class definitions and try to build the virtual classes.
@@ -10,7 +10,7 @@ class Comment < ActiveRecord::Base
10
10
 
11
11
  safe_attribute :title, :created_at, :updated_at, :status
12
12
  safe_method :text => String, :author_name => {:class => String, :nil => true},
13
- :discussion_zip => Number
13
+ :discussion_id => Number
14
14
 
15
15
  safe_context :replies => ['Comment'], :node => 'Node'
16
16
 
@@ -64,11 +64,6 @@ class Comment < ActiveRecord::Base
64
64
  self[:id]
65
65
  end
66
66
 
67
- # needed by zafu to group
68
- def discussion_zip
69
- self[:discussion_id]
70
- end
71
-
72
67
  # TODO: test
73
68
  def can_write?
74
69
  is_author? && discussion.open?
data/app/models/node.rb CHANGED
@@ -162,7 +162,6 @@ class Node < ActiveRecord::Base
162
162
  :score => Number, :comments_count => Number,
163
163
  :custom_a => Number, :custom_b => Number
164
164
 
165
- # FIXME: remove 'zip' and use :id => {:class => Number, :method => 'zip'}
166
165
  # same with parent_zip, section_zip, etc...
167
166
 
168
167
 
@@ -808,7 +807,7 @@ class Node < ActiveRecord::Base
808
807
  transform_attributes(attributes, base_node)
809
808
  end
810
809
 
811
- def safe_method_type(signature)
810
+ def safe_method_type(signature, receiver = nil)
812
811
  if signature.size > 1
813
812
  RubyLess::SafeClass.safe_method_type_for(self, signature)
814
813
  else
@@ -818,6 +817,13 @@ class Node < ActiveRecord::Base
818
817
  elsif method =~ /^(.+)_((id|zip|status|comment)(s?))\Z/ && !instance_methods.include?(method)
819
818
  key = $3 == 'id' ? "zip#{$4}" : $2
820
819
  {:method => "rel[#{$1.inspect}].try(:other_#{key})", :nil => true, :class => ($4.blank? ? Number : [Number])}
820
+ elsif receiver && query = receiver.opts[:query]
821
+ # Resolve by using information in the SELECT part of the query that found this node
822
+ if query.select_keys.include?(method)
823
+ {:class => String, :method => "attributes[#{method.inspect}]", :nil => true}
824
+ else
825
+ nil
826
+ end
821
827
  else
822
828
  nil
823
829
  end
@@ -1395,6 +1401,19 @@ class Node < ActiveRecord::Base
1395
1401
  secure(Node) { Node.find_node_by_pseudo(string, base_node || self) }
1396
1402
  end
1397
1403
 
1404
+ safe_method [:send, String] => {:class => String, :nil => true, :method => 'safe_send'}
1405
+
1406
+ # Safe dynamic method dispatching when the method is not known during compile time. Currently this
1407
+ # only works for methods without arguments.
1408
+ def safe_send(method)
1409
+ # We need to load roles or all properties will be ignored
1410
+ load_roles!
1411
+
1412
+ return nil unless type = safe_method_type([method])
1413
+ res = eval(type[:method])
1414
+ res ? res.to_s : nil
1415
+ end
1416
+
1398
1417
  protected
1399
1418
 
1400
1419
  # after node is saved, make sure it's children have the correct section set
@@ -1721,7 +1740,6 @@ class Node < ActiveRecord::Base
1721
1740
  end
1722
1741
  end
1723
1742
  end
1724
-
1725
1743
  end
1726
1744
 
1727
1745
  Bricks.apply_patches
data/app/models/role.rb CHANGED
@@ -8,6 +8,27 @@ class Role < ActiveRecord::Base
8
8
  before_validation :set_defaults
9
9
  validate :check_can_save
10
10
 
11
+ include RubyLess
12
+ safe_method :columns => {:class => ['Column'], :method => 'columns.values', :nil => false}
13
+ safe_method :name => String
14
+
15
+ def superclass
16
+ if new_record?
17
+ Node
18
+ else
19
+ Node.get_class_from_kpath(kpath)
20
+ end
21
+ end
22
+
23
+ def superclass=(klass)
24
+ if k = Node.get_class(klass)
25
+ self.kpath = k.kpath
26
+ else
27
+ errors.add('superclass', 'invalid')
28
+ end
29
+ end
30
+
31
+
11
32
  private
12
33
  def set_defaults
13
34
  self.site_id = visitor.site.id
data/app/models/site.rb CHANGED
@@ -19,11 +19,11 @@ The #Site model holds configuration information for a site:
19
19
  class Site < ActiveRecord::Base
20
20
  include RubyLess
21
21
  safe_method :host => String, :lang_list => [String]
22
- safe_context :root => {:class => Node, :method => 'root_node'}
22
+ safe_context :root => {:class => 'Node', :method => 'root_node'}
23
23
 
24
24
  validate :valid_site
25
25
  validates_uniqueness_of :host
26
- attr_accessible :name, :languages, :default_lang, :authentication, :http_auth, :auto_publish, :redit_time
26
+ attr_accessible :name, :languages, :default_lang, :authentication, :http_auth, :auto_publish, :redit_time, :api_group_id
27
27
  has_many :groups, :order => "name"
28
28
  has_many :nodes
29
29
  has_many :users
@@ -229,6 +229,11 @@ class Site < ActiveRecord::Base
229
229
  @site_group ||= Group.find(self[:site_group_id])
230
230
  end
231
231
 
232
+ # Return the API group: the one in which API visitors must be to use the API.
233
+ def api_group
234
+ @api_group ||= Group.find_by_id(self[:api_group_id])
235
+ end
236
+
232
237
  # Return true if the given user is an administrator for this site.
233
238
  def is_admin?(user)
234
239
  admin_user_ids.include?(user[:id])
@@ -93,14 +93,14 @@ class Template < TextDocument
93
93
  self.text = <<END_TXT
94
94
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
95
95
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
96
- <html xmlns="http://www.w3.org/1999/xhtml" do='void' lang="en" set_lang='[v_lang]' xml:lang='en'>
96
+ <html xmlns='http://www.w3.org/1999/xhtml' do='void' lang='\#{v.lang}' xml:lang='en'>
97
97
  <head do='void' name='head'>
98
98
  <title do='title_for_layout' do='show' attr='title' name='page_title'>page title</title>
99
99
  <!-- link href='favicon.png' rel='shortcut icon' type='image/png' / -->
100
- <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
100
+ <meta http-equiv='Content-type' content='text/html; charset=utf-8' />
101
101
  <r:void name='stylesheets'>
102
102
  <r:stylesheets/>
103
- <link href="style.css" rel="Stylesheet" type="text/css"/>
103
+ <link href='style.css' rel='Stylesheet' type='text/css'/>
104
104
  </r:void>
105
105
 
106
106
  <r:javascripts/>