view_models 2.0.1 → 3.0.0
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/.bundle/config +2 -0
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +19 -0
- data/.yardoc/checksums +13 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/Appraisals +15 -0
- data/CHANGELOG +31 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +174 -0
- data/MIT-LICENSE +20 -0
- data/README.textile +199 -0
- data/Rakefile +24 -0
- data/doc/ModulesInRenderHierarchy.html +186 -0
- data/doc/ModulesInRenderHierarchy/ClassMethods.html +188 -0
- data/doc/ViewModels.html +202 -0
- data/doc/ViewModels/Base.html +1342 -0
- data/doc/ViewModels/ContextExtractor.html +406 -0
- data/doc/ViewModels/Extensions.html +128 -0
- data/doc/ViewModels/Extensions/ModelReader.html +255 -0
- data/doc/ViewModels/Extensions/ModelReader/FilteredDelegationInstaller.html +908 -0
- data/doc/ViewModels/Extensions/ModelReader/Options.html +551 -0
- data/doc/ViewModels/Extensions/View.html +303 -0
- data/doc/ViewModels/Helpers.html +129 -0
- data/doc/ViewModels/Helpers/Mapping.html +562 -0
- data/doc/ViewModels/Helpers/Mapping/Collection.html +844 -0
- data/doc/ViewModels/Helpers/View.html +287 -0
- data/doc/ViewModels/PathStore.html +745 -0
- data/doc/ViewModels/RenderOptions.html +126 -0
- data/doc/ViewModels/RenderOptions/Base.html +1187 -0
- data/doc/ViewModels/RenderOptions/Partial.html +231 -0
- data/doc/ViewModels/RenderOptions/Template.html +231 -0
- data/doc/ViewModels/View.html +414 -0
- data/doc/ViewModelsGenerator.html +410 -0
- data/doc/_index.html +317 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +328 -0
- data/doc/file.README.html +113 -0
- data/doc/file_list.html +55 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +113 -0
- data/doc/js/app.js +214 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +628 -0
- data/doc/top-level-namespace.html +114 -0
- data/feature_support/testapp/app/controllers/heroes_controller.rb +6 -0
- data/feature_support/testapp/app/controllers/users_controller.rb +6 -0
- data/feature_support/testapp/app/helpers/application_helper.rb +8 -0
- data/feature_support/testapp/app/models/hero.rb +8 -0
- data/feature_support/testapp/app/models/user.rb +3 -0
- data/feature_support/testapp/app/view_models/hero.rb +8 -0
- data/feature_support/testapp/app/view_models/test.rb +8 -0
- data/feature_support/testapp/app/view_models/user.rb +14 -0
- data/feature_support/testapp/app/views/heroes/show.html.slim +6 -0
- data/feature_support/testapp/app/views/users/_box.html.slim +8 -0
- data/feature_support/testapp/app/views/users/show.html.slim +6 -0
- data/feature_support/testapp/config/application.rb +64 -0
- data/feature_support/testapp/config/cucumber.yml +8 -0
- data/feature_support/testapp/config/database.yml +28 -0
- data/feature_support/testapp/config/environments/cucumber.rb +11 -0
- data/feature_support/testapp/config/environments/test.rb +27 -0
- data/feature_support/testapp/config/routes.rb +4 -0
- data/feature_support/testapp/db/migrate/1_create_users.rb +13 -0
- data/feature_support/testapp/features/inheritance.feature +16 -0
- data/feature_support/testapp/features/step_definitions/testapp_steps.rb +16 -0
- data/feature_support/testapp/features/support/env.rb +13 -0
- data/feature_support/testapp/features/users.feature +15 -0
- data/feature_support/testapp/lib/tasks/cucumber.rake +31 -0
- data/feature_support/testapp/spec/factories/heroes.rb +7 -0
- data/feature_support/testapp/spec/factories/users.rb +7 -0
- data/features/rails_integration.feature +21 -0
- data/features/step_definitions/rails_steps.rb +112 -0
- data/features/support/env.rb +6 -0
- data/gemfiles/3.0.Gemfile +13 -0
- data/gemfiles/3.1.Gemfile +15 -0
- data/gemfiles/3.2.gemfile +15 -0
- data/lib/rails/generators/view_models/USAGE +6 -0
- data/lib/rails/generators/view_models/templates/views/_collection.html.erb +6 -0
- data/lib/{rails2/generators/view_models/templates/views/view_models/collection → rails/generators/view_models/templates/views}/_collection.html.haml +1 -2
- data/lib/rails/generators/view_models/templates/views/_collection.html.slim +6 -0
- data/lib/{rails2/generators/view_models/templates/views/_empty.html.haml → rails/generators/view_models/templates/views/_empty.html.erb} +0 -0
- data/lib/rails/generators/view_models/templates/views/_empty.html.haml +0 -0
- data/lib/rails/generators/view_models/templates/views/_empty.html.slim +0 -0
- data/lib/rails/generators/view_models/templates/views/_list.html.erb +6 -0
- data/lib/rails/generators/view_models/templates/views/_list.html.haml +4 -0
- data/lib/rails/generators/view_models/templates/views/_list.html.slim +5 -0
- data/lib/rails/generators/view_models/templates/views/_pagination.html.erb +18 -0
- data/lib/{rails2/generators/view_models/templates/views/view_models/collection → rails/generators/view_models/templates/views}/_pagination.html.haml +2 -2
- data/lib/rails/generators/view_models/templates/views/_pagination.html.slim +12 -0
- data/lib/rails/generators/view_models/templates/views/_table.html.erb +10 -0
- data/lib/{rails2/generators/view_models/templates/views/view_models/collection → rails/generators/view_models/templates/views}/_table.html.haml +0 -0
- data/lib/rails/generators/view_models/templates/views/_table.html.slim +5 -0
- data/lib/rails/generators/view_models/view_models_generator.rb +57 -0
- data/lib/view_models.rb +15 -5
- data/lib/{shared/lib/view_models → view_models}/base.rb +148 -37
- data/lib/{shared/lib/view_models → view_models}/context_extractor.rb +6 -2
- data/lib/{shared/lib/view_models → view_models}/extensions/model_reader.rb +27 -13
- data/lib/{rails2/lib → view_models}/extensions/view.rb +6 -1
- data/lib/view_models/helpers/collection.rb +113 -0
- data/lib/{shared/lib/view_models → view_models}/helpers/mapping.rb +12 -15
- data/lib/{rails2/lib → view_models}/helpers/view.rb +5 -1
- data/lib/{shared/lib/view_models → view_models}/path_store.rb +6 -1
- data/lib/{shared/lib/view_models → view_models}/render_options.rb +19 -4
- data/lib/view_models/version.rb +5 -0
- data/lib/{rails2/lib/view_models → view_models}/view.rb +7 -6
- data/spec/{rails2/lib → lib}/view_models/base_spec.rb +38 -5
- data/spec/{rails2/lib → lib/view_models}/extensions/model_reader_spec.rb +4 -4
- data/spec/{shared/lib → lib/view_models}/helpers/collection_spec.rb +21 -1
- data/spec/{shared/lib → lib/view_models}/helpers/mapping_spec.rb +6 -5
- data/spec/{rails2/lib → lib/view_models}/helpers/view_spec.rb +1 -1
- data/spec/lib/view_models/view_spec.rb +42 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/spec_helper_extensions.rb +13 -0
- data/view_models.gemspec +36 -0
- metadata +411 -142
- data/lib/init.rb +0 -1
- data/lib/padrino/README.textile +0 -3
- data/lib/padrino/init.rb +0 -10
- data/lib/padrino/lib/helpers/collection.rb +0 -27
- data/lib/padrino/lib/padrino/view_models.rb +0 -19
- data/lib/padrino/lib/view_models/base.rb +0 -65
- data/lib/rails2/README.textile +0 -3
- data/lib/rails2/TODO.textile +0 -5
- data/lib/rails2/generators/view_models/USAGE +0 -6
- data/lib/rails2/generators/view_models/templates/README +0 -1
- data/lib/rails2/generators/view_models/templates/spec/view_model_spec.rb +0 -7
- data/lib/rails2/generators/view_models/templates/view_models/view_model.rb +0 -5
- data/lib/rails2/generators/view_models/templates/views/view_models/collection/_collection.html.erb +0 -1
- data/lib/rails2/generators/view_models/templates/views/view_models/collection/_collection.text.erb +0 -6
- data/lib/rails2/generators/view_models/templates/views/view_models/collection/_list.html.erb +0 -1
- data/lib/rails2/generators/view_models/templates/views/view_models/collection/_list.text.erb +0 -6
- data/lib/rails2/generators/view_models/templates/views/view_models/collection/_pagination.text.erb +0 -3
- data/lib/rails2/generators/view_models/templates/views/view_models/collection/_table.text.erb +0 -10
- data/lib/rails2/generators/view_models/view_models_generator.rb +0 -47
- data/lib/rails2/init.rb +0 -18
- data/lib/rails2/lib/experimental/README.textile +0 -32
- data/lib/rails2/lib/experimental/modules_in_render_hierarchy.rb +0 -21
- data/lib/rails2/lib/helpers/collection.rb +0 -27
- data/lib/rails2/lib/view_models.rb +0 -1
- data/lib/rails2/lib/view_models/base.rb +0 -99
- data/lib/shared/README.textile +0 -3
- data/lib/shared/init.rb +0 -11
- data/lib/shared/lib/view_models.rb +0 -4
- data/lib/shared/lib/view_models/extensions/active_record.rb +0 -27
- data/lib/shared/lib/view_models/helpers/collection.rb +0 -110
- data/spec/padrino/integration/integration_spec.rb +0 -287
- data/spec/padrino/lib/helpers/collection_spec.rb +0 -30
- data/spec/rails2/integration/integration_spec.rb +0 -279
- data/spec/rails2/lib/extensions/active_record_spec.rb +0 -31
- data/spec/rails2/lib/helpers/collection_spec.rb +0 -30
- data/spec/rails2/lib/view_models/view_spec.rb +0 -12
|
@@ -1,59 +1,115 @@
|
|
|
1
1
|
# Base Module for ViewModels.
|
|
2
|
+
# @author Florian Hanke
|
|
3
|
+
# @author Kaspar Schiess
|
|
4
|
+
# @author Niko Dittmann
|
|
5
|
+
# @author Beat Richartz
|
|
6
|
+
# @version 3.0.0
|
|
7
|
+
# @since 1.0.0
|
|
2
8
|
#
|
|
3
|
-
module ViewModels
|
|
4
|
-
|
|
9
|
+
module ViewModels
|
|
10
|
+
|
|
5
11
|
# Gets raised when render_as, render_the, or render_template cannot
|
|
6
12
|
# find the named template, not even in the hierarchy.
|
|
7
13
|
#
|
|
8
|
-
|
|
14
|
+
MissingTemplateError = Class.new(StandardError)
|
|
9
15
|
|
|
10
16
|
# Base class from which all view_models inherit.
|
|
17
|
+
# @example Create Your first View Model
|
|
18
|
+
# class ViewModels::MyViewModel < ViewModels::Base
|
|
19
|
+
# # your code
|
|
20
|
+
# end
|
|
11
21
|
#
|
|
12
22
|
class Base
|
|
13
23
|
|
|
24
|
+
# Make the rails methods helper and helper_method available in view models
|
|
25
|
+
#
|
|
26
|
+
include AbstractController::Helpers
|
|
27
|
+
|
|
14
28
|
# Create a view_model. To create a view_model, you need to have a model (to present) and a context.
|
|
15
29
|
# The context is usually a view, a controller, or an app, but doesn't need to be.
|
|
16
30
|
#
|
|
17
|
-
#
|
|
31
|
+
# The @context = @controller is really only needed because some Rails helpers access @controller directly.
|
|
32
|
+
# It's really bad.
|
|
33
|
+
# @param [ActiveRecord] model The model which the view model is based upon
|
|
34
|
+
# @param [ActionView, ActionController, Rails::Application] app_or_controller_or_view The context of the view model
|
|
35
|
+
# @example Initialize a view model without the mapping helper
|
|
36
|
+
# ViewModel::YourModel.new(@model, @context)
|
|
18
37
|
#
|
|
19
38
|
def initialize model, app_or_controller_or_view
|
|
20
|
-
@model
|
|
21
|
-
@context = ContextExtractor.new(app_or_controller_or_view).extract
|
|
39
|
+
@model = model
|
|
40
|
+
@context = @controller = ContextExtractor.new(app_or_controller_or_view).extract
|
|
22
41
|
end
|
|
23
42
|
|
|
24
43
|
class << self
|
|
25
44
|
|
|
26
|
-
#
|
|
27
|
-
# template inheritance, to remember specific
|
|
28
|
-
# [path, name, format] tuples, pointing to a template path,
|
|
29
|
-
# so the view models don't have to traverse the inheritance chain always.
|
|
45
|
+
# The path store accessor, storing the view paths for the view model
|
|
30
46
|
#
|
|
31
47
|
attr_accessor :path_store
|
|
48
|
+
|
|
49
|
+
# Installs a path store, a specific store for template inheritance, to remember specific
|
|
50
|
+
# [path, name, format] tuples, pointing to a template path
|
|
51
|
+
# so the view models don't have to always traverse the inheritance chain.
|
|
52
|
+
# @param [ViewModel] subclass The subclass of the view model
|
|
53
|
+
#
|
|
32
54
|
def inherited subclass
|
|
33
55
|
ViewModels::PathStore.install_in subclass
|
|
34
56
|
super
|
|
35
57
|
end
|
|
36
58
|
|
|
37
59
|
# Delegates method calls to the context.
|
|
38
|
-
#
|
|
39
|
-
# Examples:
|
|
40
|
-
# context_method :current_user
|
|
41
|
-
# context_method :current_user, :current_profile # multiple methods to be delegated
|
|
42
|
-
#
|
|
43
60
|
# In the view_model:
|
|
44
61
|
# self.current_user
|
|
45
62
|
# will call
|
|
46
63
|
# context.current_user
|
|
47
64
|
#
|
|
65
|
+
# @param [Symbol] methods A list of symbols representing methods to be delegated
|
|
66
|
+
# @example delegate one method to the context
|
|
67
|
+
# context_method :current_user
|
|
68
|
+
# @example delegate multiple methods to the context
|
|
69
|
+
# context_method :current_user, :current_profile
|
|
70
|
+
#
|
|
48
71
|
def context_method *methods
|
|
49
72
|
delegate *methods << { :to => :context }
|
|
50
73
|
end
|
|
51
74
|
|
|
75
|
+
# Alias the context_method to the rails-centric controller_method.
|
|
76
|
+
#
|
|
77
|
+
alias controller_method context_method
|
|
78
|
+
|
|
52
79
|
# Installs the model_reader Method for filtered
|
|
53
80
|
# model method delegation.
|
|
54
81
|
#
|
|
55
82
|
include Extensions::ModelReader
|
|
56
83
|
|
|
84
|
+
unless instance_methods.include?('old_add_template_helper')
|
|
85
|
+
alias old_add_template_helper add_template_helper
|
|
86
|
+
|
|
87
|
+
# Wrapper for add_template_helper in ActionController::Helpers, also
|
|
88
|
+
# includes given helper in the view_model
|
|
89
|
+
#
|
|
90
|
+
# @todo extract into module
|
|
91
|
+
# @param [Module] helper_module the helper to be added
|
|
92
|
+
#
|
|
93
|
+
def add_template_helper helper_module
|
|
94
|
+
include helper_module
|
|
95
|
+
old_add_template_helper helper_module
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Sets the view format and tries to render the given options.
|
|
100
|
+
# @param [ActionView] renderer The view renderer
|
|
101
|
+
# @param [Hash] options The options to pass to the view
|
|
102
|
+
# @option options [Hash] :locals The locals to pass to the view
|
|
103
|
+
# @note Also caches [path, name, format] => template path.
|
|
104
|
+
#
|
|
105
|
+
def render renderer, options
|
|
106
|
+
options.format! renderer
|
|
107
|
+
path_store.cached options do
|
|
108
|
+
options.file = template_path renderer, options
|
|
109
|
+
renderer.render_with options
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
57
113
|
protected
|
|
58
114
|
|
|
59
115
|
# Hierarchical rendering.
|
|
@@ -61,27 +117,31 @@ module ViewModels
|
|
|
61
117
|
|
|
62
118
|
# Returns the next view model class in the render hierarchy.
|
|
63
119
|
#
|
|
64
|
-
#
|
|
120
|
+
# @note Just returns the superclass.
|
|
65
121
|
#
|
|
66
|
-
#
|
|
122
|
+
# @todo Think about raising the MissingTemplateError here.
|
|
123
|
+
# @return The superclass of the view model, which ends with ViewModel::Base
|
|
67
124
|
#
|
|
68
125
|
def next_in_render_hierarchy
|
|
69
126
|
superclass
|
|
70
127
|
end
|
|
71
|
-
|
|
128
|
+
|
|
129
|
+
# Raises the fitting template error with the given message
|
|
130
|
+
# @param [String,Symbol] message The message with which the template error should be raised
|
|
131
|
+
# @raise [MissingTemplateError] A template error indicating that the template is missing
|
|
72
132
|
#
|
|
73
133
|
def raise_template_error_with message
|
|
74
134
|
raise MissingTemplateError.new("No template #{message} found.")
|
|
75
135
|
end
|
|
136
|
+
|
|
76
137
|
# Check if the view lookup inheritance chain has ended.
|
|
77
|
-
#
|
|
78
138
|
# Raises a MissingTemplateError if yes.
|
|
139
|
+
# @return wether the current class is ViewModel::Base and therefore at the end of the inheritance chain
|
|
79
140
|
#
|
|
80
141
|
def inheritance_chain_ends?
|
|
81
142
|
self == ViewModels::Base
|
|
82
143
|
end
|
|
83
144
|
|
|
84
|
-
|
|
85
145
|
# Template finding
|
|
86
146
|
#
|
|
87
147
|
|
|
@@ -91,27 +151,36 @@ module ViewModels
|
|
|
91
151
|
#
|
|
92
152
|
# Raises a MissingTemplateError if none is found during
|
|
93
153
|
# inheritance chain traversal.
|
|
154
|
+
# @param [ActionView] renderer The view renderer
|
|
155
|
+
# @param [Hash] options The options to pass to the template path
|
|
94
156
|
#
|
|
95
|
-
def template_path renderer, options
|
|
157
|
+
def template_path renderer, options
|
|
96
158
|
raise_template_error_with options.error_message if inheritance_chain_ends?
|
|
97
159
|
|
|
98
160
|
template_path_from(renderer, options) || self.next_in_render_hierarchy.template_path(renderer, options)
|
|
99
161
|
end
|
|
100
|
-
|
|
101
|
-
#
|
|
102
|
-
|
|
103
|
-
#
|
|
162
|
+
|
|
163
|
+
# Accesses the view to find a suitable template path.
|
|
164
|
+
# @param [ActionView] renderer The view renderer
|
|
165
|
+
# @param [Hash] options The options to pass to the view
|
|
104
166
|
#
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
167
|
+
def template_path_from renderer, options
|
|
168
|
+
template = renderer.find_template tentative_template_path(options)
|
|
169
|
+
|
|
170
|
+
template && template.virtual_path.to_s
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# @return render path either a stored path or a newly generated one.
|
|
174
|
+
# @note If nothing or nil is passed, the store is ignored.
|
|
175
|
+
# @param [Hash] options The view render options
|
|
108
176
|
#
|
|
109
177
|
def tentative_template_path options
|
|
110
178
|
path_store[options.path_key] || generate_template_path_from(options)
|
|
111
179
|
end
|
|
112
180
|
|
|
113
|
-
#
|
|
114
|
-
#
|
|
181
|
+
# @return the root of this view_models views with the template name appended.
|
|
182
|
+
# @example Returning a specific path
|
|
183
|
+
# 'some/specific/path/to/template'
|
|
115
184
|
#
|
|
116
185
|
def generate_template_path_from options
|
|
117
186
|
File.join generate_path_from(options), options.name
|
|
@@ -130,19 +199,47 @@ module ViewModels
|
|
|
130
199
|
# If the class is named
|
|
131
200
|
# ViewModels::Models::Book
|
|
132
201
|
# this method will yield
|
|
133
|
-
#
|
|
202
|
+
# models/book
|
|
134
203
|
#
|
|
135
204
|
# Note: Remembers the result since it is dependent on the Class name only.
|
|
136
205
|
#
|
|
137
206
|
def view_model_path
|
|
138
|
-
@view_model_path
|
|
207
|
+
@view_model_path ||= self.name.gsub(/^ViewModels::|(\w+)(::)?/) { $1.underscore.pluralize + ($2 ? '/' : '').to_s if $1 }
|
|
139
208
|
end
|
|
140
209
|
|
|
141
210
|
end
|
|
142
|
-
|
|
211
|
+
|
|
143
212
|
# Delegate context methods.
|
|
144
213
|
#
|
|
145
|
-
context_method :logger
|
|
214
|
+
context_method :logger, :form_authenticity_token, :protect_against_forgery?, :request_forgery_protection_token, :config, :cookies, :flash, :default_url_options
|
|
215
|
+
|
|
216
|
+
# id and param are simply delegated to the model.
|
|
217
|
+
#
|
|
218
|
+
# This makes it possible to use the view_model
|
|
219
|
+
# for e.g. url generation:
|
|
220
|
+
# * edit_user_path(view_model)
|
|
221
|
+
#
|
|
222
|
+
delegate :id, :to_param, :to => :model
|
|
223
|
+
|
|
224
|
+
# Delegate dom id to the action controller record identifier.
|
|
225
|
+
#
|
|
226
|
+
def dom_id *args
|
|
227
|
+
if args.present?
|
|
228
|
+
context.dom_id *args
|
|
229
|
+
else
|
|
230
|
+
ActionController::RecordIdentifier.dom_id model
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Make all the dynamically generated routes (restful routes etc.)
|
|
235
|
+
# available in the view_model
|
|
236
|
+
#
|
|
237
|
+
Rails.application.routes.install_helpers self if Rails.application
|
|
238
|
+
|
|
239
|
+
# include these helpers by default
|
|
240
|
+
#
|
|
241
|
+
helper Helpers::View
|
|
242
|
+
helper Helpers::Mapping
|
|
146
243
|
|
|
147
244
|
# Renders the given partial in the view_model's view root in the format given.
|
|
148
245
|
#
|
|
@@ -199,6 +296,22 @@ module ViewModels
|
|
|
199
296
|
#
|
|
200
297
|
attr_reader :model, :context
|
|
201
298
|
|
|
299
|
+
# CaptureHelper needs this.
|
|
300
|
+
#
|
|
301
|
+
attr_accessor :output_buffer
|
|
302
|
+
|
|
303
|
+
# alias the context as controller
|
|
304
|
+
#
|
|
305
|
+
alias controller context
|
|
306
|
+
|
|
307
|
+
# Returns a view instance for render_xxx.
|
|
308
|
+
#
|
|
309
|
+
# @todo Try getting a view instance from the controller.
|
|
310
|
+
#
|
|
311
|
+
def renderer
|
|
312
|
+
View.new context, self._helpers
|
|
313
|
+
end
|
|
314
|
+
|
|
202
315
|
# Internal render method that uses the options to get a view instance
|
|
203
316
|
# and then referring to its class for rendering.
|
|
204
317
|
#
|
|
@@ -212,9 +325,7 @@ module ViewModels
|
|
|
212
325
|
|
|
213
326
|
# Determines what format to use for rendering.
|
|
214
327
|
#
|
|
215
|
-
#
|
|
216
|
-
# if none is explicitly set in the options.
|
|
217
|
-
# This propagates the format to further render_xxx calls.
|
|
328
|
+
# @note Uses the template format of the view model instance if none is explicitly set in the options. This propagates the format to further render_xxx calls.
|
|
218
329
|
#
|
|
219
330
|
def determine_and_set_format options
|
|
220
331
|
options.format = @template_format = options.format || @template_format
|
|
@@ -4,17 +4,21 @@ module ViewModels
|
|
|
4
4
|
|
|
5
5
|
# Extracts controllers for a living from unsuspecting views.
|
|
6
6
|
#
|
|
7
|
-
# Note: This is actually only needed in Rails. In Padrino, the context is always the app.
|
|
8
|
-
#
|
|
9
7
|
class ContextExtractor
|
|
10
8
|
|
|
9
|
+
# The context
|
|
10
|
+
#
|
|
11
11
|
attr_reader :context
|
|
12
12
|
|
|
13
|
+
# Initialize the Context extractor
|
|
14
|
+
# @param [ActionController, ActionMailer, ActionView] context Some render context
|
|
15
|
+
#
|
|
13
16
|
def initialize context
|
|
14
17
|
@context = context
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
# Extracts a controller from the context.
|
|
21
|
+
# @return [ActionController] an instance of action controller
|
|
18
22
|
#
|
|
19
23
|
def extract
|
|
20
24
|
context = self.context
|
|
@@ -2,15 +2,23 @@
|
|
|
2
2
|
#
|
|
3
3
|
#
|
|
4
4
|
module ViewModels
|
|
5
|
+
|
|
6
|
+
# Extensions of the View Model Class
|
|
7
|
+
#
|
|
5
8
|
module Extensions
|
|
9
|
+
|
|
10
|
+
# Model Reader extension. Allows to define model readers on view models, accessing attributes and methods
|
|
11
|
+
# on models
|
|
12
|
+
#
|
|
6
13
|
module ModelReader
|
|
7
14
|
|
|
8
15
|
# Define a reader for a model attribute. Acts as a filtered delegation to the model.
|
|
9
16
|
#
|
|
10
17
|
# You may specify a :filter_through option that is either a symbol or an array of symbols. The return value
|
|
11
|
-
# from the model will be filtered through the functions (arity 1) and then passed back to the receiver.
|
|
18
|
+
# from the model will be filtered through the functions (arity 1) and then passed back to the receiver.
|
|
19
|
+
# @param [Symbol, Hash] attributes_and_options The attributes and options for the model reader
|
|
12
20
|
#
|
|
13
|
-
#
|
|
21
|
+
# @example install different model readers
|
|
14
22
|
#
|
|
15
23
|
# model_reader :foobar # same as delegate :foobar, :to => :model
|
|
16
24
|
# model_reader :foobar, :filter_through => :h # html escape foobar
|
|
@@ -32,6 +40,7 @@ module ViewModels
|
|
|
32
40
|
end
|
|
33
41
|
|
|
34
42
|
# Extract filter_through options from the options hash if there are any.
|
|
43
|
+
# @param [Hash] options the options to split
|
|
35
44
|
#
|
|
36
45
|
def split options
|
|
37
46
|
@filters = if options.last.kind_of?(Hash)
|
|
@@ -42,6 +51,9 @@ module ViewModels
|
|
|
42
51
|
@attributes = options
|
|
43
52
|
end
|
|
44
53
|
|
|
54
|
+
# Render the options to an array
|
|
55
|
+
# @return [Array] The attributes and the filters in this order
|
|
56
|
+
#
|
|
45
57
|
def to_a
|
|
46
58
|
[attributes, filters]
|
|
47
59
|
end
|
|
@@ -53,13 +65,19 @@ module ViewModels
|
|
|
53
65
|
#
|
|
54
66
|
class FilteredDelegationInstaller
|
|
55
67
|
|
|
68
|
+
# The attributes target, attributes, filters
|
|
69
|
+
#
|
|
56
70
|
attr_reader :target, :attributes, :filters
|
|
57
71
|
|
|
72
|
+
# Initialize a new filtered delegation
|
|
73
|
+
# @param [ViewModel] target the target to install the filtered delegation in
|
|
74
|
+
# @param [ModelReader::Options] options The options for the filtered delegation
|
|
75
|
+
#
|
|
58
76
|
def initialize target, options
|
|
59
77
|
@target, @attributes, @filters = target, *options
|
|
60
78
|
end
|
|
61
79
|
|
|
62
|
-
# Install
|
|
80
|
+
# Install a reader for each attribute
|
|
63
81
|
#
|
|
64
82
|
def install
|
|
65
83
|
attributes.each { |attribute| install_reader(attribute) }
|
|
@@ -67,10 +85,8 @@ module ViewModels
|
|
|
67
85
|
|
|
68
86
|
# Install a reader for the given name with the given filters.
|
|
69
87
|
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
# #
|
|
73
|
-
# * install_reader :attribute
|
|
88
|
+
# @example Installs a reader for model.attribute
|
|
89
|
+
# install_reader :attribute
|
|
74
90
|
#
|
|
75
91
|
def install_reader attribute
|
|
76
92
|
target.class_eval reader_definition_for(attribute)
|
|
@@ -79,7 +95,7 @@ module ViewModels
|
|
|
79
95
|
# Defines a reader for the given model attribute and filtering
|
|
80
96
|
# through the given filters.
|
|
81
97
|
#
|
|
82
|
-
#
|
|
98
|
+
# @note The filters are applied from last to first element.
|
|
83
99
|
#
|
|
84
100
|
def reader_definition_for attribute
|
|
85
101
|
"def #{attribute}; #{filtered_left_parentheses}model.#{attribute}#{right_parentheses}; end"
|
|
@@ -88,7 +104,7 @@ module ViewModels
|
|
|
88
104
|
# Combines left parentheses and filters.
|
|
89
105
|
#
|
|
90
106
|
def filtered_left_parentheses
|
|
91
|
-
filters.zip(left_parentheses).
|
|
107
|
+
filters.zip(left_parentheses).join
|
|
92
108
|
end
|
|
93
109
|
|
|
94
110
|
# Generates the needed amount of parentheses to match the left parentheses.
|
|
@@ -99,10 +115,8 @@ module ViewModels
|
|
|
99
115
|
|
|
100
116
|
# Generates an array of left parentheses with
|
|
101
117
|
# length <amount of filters>
|
|
102
|
-
#
|
|
103
|
-
# #
|
|
104
|
-
# #
|
|
105
|
-
# left_parentheses # => ['(', '(', '(', '(']
|
|
118
|
+
# @example for 4 Filters
|
|
119
|
+
# left_parentheses # => ['(', '(', '(', '(']
|
|
106
120
|
#
|
|
107
121
|
def left_parentheses
|
|
108
122
|
['('] * filters.size
|
|
@@ -5,15 +5,20 @@
|
|
|
5
5
|
#
|
|
6
6
|
module ViewModels
|
|
7
7
|
module Extensions
|
|
8
|
+
|
|
9
|
+
# Extensions for the View instance
|
|
10
|
+
#
|
|
8
11
|
module View
|
|
9
12
|
|
|
10
|
-
#
|
|
13
|
+
# Renders the template with the given options
|
|
14
|
+
# @param [RenderOptions::Base] options The options to render with
|
|
11
15
|
#
|
|
12
16
|
def render_with options
|
|
13
17
|
render options.to_render_options
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
# Finds the template in the view paths at the given path, with its format.
|
|
21
|
+
# @param [String] path the template path
|
|
17
22
|
#
|
|
18
23
|
def find_template path
|
|
19
24
|
view_paths.find_template path, template_format rescue nil
|