prawn_cocktail 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in prawn_cocktail.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # PrawnCocktail
2
+
3
+ Simple views, templates and helpers on top of Prawn in Ruby on Rails.
4
+
5
+ Because writing Prawn documents PHP 4 style is no fun.
6
+
7
+ Ruby 1.9 only.
8
+
9
+ NOTE: Work in progress; well used but untested.
10
+
11
+ ![](http://upload.wikimedia.org/wikipedia/commons/f/f8/Cocktail_1_bg_060702.jpg)
12
+
13
+ ## TODO
14
+
15
+ * Tests.
16
+ * Look into what dependencies to declare. Rails? Active Support?
17
+ * Include instead of inherit? Consider `class_attribute`.
18
+
19
+ ## Usage
20
+
21
+ ### Controller
22
+
23
+ Your controllers get a `send_pdf` method:
24
+
25
+ ``` ruby
26
+ class InvoiceController < ApplicationController
27
+ def show
28
+ invoice = Invoice.find(params[:id])
29
+ document = InvoiceDocument.new(invoice)
30
+ send_pdf document
31
+ end
32
+ end
33
+ ```
34
+
35
+ ### View
36
+
37
+ Against Rails conventions, but in line with the idea of [two-step views](http://martinfowler.com/eaaCatalog/twoStepView.html), we think of these as "views" as opposed to "templates".
38
+
39
+ Build your view data in a document class:
40
+
41
+ ``` ruby
42
+ # app/documents/invoice_document.rb
43
+
44
+ class InvoiceDocument < PrawnCocktail::Document
45
+ def initialize(invoice)
46
+ @invoice = invoice
47
+ end
48
+
49
+ def filename
50
+ "invoice_#{@invoice.id}"
51
+ end
52
+
53
+ private
54
+
55
+ def data
56
+ {
57
+ number: @invoice.id,
58
+ amount: @invoice.amount,
59
+ customer_name: @invoice.customer_name
60
+ }
61
+ end
62
+ end
63
+ ```
64
+
65
+ The document has `render` and `render_file(name)` methods, just like `Prawn::Document`.
66
+
67
+ The filename, if defined, is used when generating the document. The `data` value is passed to the template as an `OpenStruct`.
68
+
69
+ If the data becomes complex, you are advised to extract one or many builder classes like `InvoiceDocument::Data` and call those from `data`.
70
+
71
+ ### Template
72
+
73
+ Put the Prawn code in a template named after the view:
74
+
75
+ ``` ruby
76
+ # app/documents/views/invoice_document.pdf.rb
77
+
78
+ meta page_size: "A4"
79
+
80
+ content do |data|
81
+ text "Invoice #{data.number}"
82
+ move_down 1.cm
83
+ text "Amount: #{data.amount}"
84
+ move_down 1.cm
85
+ text data.customer_name
86
+ end
87
+ ```
88
+
89
+ The `meta` declaration is optional. It takes a hash which will be passed to `Prawn::Document.new`. This is where you specify `page_size`, `page_layout` and such.
90
+
91
+ The `content` block will be passed the data from the document as an `OpenStruct`, and will be rendered in the context of a `Prawn::Document` instance.
92
+
93
+ ### Helpers
94
+
95
+ You are advised to extract any complexity or shared code out of the template and into helpers:
96
+
97
+ ``` ruby
98
+ # app/documents/invoice_document.rb
99
+
100
+ class InvoiceDocument
101
+ helper BaseDocumentHelper
102
+ helper InvoiceDocumentHelper
103
+ end
104
+ ```
105
+
106
+ ``` ruby
107
+ # app/documents/views/invoice_document.pdf.rb
108
+
109
+ content do |data|
110
+ common_header
111
+ text "Yo."
112
+ end
113
+ ```
114
+
115
+ ``` ruby
116
+ # app/documents/helpers/base_document_helper.rb
117
+
118
+ module BaseDocumentHelper
119
+ def common_header
120
+ text "Document generated #{Time.now}."
121
+ end
122
+ end
123
+ ```
124
+
125
+ Note that you must explicitly declare the helpers you want. No helpers are automatically included.
126
+
127
+ You can declare base helpers in a base document class, though, and that will be inherited.
128
+
129
+ ### `initialize_document`
130
+
131
+ If you want to run some code in every document, use an `initialize_document` block:
132
+
133
+ ``` ruby
134
+ class BaseDocument < PrawnCocktail::Document
135
+ initialize_document do
136
+ FONT_DIR ||= Rails.root.join("app/views/documents/fonts")
137
+
138
+ font_families.update(
139
+ "Helvetica Neue" => {
140
+ bold: FONT_DIR.join("HelveticaNeueLTCom-Md.ttf").to_s,
141
+ normal: FONT_DIR.join("HelveticaNeueLTCom-Lt.ttf").to_s
142
+ })
143
+
144
+ font "Helvetica Neue"
145
+ end
146
+ end
147
+ ```
148
+
149
+ This is incidentally how helper modules are implemented. They simply extend the document instance in such a block.
150
+
151
+ ## Installation
152
+
153
+ Add this line to your application's Gemfile:
154
+
155
+ gem 'prawn_cocktail'
156
+
157
+ And then execute:
158
+
159
+ $ bundle
160
+
161
+ Or install it yourself as:
162
+
163
+ $ gem install prawn_cocktail
164
+
165
+ ## License
166
+
167
+ Copyright (c) 2013 [Barsoom AB](http://barsoom.se)
168
+
169
+ MIT License
170
+
171
+ Permission is hereby granted, free of charge, to any person obtaining
172
+ a copy of this software and associated documentation files (the
173
+ "Software"), to deal in the Software without restriction, including
174
+ without limitation the rights to use, copy, modify, merge, publish,
175
+ distribute, sublicense, and/or sell copies of the Software, and to
176
+ permit persons to whom the Software is furnished to do so, subject to
177
+ the following conditions:
178
+
179
+ The above copyright notice and this permission notice shall be
180
+ included in all copies or substantial portions of the Software.
181
+
182
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
183
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
184
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
185
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
186
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
187
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
188
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,8 @@
1
+ require "prawn_cocktail/version"
2
+ require "prawn_cocktail/controller"
3
+ require "prawn_cocktail/document"
4
+ require "prawn_cocktail/railtie"
5
+
6
+ class ActionController::Base
7
+ include PrawnCocktail::Controller
8
+ end
@@ -0,0 +1,16 @@
1
+ module PrawnCocktail
2
+ module Controller
3
+ private
4
+
5
+ def send_pdf(document)
6
+ filename = document.respond_to?(:filename) ? "#{document.filename}.pdf" : nil
7
+
8
+ send_data(
9
+ document.render,
10
+ type: "application/pdf",
11
+ disposition: "attachment",
12
+ filename: filename
13
+ )
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ require "prawn"
2
+ require "active_support/core_ext/class/attribute"
3
+
4
+ require_relative "renderer"
5
+
6
+ module PrawnCocktail
7
+ class Document
8
+ def render
9
+ renderer.render_data
10
+ end
11
+
12
+ def render_file(file)
13
+ renderer.render_file(file)
14
+ end
15
+
16
+ private
17
+
18
+ def renderer
19
+ @renderer ||= Renderer.new(template, data, self.class.doc_initializers)
20
+ end
21
+
22
+ def template
23
+ self.class.name.underscore
24
+ end
25
+
26
+ class_attribute :doc_initializers
27
+ self.doc_initializers ||= []
28
+
29
+ def self.initialize_document(&block)
30
+ self.doc_initializers << block
31
+ end
32
+
33
+ def self.helper(mod)
34
+ initialize_document { extend mod }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ require "rails"
2
+
3
+ module PrawnCocktail
4
+ class Railtie < Rails::Railtie
5
+ initializer "prawn_cocktail.autoload", before: :set_autoload_paths do |app|
6
+ app.config.autoload_paths << "#{app.config.root}/app/documents/helpers"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,58 @@
1
+ module PrawnCocktail
2
+ class Renderer
3
+ def initialize(template, data, doc_initializers)
4
+ @template = template
5
+ @data = data
6
+ @doc_initializers = doc_initializers
7
+ end
8
+
9
+ def meta(opts)
10
+ @prawn_document_options = opts
11
+ end
12
+
13
+ def content(&block)
14
+ @doc_initializers.each do |proc|
15
+ doc.instance_eval(&proc)
16
+ end
17
+
18
+ doc.instance_exec(data_object, &block)
19
+ end
20
+
21
+ def render_data
22
+ render
23
+ doc.render
24
+ end
25
+
26
+ def render_file(file)
27
+ render
28
+ doc.render_file(file)
29
+ end
30
+
31
+ private
32
+
33
+ def render
34
+ # We pass the filename for better backtraces.
35
+ instance_eval(read_template, template_path)
36
+ end
37
+
38
+ def doc
39
+ @doc ||= Prawn::Document.new(@prawn_document_options || {})
40
+ end
41
+
42
+ def data_object
43
+ OpenStruct.new(@data)
44
+ end
45
+
46
+ def read_template
47
+ File.read(File.join(app_root, template_path))
48
+ end
49
+
50
+ def template_path
51
+ "app/documents/views/#{@template}.pdf.rb"
52
+ end
53
+
54
+ def app_root
55
+ Rails.root
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module PrawnCocktail
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'prawn_cocktail/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "prawn_cocktail"
8
+ gem.version = PrawnCocktail::VERSION
9
+ gem.authors = ["Henrik Nyh"]
10
+ gem.email = ["henrik@barsoom.se"]
11
+ gem.summary = "Simple views, templates and helpers on top of Prawn in Ruby on Rails."
12
+ gem.homepage = ""
13
+
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_dependency "prawn"
20
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prawn_cocktail
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Henrik Nyh
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: prawn
16
+ requirement: &70234014918140 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70234014918140
25
+ description:
26
+ email:
27
+ - henrik@barsoom.se
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - README.md
35
+ - Rakefile
36
+ - lib/prawn_cocktail.rb
37
+ - lib/prawn_cocktail/controller.rb
38
+ - lib/prawn_cocktail/document.rb
39
+ - lib/prawn_cocktail/railtie.rb
40
+ - lib/prawn_cocktail/renderer.rb
41
+ - lib/prawn_cocktail/version.rb
42
+ - prawn_cocktail.gemspec
43
+ homepage: ''
44
+ licenses: []
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 1.8.5
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Simple views, templates and helpers on top of Prawn in Ruby on Rails.
67
+ test_files: []
68
+ has_rdoc: