view_models 1.5.6 → 1.5.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -1,22 +1,16 @@
1
- h1. ViewModels for Rails
1
+ h1. ViewModels
2
2
 
3
- h2. Previous contributors
3
+ A view model/representer solution for Rails.
4
4
 
5
- Code:
5
+ h2. Features
6
6
 
7
- "Kaspar":http://github.com/kschiess @http://github.com/kschiess@, for the first, and foundation-laying version.
8
-
9
- "Niko":http://github.com/niko @http://github.com/niko@, for handling collections and better Helpers handling.
10
-
11
- "Andi":http://github.com/andi @http://github.com/andi@, for refactoring it into a cleaner structure.
12
-
13
- Inspiration:
14
-
15
- "Severin":http://github.com/severin @http://github.com/severin@, for bits and pieces here and there.
16
-
17
- "rainhead":http://github.com/rainhead @http://github.com/rainhead@, for the idea to subclass ActionView::Base.
18
-
19
- Important note: These guys rock! :)
7
+ * Polymorph view model objects that correspond to model objects.
8
+ * View model specific templates.
9
+ * Hierarchical Template Rendering: Allows generalized templates for a class tree of view models.
10
+ * Helper methods directly on the view models.
11
+ * No view related code in the models.
12
+ * A clean API for use in Rails.
13
+ * 100% rcov coverage, nice metrics, gallons of blood and sweat by excellent contributors.
20
14
 
21
15
  h2. Installation
22
16
 
@@ -24,7 +18,7 @@ h3. Rails Plugin
24
18
 
25
19
  @script/plugin install git://github.com/floere/view_models.git@
26
20
 
27
- h3. Gem for use in Rails
21
+ h3. Gem (for use in Rails)
28
22
 
29
23
  @gem install view_models@
30
24
 
@@ -34,221 +28,13 @@ and then adding the line
34
28
 
35
29
  in your environment.rb.
36
30
 
