rails_presenter 0.0.1 → 0.0.2

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.
data/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # Rails Presenter
2
+
3
+ [![Build Status](https://travis-ci.org/dfmonaco/rails_presenter.png?branch=master)](https://travis-ci.org/dfmonaco/rails_presenter)
4
+
5
+ ##Before:
6
+
7
+ ```haml
8
+ # app/views/purchase_orders/show.html.haml
9
+
10
+ %h1 Purchase Order
11
+ %div
12
+ %p
13
+ %strong Date:
14
+ %span= localize(@purchase_order.date, format: :long)
15
+ %p
16
+ %strong Number:
17
+ %span= @purchase_order.number
18
+
19
+ %h2 Customer
20
+ %div
21
+ %p
22
+ %strong Name:
23
+ %span= @purchase_order.customer.name
24
+ %p
25
+ %strong Phone:
26
+ %span= @purchase_order.customer.phone || '------'
27
+ %p
28
+ %strong Email:
29
+ %span= mail_to(@purchase_order.customer.email)
30
+
31
+ %table
32
+ %thead
33
+ %tr
34
+ %th N°
35
+ %th Quantity
36
+ %th Item
37
+ %th Unit Price
38
+ %th Discount
39
+ %th Amount
40
+
41
+ %tbody
42
+ - @purchase_order.items.includes(:product).each_with_index do |item, index|
43
+ %tr
44
+ %td= index + 1
45
+ %td= number_with_precision(item.quantity)
46
+ %td= item.product.name
47
+ %td= number_to_currency(item.unit_price)
48
+ %td= number_to_percentage(item.discount)
49
+ %td= number_to_currency(item.amount)
50
+
51
+ %div
52
+ %p
53
+ %strong Subtotal:
54
+ %span= number_to_currency(@purchase_order.subtotal)
55
+ %p
56
+ %strong Vat:
57
+ %span= number_to_currency(@purchase_order.vat)
58
+ %p
59
+ %strong Total:
60
+ %span= number_to_currency(@purchase_order.total)
61
+
62
+ ```
63
+
64
+ ##After:
65
+
66
+ ```haml
67
+ # app/views/purchase_orders/show.html.haml
68
+
69
+ - present(@purchase_order) do |order_presenter|
70
+
71
+ %h1 Purchase Order
72
+ = order_presenter.with_attrs :date, :number
73
+
74
+ %h2 Customer
75
+ = order_presenter.customer.with_attrs :name, :phone, :email
76
+
77
+ %table
78
+ %thead
79
+ %tr
80
+ %th N°
81
+ %th Quantity
82
+ %th Item
83
+ %th Unit Price
84
+ %th Discount
85
+ %th Amount
86
+
87
+ %tbody
88
+ - order_presenter.items.each_with_index do |item_presenter, index|
89
+ %tr
90
+ %td= index + 1
91
+ %td= item_presenter.quantity
92
+ %td= item_presenter.product
93
+ %td= item_presenter.unit_price
94
+ %td= item_presenter.discount
95
+ %td= item_presenter.amount
96
+
97
+ = order_presenter.with_attrs :subtotal, :vat, :total
98
+ ```
99
+
100
+ ## How did we get here?
101
+
102
+ ```ruby
103
+ # app/presenters/purchase_order_presenter.rb
104
+
105
+ class PurchaseOrderPresenter < RailsPresenter::Base
106
+ present :customer
107
+
108
+ present :items do
109
+ includes(:product)
110
+ end
111
+
112
+ format :subtotal, :vat, :total, with: :number_to_currency
113
+
114
+ def date
115
+ h.localize(super, format: :long)
116
+ end
117
+ end
118
+ ```
119
+
120
+ ```ruby
121
+ # app/presenters/customer_presenter.rb
122
+
123
+ class CustomerPresenter < RailsPresenter::Base
124
+ def email
125
+ h.mail_to super
126
+ end
127
+ end
128
+ ```
129
+
130
+ ```ruby
131
+ # app/presenters/item_presenter.rb
132
+
133
+ class ItemPresenter < RailsPresenter::Base
134
+ present :product
135
+
136
+ format :quantity, with: :number_with_precision
137
+ format :unit_price, :amount, with: :number_to_currency
138
+ format :discount, with: :number_to_percentage
139
+ end
140
+ ```
141
+
142
+ ```ruby
143
+ # app/presenters/product_presenter.rb
144
+
145
+ class ProductPresenter < RailsPresenter::Base
146
+ end
147
+ ```
148
+
149
+
@@ -1,18 +1,3 @@
1
1
  module PresenterHelper
2
- def present(object, template = self, &block)
3
- if [Array, ActiveRecord::Relation].include? object.class
4
- return object.map {|e| present(e)}
5
- end
6
-
7
- begin
8
- presenter_class = "#{object.class}Presenter".constantize
9
- rescue NameError
10
- return object
11
- end
12
-
13
- presenter = presenter_class.new(object, template)
14
-
15
- block.call(presenter) if block
16
- presenter
17
- end
2
+ include RailsPresenter::PresenterHelper
18
3
  end
@@ -1,7 +1,7 @@
1
1
  <div class="show-with-attrs">
2
2
  <% attrs_hash.each do |name, value| %>
3
3
  <p>
4
- <strong><%= name %></strong>
4
+ <strong><%= "#{name.to_s.titleize}: " %></strong>
5
5
  <span><%= value %></span>
6
6
  </p>
7
7
  <% end %>
@@ -0,0 +1,182 @@
1
+ require 'delegate'
2
+
3
+ module RailsPresenter
4
+ class Base < SimpleDelegator
5
+ include RailsPresenter::PresenterHelper
6
+
7
+ @@nil_formatter = '----'
8
+
9
+ class << self
10
+ def location(*args)
11
+ define_method(:self_location, ->(location=nil) do
12
+ location ||= args.map do |p|
13
+ p = p.to_s
14
+ if p.delete! "@"
15
+ public_send("get_#{p}")
16
+ else
17
+ p
18
+ end
19
+ end
20
+
21
+ super(location)
22
+ end)
23
+ end
24
+
25
+ def present(*args, &block)
26
+ module_name = "#{name}Associations"
27
+
28
+ unless const_defined? module_name
29
+ include const_set(module_name, Module.new)
30
+ end
31
+
32
+ associations_module = const_get(module_name)
33
+
34
+ block ||= proc { self }
35
+
36
+ associations_module.module_eval do
37
+ args.each do |assoc_name|
38
+ define_method(assoc_name) do
39
+ instance_variable_get("@#{assoc_name}") ||
40
+ begin
41
+ association = if super().is_a?(Array) && super().respond_to?(:scoped)
42
+ super().scoped
43
+ else
44
+ super()
45
+ end
46
+ instance_variable_set("@#{assoc_name}", present(association.instance_eval(&block)))
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+
54
+ def format(*attrs)
55
+ formatter = attrs.pop.values.first
56
+
57
+ module_name = formatter.to_s.camelize
58
+
59
+ unless const_defined? module_name
60
+ include const_set(module_name, Module.new)
61
+ end
62
+
63
+ formatter_module = const_get(module_name)
64
+
65
+ formatter_module.module_eval do
66
+ attrs.each do |attr|
67
+ define_method(attr) do
68
+ h.public_send(formatter, super())
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def inherited(child_class)
75
+ child_class.instance_eval do
76
+ format_blank_attributes(*possible_blank_attributes) if based_on_active_record?
77
+ end
78
+ end
79
+
80
+ def format_blank_attributes(*attrs)
81
+ attr_module = Module.new do
82
+ attrs.each do |attr|
83
+ define_method(attr) do
84
+ return nil_formatter if super().blank?
85
+ super()
86
+ end
87
+ end
88
+ end
89
+
90
+ include const_set("BlankAttributes", attr_module)
91
+ end
92
+
93
+ private
94
+
95
+ def base_class
96
+ @base_class ||= to_s.chomp('Presenter').constantize
97
+ end
98
+
99
+ def based_on_active_record?
100
+ base_class.ancestors.include?(ActiveRecord::Base)
101
+ end
102
+
103
+ def possible_blank_attributes
104
+ base_class.column_names.reject do |attr|
105
+ ['id', 'created_at', 'updated_at'].include?(attr) ||
106
+ /_id\z/.match(attr) ||
107
+ base_class.validators_on(attr).any? {|v| !(v.options[:allow_nil] || v.options[:allow_blank])}
108
+ end
109
+ end
110
+ end
111
+
112
+ def initialize(base_object, template)
113
+ @template = template
114
+ super(base_object)
115
+ end
116
+
117
+ def present(object)
118
+ super(object, h)
119
+ end
120
+
121
+ def h
122
+ @template
123
+ end
124
+
125
+ def o
126
+ __getobj__
127
+ end
128
+
129
+ def to_s
130
+ respond_to?(:name) ? name : super
131
+ end
132
+
133
+ def with_attrs(*attrs)
134
+ attrs_hash = attrs.reduce({}) do |hash, attr|
135
+ if attr.is_a? Array
136
+ hash[attr.first]= attr.last.call(self)
137
+ else
138
+ hash[attr]= public_send(attr)
139
+ end
140
+ hash
141
+ end
142
+
143
+ h.render partial: 'shared/show_with_attrs', locals: {attrs_hash: attrs_hash}
144
+ end
145
+
146
+ def self_location(location = o)
147
+ h.polymorphic_path location
148
+ end
149
+
150
+ def link_to_self(options={})
151
+ text = options[:text] || self.to_s
152
+ path = options[:path] || self_location
153
+ h.link_to text, path
154
+ end
155
+
156
+ def nil_formatter
157
+ @@nil_formatter
158
+ end
159
+
160
+ def method_missing(method_name, *args)
161
+ case method_name.to_s
162
+ when /^h_(.*)$/
163
+ get_iv_from_view($1)
164
+ when /^get_(.*)$/
165
+ return o if o.is_a? $1.camelize.constantize
166
+ get_iv_from_view($1) || o.public_send($1)
167
+ else
168
+ super
169
+ end
170
+ end
171
+
172
+ private
173
+ def base_object_name
174
+ o.class.to_s.underscore
175
+ end
176
+
177
+ def get_iv_from_view(iv_name)
178
+ h.instance_variable_get("@#{iv_name}")
179
+ end
180
+
181
+ end
182
+ end
@@ -0,0 +1,20 @@
1
+ module RailsPresenter
2
+ module PresenterHelper
3
+ def present(object, template = self, &block)
4
+ if [Array, ActiveRecord::Relation].include? object.class
5
+ return object.map {|e| present(e)}
6
+ end
7
+
8
+ begin
9
+ presenter_class = "#{object.class}Presenter".constantize
10
+ rescue NameError
11
+ return object
12
+ end
13
+
14
+ presenter = presenter_class.new(object, template)
15
+
16
+ block.call(presenter) if block
17
+ presenter
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module RailsPresenter
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,4 +1,6 @@
1
- require "rails_presenter/engine"
1
+ require 'rails_presenter/engine'
2
+ require 'rails_presenter/presenter_helper'
3
+ require 'rails_presenter/base'
2
4
 
3
5
  module RailsPresenter
4
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-02 00:00:00.000000000 Z
12
+ date: 2013-04-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -82,17 +82,18 @@ executables: []
82
82
  extensions: []
83
83
  extra_rdoc_files: []
84
84
  files:
85
- - app/presenters/presenter.rb
86
85
  - app/helpers/presenter_helper.rb
87
86
  - app/views/shared/_show_with_attrs.html.erb
88
87
  - config/routes.rb
89
88
  - lib/tasks/rails_presenter_tasks.rake
90
89
  - lib/rails_presenter.rb
90
+ - lib/rails_presenter/base.rb
91
91
  - lib/rails_presenter/engine.rb
92
92
  - lib/rails_presenter/version.rb
93
+ - lib/rails_presenter/presenter_helper.rb
93
94
  - MIT-LICENSE
94
95
  - Rakefile
95
- - README.rdoc
96
+ - README.md
96
97
  homepage: https://github.com/dfmonaco/rails_presenter
97
98
  licenses: []
98
99
  post_install_message:
@@ -107,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
108
  version: '0'
108
109
  segments:
109
110
  - 0
110
- hash: 610965391
111
+ hash: 644764051
111
112
  required_rubygems_version: !ruby/object:Gem::Requirement
112
113
  none: false
113
114
  requirements:
@@ -116,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
117
  version: '0'
117
118
  segments:
118
119
  - 0
119
- hash: 610965391
120
+ hash: 644764051
120
121
  requirements: []
121
122
  rubyforge_project:
122
123
  rubygems_version: 1.8.25
data/README.rdoc DELETED
@@ -1,3 +0,0 @@
1
- = RailsPresenter
2
-
3
- This project rocks and uses MIT-LICENSE.
@@ -1,180 +0,0 @@
1
- require 'delegate'
2
-
3
- class Presenter < SimpleDelegator
4
- include PresenterHelper
5
-
6
- @@nil_formatter = '----'
7
-
8
- class << self
9
- def location(*args)
10
- define_method(:self_location, ->(location=nil) do
11
- location ||= args.map do |p|
12
- p = p.to_s
13
- if p.delete! "@"
14
- public_send("get_#{p}")
15
- else
16
- p
17
- end
18
- end
19
-
20
- super(location)
21
- end)
22
- end
23
-
24
- def present(*args, &block)
25
- module_name = "#{name}Associations"
26
-
27
- unless const_defined? module_name
28
- include const_set(module_name, Module.new)
29
- end
30
-
31
- associations_module = const_get(module_name)
32
-
33
- block ||= proc { self }
34
-
35
- associations_module.module_eval do
36
- args.each do |assoc_name|
37
- define_method(assoc_name) do
38
- instance_variable_get("@#{assoc_name}") ||
39
- begin
40
- association = if super().is_a?(Array) && super().respond_to?(:scoped)
41
- super().scoped
42
- else
43
- super()
44
- end
45
- instance_variable_set("@#{assoc_name}", present(association.instance_eval(&block)))
46
- end
47
- end
48
- end
49
- end
50
- end
51
-
52
-
53
- def format(*attrs)
54
- formatter = attrs.pop.values.first
55
-
56
- module_name = formatter.to_s.camelize
57
-
58
- unless const_defined? module_name
59
- include const_set(module_name, Module.new)
60
- end
61
-
62
- formatter_module = const_get(module_name)
63
-
64
- formatter_module.module_eval do
65
- attrs.each do |attr|
66
- define_method(attr) do
67
- h.public_send(formatter, super())
68
- end
69
- end
70
- end
71
- end
72
-
73
- def inherited(child_class)
74
- child_class.instance_eval do
75
- format_blank_attributes(*possible_blank_attributes) if based_on_active_record?
76
- end
77
- end
78
-
79
- def format_blank_attributes(*attrs)
80
- attr_module = Module.new do
81
- attrs.each do |attr|
82
- define_method(attr) do
83
- return nil_formatter if super().blank?
84
- super()
85
- end
86
- end
87
- end
88
-
89
- include const_set("BlankAttributes", attr_module)
90
- end
91
-
92
- private
93
-
94
- def base_class
95
- @base_class ||= to_s.chomp('Presenter').constantize
96
- end
97
-
98
- def based_on_active_record?
99
- base_class.ancestors.include?(ActiveRecord::Base)
100
- end
101
-
102
- def possible_blank_attributes
103
- base_class.column_names.reject do |attr|
104
- ['id', 'created_at', 'updated_at'].include?(attr) ||
105
- /_id\z/.match(attr) ||
106
- base_class.validators_on(attr).any? {|v| !(v.options[:allow_nil] || v.options[:allow_blank])}
107
- end
108
- end
109
- end
110
-
111
- def initialize(base_object, template)
112
- @template = template
113
- super(base_object)
114
- end
115
-
116
- def present(object)
117
- super(object, h)
118
- end
119
-
120
- def h
121
- @template
122
- end
123
-
124
- def o
125
- __getobj__
126
- end
127
-
128
- def to_s
129
- respond_to?(:name) ? name : super
130
- end
131
-
132
- def with_attrs(*attrs)
133
- attrs_hash = attrs.reduce({}) do |hash, attr|
134
- if attr.is_a? Array
135
- hash[attr.first]= attr.last.call(self)
136
- else
137
- hash[attr]= public_send(attr)
138
- end
139
- hash
140
- end
141
-
142
- h.render partial: 'shared/show_with_attrs', locals: {attrs_hash: attrs_hash}
143
- end
144
-
145
- def self_location(location = o)
146
- h.polymorphic_path location
147
- end
148
-
149
- def link_to_self(options={})
150
- text = options[:text] || self.to_s
151
- path = options[:path] || self_location
152
- h.link_to text, path
153
- end
154
-
155
- def nil_formatter
156
- @@nil_formatter
157
- end
158
-
159
- def method_missing(method_name, *args)
160
- case method_name.to_s
161
- when /^h_(.*)$/
162
- get_iv_from_view($1)
163
- when /^get_(.*)$/
164
- return o if o.is_a? $1.camelize.constantize
165
- get_iv_from_view($1) || o.public_send($1)
166
- else
167
- super
168
- end
169
- end
170
-
171
- private
172
- def base_object_name
173
- o.class.to_s.underscore
174
- end
175
-
176
- def get_iv_from_view(iv_name)
177
- h.instance_variable_get("@#{iv_name}")
178
- end
179
-
180
- end