##// END OF EJS Templates
Adds a builder-like template system for rendering xml and json API responses....
Jean-Philippe Lang -
r4338:96ce0f017cfe
parent child
Show More
@@ -0,0 +1,28
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 module Redmine
19 module Views
20 class ApiTemplateHandler < ActionView::TemplateHandler
21 include ActionView::TemplateHandlers::Compilable
22
23 def compile(template)
24 "Redmine::Views::Builders.for(params[:format]) do |api|; #{template.source}; self.output_buffer = api.output; end"
25 end
26 end
27 end
28 end
@@ -0,0 +1,35
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 module Redmine
19 module Views
20 module Builders
21 def self.for(format, &block)
22 builder = case format
23 when 'xml', :xml; Builders::Xml.new
24 when 'json', :json; Builders::Json.new
25 else; raise "No builder for format #{format}"
26 end
27 if block
28 block.call(builder)
29 else
30 builder
31 end
32 end
33 end
34 end
35 end
@@ -0,0 +1,30
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 require 'blankslate'
19
20 module Redmine
21 module Views
22 module Builders
23 class Json < Structure
24 def output
25 @struct.first.to_json
26 end
27 end
28 end
29 end
30 end
@@ -0,0 +1,68
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 require 'blankslate'
19
20 module Redmine
21 module Views
22 module Builders
23 class Structure < BlankSlate
24 def initialize
25 @struct = [{}]
26 end
27
28 def array(tag, &block)
29 @struct << []
30 block.call(self)
31 ret = @struct.pop
32 @struct.last[tag] = ret
33 end
34
35 def method_missing(sym, *args, &block)
36 if args.any?
37 if args.first.is_a?(Hash)
38 if @struct.last.is_a?(Array)
39 @struct.last << args.first
40 end
41 else
42 if @struct.last.is_a?(Array)
43 @struct.last << (args.last || {}).merge(:value => args.first)
44 else
45 @struct.last[sym] = args.first
46 end
47 end
48 end
49
50 if block
51 @struct << {}
52 block.call(self)
53 ret = @struct.pop
54 if @struct.last.is_a?(Array)
55 @struct.last << ret
56 else
57 @struct.last[sym] = ret
58 end
59 end
60 end
61
62 def output
63 raise "Need to implement #{self.class.name}#output"
64 end
65 end
66 end
67 end
68 end
@@ -0,0 +1,45
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 module Redmine
19 module Views
20 module Builders
21 class Xml < ::Builder::XmlMarkup
22 def initialize
23 super
24 instruct!
25 end
26
27 def output
28 target!
29 end
30
31 def method_missing(sym, *args, &block)
32 if args.size == 1 && args.first.is_a?(Time)
33 __send__ sym, args.first.xmlschema, &block
34 else
35 super
36 end
37 end
38
39 def array(name, options={}, &block)
40 __send__ name, options.merge(:type => 'array'), &block
41 end
42 end
43 end
44 end
45 end
@@ -0,0 +1,54
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 require File.dirname(__FILE__) + '/../../../../../test_helper'
19
20 class Redmine::Views::Builders::JsonTest < HelperTestCase
21
22 def test_hash
23 assert_json_output({'person' => {'name' => 'Ryan', 'age' => 32}}) do |b|
24 b.person do
25 b.name 'Ryan'
26 b.age 32
27 end
28 end
29 end
30
31 def test_array
32 assert_json_output({'books' => [{'title' => 'Book 1', 'author' => 'B. Smith'}, {'title' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
33 b.array :books do |b|
34 b.book :title => 'Book 1', :author => 'B. Smith'
35 b.book :title => 'Book 2', :author => 'G. Cooper'
36 end
37 end
38 end
39
40 def test_array_with_content_tags
41 assert_json_output({'books' => [{'value' => 'Book 1', 'author' => 'B. Smith'}, {'value' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
42 b.array :books do |b|
43 b.book 'Book 1', :author => 'B. Smith'
44 b.book 'Book 2', :author => 'G. Cooper'
45 end
46 end
47 end
48
49 def assert_json_output(expected, &block)
50 builder = Redmine::Views::Builders::Json.new
51 block.call(builder)
52 assert_equal(expected, ActiveSupport::JSON.decode(builder.output))
53 end
54 end
@@ -0,0 +1,54
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 require File.dirname(__FILE__) + '/../../../../../test_helper'
19
20 class Redmine::Views::Builders::XmlTest < HelperTestCase
21
22 def test_hash
23 assert_xml_output('<person><name>Ryan</name><age>32</age></person>') do |b|
24 b.person do
25 b.name 'Ryan'
26 b.age 32
27 end
28 end
29 end
30
31 def test_array
32 assert_xml_output('<books type="array"><book author="B. Smith" title="Book 1"/><book author="G. Cooper" title="Book 2"/></books>') do |b|
33 b.array :books do |b|
34 b.book :title => 'Book 1', :author => 'B. Smith'
35 b.book :title => 'Book 2', :author => 'G. Cooper'
36 end
37 end
38 end
39
40 def test_array_with_content_tags
41 assert_xml_output('<books type="array"><book author="B. Smith">Book 1</book><book author="G. Cooper">Book 2</book></books>') do |b|
42 b.array :books do |b|
43 b.book 'Book 1', :author => 'B. Smith'
44 b.book 'Book 2', :author => 'G. Cooper'
45 end
46 end
47 end
48
49 def assert_xml_output(expected, &block)
50 builder = Redmine::Views::Builders::Xml.new
51 block.call(builder)
52 assert_equal('<?xml version="1.0" encoding="UTF-8"?>' + expected, builder.output)
53 end
54 end
@@ -22,7 +22,7 class ApplicationController < ActionController::Base
22 22 include Redmine::I18n
23 23
24 24 layout 'base'
25 exempt_from_layout 'builder'
25 exempt_from_layout 'builder', 'apit'
26 26
27 27 # Remove broken cookie after upgrade from 0.8.x (#4292)
28 28 # See https://rails.lighthouseapp.com/projects/8994/tickets/3360
@@ -229,3 +229,5 end
229 229 Redmine::WikiFormatting.map do |format|
230 230 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
231 231 end
232
233 ActionView::Template.register_template_handler :apit, Redmine::Views::ApiTemplateHandler
General Comments 0
You need to be logged in to leave comments. Login now