37
- h2. Description
38
-
39
- A possible view_model solution, i.e. no view logic in model code.
40
-
41
- h2. Feedback
42
-
43
- Ask/Write florian.hanke@gmail.com if you have questions/feedback, thanks! :)
44
- Fork if you have improvements. Send me a pull request, it is much appreciated.
45
-
46
- h2. Problem
47
-
48
- Display Methods are not well placed either in
49
- * models: Violation of the MVC principle.
50
- * helpers: No Polymorphism.
51
-
52
- h2. Solution
53
-
54
- A thin proxy layer over a model, with access to the controller, used by the view or controller.
55
-
56
- @The view@ -> to @the view model@ which in turn -> @the model@ and -> @the controller@
57
-
58
- h2. Examples & What you can do
59
-
60
- h3. A quick one
61
-
62
- In the view:
63
- <pre><code>user = view_model_for @user
64
- %h1= "You, #{user.full_name}, the user"
65
- %h2 This is how you look as a search result:
66
- = user.render_as :result
67
- %h2 This is how you look as a Vcard:
68
- = user.render_as :vcard</code></pre>
69
- In the view model:
70
- <pre><code>class ViewModels::User < ViewModels::Project
71
- model_reader :first_name, :last_name
72
- def full_name
73
- "#{last_name}, #{first_name}"
74
- end
75
- end</code></pre>
76
- In the model:
77
- <pre><code>class User < ActiveRecord::Base
78
- end</code></pre>
79
- Also, there are two partials in @app/views/view_models/user/@, @_result.html.haml@ and @_vcard.html.haml@ that define how the result of @user.render_as :result@ and @user.render_as :vcard@ look. The ViewModel can be accessed inside the view by using the local variable @view_model@.
80
-
81
- h3. Getting a view_model in a view or a controller.
82
-
83
- Call view_model_for: @view_model_instance = view_model_for model_instance@
84
- By convention, uses @ViewModels::Model::Class::Name@, thus prefixing @ViewModels::@ to the model class name.
85
-
86
- Note: You can override @specific_view_model_class_for@ to change the mapping of model to class, or make it dynamic.
87
-
88
- h3. Getting a collection view model in a view.
89
-
90
- The collection view_model renders each of the given items with its view_model.
91
-
92
- Call collection_view_model_for: @collection_view_model_instance = collection_view_model_for enumerable_containing_model_instances@
93
-
94
- Rendering a list: @collection_view_model_instance.list@
95
-
96
- Rendering a collection: @collection_view_model_instance.collection@
97
-
98
- Rendering a table: @collection_view_model_instance.table@
99
-
100
- Rendering a pagination: @collection_view_model_instance.pagination@
101
- Note: Only works if the passed parameter for @collection_view_model_for@ is a @PaginationEnumeration@.
102
-
103
- Important note:
104
- As of yet it is needed to copy the templates/views/view_models/collection
105
- directory to the corresponding location in app/views/view_models/collection.
106
- This is only needed if you wish to use the collection view model.
107
- The collections are automatically copied if you use the generator.
108
-
109
- Note: Rewrite the collection templates as needed, they are rather basic.
110
-
111
- h3. Writing filtered delegate methods on the view model.
112
-
113
- Will create two delegate methods first_name and last_name that delegate to the model: @model_reader :first_name, :last_name@
114
-
115
- Will create a description delegate method that filters the model value through h: @model_reader :description, :filter_through => :h@
116
-
117
- Will create a description delegate method that filters the model value through first textilize, then h: @model_reader :description, :filter_through => [:textilize, :h]@
118
-
119
- Will create both a first_name and last_name delegate method that filters the model value through first textilize, then h: @model_reader :first_name, :last_name, :filter_through => [:textilize, :h]@
120
- Note: Filter methods can be any method on the view_model with arity 1.
121
-
122
- h3. Rendering view model templates
123
-
124
- Use @render_as(template_name, options)@.
125
-
126
- Gets a @ViewModels::Model::Class@ instance: @view_model = view_model_for Model::Class.new@
127
-
128
- Gets a @ViewModels::<model_instance.class.name>@ instance: @view_model = view_model_for model_instance@
129
-
130
- Renders the 'example' partial in view_models/model/class: @view_model.render_as :example@
131
- Note: Renders a format depending on the request. ../index.text will render example.text.erb.
132
-
133
- Renders the 'example.text.erb' partial in view_models/model/class: @view_model.render_as :example, :format => :text@
134
- Note: If the partial cannot be found, it will traverse the view model hierarchy upwards to find a partial template.
135
-
136
- Locals can be passed through as usual: @view_model.render_as :example, :format => :text, :locals => { :name => value }@
137
-
138
- h3. Rails Helpers in ViewModels
139
-
140
- Use @helper@ as you would in the controller.
141
- @helper ActionView::Helpers::UrlHelper@
142
- @helper ApplicationHelper@
143
- Note: It is helpful to create a superclass to all view models in the project with generally used helpers.
144
- We use @ViewModels::Project@ a lot, for example. See example below.
145
-
146
- h3. Controller Delegate Methods
147
-
148
- Use @controller_method(*args)@.
149
-
150
- Delegates current_user and logger on the view_model to the controller: @controller_method :current_user, :logger@
151
-
152
- h2. The Generator
153
-
154
- Generates view model class, spec, and views. Use as follows:
155
-
156
- @script/generate view_models <view model class name>@
157
- @script/generate view_models User@
158
-
159
- @script/generate view_models <view model class name> <partials for render_as, separated by space>@
160
- @script/generate view_models User compact extensive list_item table_item@
161
-
162
- h2. One Big Fat Example
163
-
164
- The following classes all have specs of course ;) But are not shown since they don't help the example.
165
-
166
- @ViewModels@ superclass for this project.
167
-
168
- We include all of Rails' helpers for the view models in this project.
169
- Also, we include the @ApplicationHelper@.
170
-
171
- We delegate @logger@ and @current_user@ calls in the view models to the active controller.
172
-
173
- <pre>
174
- <code>
175
- class ViewModels::Project < ViewModels::Base
176
-
177
- # Our ApplicationHelper.
178
- #
179
- helper ApplicationHelper
180
-
181
- # We want to be able to call view_model_for in our view_models.
182
- #
183
- helper ViewModels::Helpers::Rails
184
-
185
- # Include all common view helpers.
186
- #
187
- helper ViewModels::Helpers::View
188
-
189
- # We want to be able to use id, dom_id, to_param on the view model.
190
- #
191
- # Note: Overrides the standard dom_id method from the RecordIdentificationHelper.
192
- #
193
- include ViewModels::Extensions::ActiveRecord
194
-
195
- controller_method :logger, :current_user
196
-
197
- end
198
-
199
- # All items have a description that needs to be filtered by textilize.
200
- #
201
- class ViewModels::Item < ViewModels::Project
202
- model_reader :description, :filter_through => :textilize
203
- # Use price in the view as follows:
204
- # = view_model.price - will display e.g. 16.57 CHF, since it is filtered first through localize_currency
205
- model_reader :price, :filter_through => :localize_currency
206
-
207
- # Converts a database price tag to the users chosen value, with the users preferred currency appended.
208
- # If the user is Swiss, localize_currency will convert 10 Euros to "16.57 CHF"
209
- #
210
- def localize_currency(price_in_euros)
211
- converted_price = current_user.convert_price(price_in_euros)
212
- "#{converted_price} #{current_user.currency.to_s}"
213
- end
214
- end
215
-
216
- # This class also has partial templates in the directory
217
- # app/views/view_models/book
218
- # that are called
219
- # _cart_item.html.haml
220
- # _cart_item.text.erb
221
- #
222
- # Call view_model_for on a book in the view or controller to get this view_model.
223
- #
224
- class ViewModels::Book < ViewModels::Item
225
- model_reader :author, :title, :pages
226
- model_reader :excerpt, :filter_through => :textilize
227
-
228
- def header
229
- content_tag(:h1, "#{author} – #{title}")
230
- end
231
-
232
- def full_description
233
- content_tag(:p, "#{excerpt} #{description}", :class => 'description full')
234
- end
235
- end
31
+ h2. Links Galore!
236
32
 
237
- # This class also has partial templates in the directory
238
- # app/views/view_models/toy
239
- # that are called
240
- # _cart_item.html.haml
241
- # _cart_item.text.erb
242
- #
243
- # Call view_model_for on a toy in the view or controller to get this view_model.
244
- #
245
- class ViewModels::Toy < ViewModels::Item
246
- model_reader :starting_age, :small_dangerous_parts
247
-
248
- def obligatory_parental_warning
249
- "Warning, this toy can only be used by kids ages #{starting_age} and up. Your department of health. Thank you."
250
- end
251
-
252
- end
253
- </code>
254
- </pre>
33
+ "Usage, Examples, In-depth Infos [Wiki]":http://wiki.github.com/floere/view_models/
34
+ "Reference [RDoc]":http://rdoc.info/projects/floere/view_models
35
+ "Gem [RubyGems.org]":http://rubygems.org/gems/view_models
36
+ "Mailing List":http://groups.google.com/group/view_models/topics
37
+ "Bug Tracker":http://github.com/floere/view_models/issues
38
+ "Metrics":http://getcaliper.com/caliper/project?repo=git://github.com/floere/view_models.git
39
+ "Source [Github]":http://github.com/floere/view_models
40
+ "Homepage":http://floere.github.com/view_models/
data/TODO.textile CHANGED
@@ -1,4 +1,5 @@
1
1
  h1. Next up
2
2
 
3
- * Explore possibilities to include Modules in hierarchical rendering.
4
- * Encapsule the rather bloated hierarchical rendering in a HierarchicalRendering object that mediates the whole rendering process.
3
+ * Encapsule the rather bloated hierarchical rendering in a HierarchicalRendering object that mediates the whole rendering process.
4
+
5
+ --* Explore possibilities to include Modules in hierarchical rendering.--
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 5
3
- :patch: 6
3
+ :patch: 7
4
4
  :major: 1
@@ -1,10 +1,10 @@
1
1
  module ModulesInRenderHierarchy
2
-
2
+
3
3
  def self.included klass
4
4
  klass.extend ClassMethods
5
5
  klass.metaclass.alias_method_chain :include, :superclass_override
6
6
  end
7
-
7
+
8
8
  module ClassMethods
9
9
  def include_with_superclass_override mod
10
10
  original_superclass = superclass
@@ -17,5 +17,5 @@ module ModulesInRenderHierarchy
17
17
  end
18
18
  end
19
19
  end
20
-
20
+
21
21
  end
@@ -4,7 +4,7 @@ module ViewModels
4
4
  #
5
5
  module RenderOptions
6
6
 
7
- # Hold a number of options for rendering.
7
+ # Base class for Partial and Template.
8
8
  #
9
9
  class Base
10
10
 
@@ -57,35 +57,43 @@ module ViewModels
57
57
  template_name.to_s.include?('/') ? specific_path(template_name) : incomplete_path(template_name)
58
58
  end
59
59
 
60
- #
61
- #
62
- def deoptionize template_name
63
- if template_name.kind_of?(Hash)
64
- @options.merge! template_name
65
- @options.delete :partial
66
- else
67
- template_name
68
- end
69
- end
70
-
71
- #
60
+ # Specific path is a specifically named view path, with slashes.
72
61
  #
73
62
  def specific_path name
74
63
  self.path = File.dirname name
75
64
  self.name_with_prefix = File.basename name
76
65
  end
77
66
 
78
- #
67
+ # Incomplete path is a view path without slashes. The view models will
68
+ # try to find out where to take the template from.
79
69
  #
80
70
  def incomplete_path name
81
71
  self.path = nil
82
72
  self.name_with_prefix = name
83
73
  end
84
74
 
75
+ # Add the prefix to the template name.
76
+ #
77
+ # Note: Will add an underscore if it's a partial.
78
+ #
85
79
  def name_with_prefix= name
86
80
  self.name = "#{self.prefix}#{name}"
87
81
  end
88
82
 
83
+ # Extracts the template name from the given parameter.
84
+ #
85
+ # If it's a hash, it will remove and use the :partial option.
86
+ # If not, it will use that.
87
+ #
88
+ def deoptionize template_name
89
+ if template_name.kind_of?(Hash)
90
+ @options.merge! template_name
91
+ @options.delete :partial
92
+ else
93
+ template_name
94
+ end
95
+ end
96
+
89
97
  end
90
98
 
91
99
  # A specific container for partial rendering.
@@ -60,7 +60,7 @@ describe 'Integration' do
60
60
  # end
61
61
  # end
62
62
  # end
63
-
63
+
64
64
  describe 'ActiveRecord Extensions' do
65
65
  before(:each) do
66
66
  @view_model.extend ViewModels::Extensions::ActiveRecord
@@ -1,7 +1,7 @@
1
1
  module ModuleForRendering
2
-
2
+
3
3
  def module_method
4
4
  "Hello!"
5
5
  end
6
-
6
+
7
7
  end
@@ -32,8 +32,6 @@ describe ViewModels::Helpers::Rails do
32
32
  specific_view_model_mapping.should == {}
33
33
  end
34
34
  it "should raise an ArgumentError on an non-mapped model" do
35
- # TODO really clear enough that one should provide a ViewModel with an initializer with 2 params?
36
- #
37
35
  class SomeViewModelClass; end
38
36
  specific_view_model_mapping[String] = SomeViewModelClass
39
37
  lambda {
@@ -43,8 +41,6 @@ describe ViewModels::Helpers::Rails do
43
41
  end
44
42
  describe "no specific mapping" do
45
43
  it "should raise on an non-mapped model" do
46
- # TODO really clear enough that the view model class is missing?
47
- #
48
44
  lambda {
49
45
  view_model_for(42)
50
46
  }.should raise_error(NameError, "uninitialized constant ViewModels::Fixnum")
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 5
8
- - 6
9
- version: 1.5.6
8
+ - 7
9
+ version: 1.5.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - Florian Hanke
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2010-03-04 00:00:00 +01:00
20
+ date: 2010-04-15 00:00:00 +02:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency