view_models 2.0.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. data/.bundle/config +2 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +2 -0
  4. data/.rvmrc +1 -0
  5. data/.travis.yml +19 -0
  6. data/.yardoc/checksums +13 -0
  7. data/.yardoc/object_types +0 -0
  8. data/.yardoc/objects/root.dat +0 -0
  9. data/.yardoc/proxy_types +0 -0
  10. data/Appraisals +15 -0
  11. data/CHANGELOG +31 -0
  12. data/Gemfile +13 -0
  13. data/Gemfile.lock +174 -0
  14. data/MIT-LICENSE +20 -0
  15. data/README.textile +199 -0
  16. data/Rakefile +24 -0
  17. data/doc/ModulesInRenderHierarchy.html +186 -0
  18. data/doc/ModulesInRenderHierarchy/ClassMethods.html +188 -0
  19. data/doc/ViewModels.html +202 -0
  20. data/doc/ViewModels/Base.html +1342 -0
  21. data/doc/ViewModels/ContextExtractor.html +406 -0
  22. data/doc/ViewModels/Extensions.html +128 -0
  23. data/doc/ViewModels/Extensions/ModelReader.html +255 -0
  24. data/doc/ViewModels/Extensions/ModelReader/FilteredDelegationInstaller.html +908 -0
  25. data/doc/ViewModels/Extensions/ModelReader/Options.html +551 -0
  26. data/doc/ViewModels/Extensions/View.html +303 -0
  27. data/doc/ViewModels/Helpers.html +129 -0
  28. data/doc/ViewModels/Helpers/Mapping.html +562 -0
  29. data/doc/ViewModels/Helpers/Mapping/Collection.html +844 -0
  30. data/doc/ViewModels/Helpers/View.html +287 -0
  31. data/doc/ViewModels/PathStore.html +745 -0
  32. data/doc/ViewModels/RenderOptions.html +126 -0
  33. data/doc/ViewModels/RenderOptions/Base.html +1187 -0
  34. data/doc/ViewModels/RenderOptions/Partial.html +231 -0
  35. data/doc/ViewModels/RenderOptions/Template.html +231 -0
  36. data/doc/ViewModels/View.html +414 -0
  37. data/doc/ViewModelsGenerator.html +410 -0
  38. data/doc/_index.html +317 -0
  39. data/doc/class_list.html +53 -0
  40. data/doc/css/common.css +1 -0
  41. data/doc/css/full_list.css +57 -0
  42. data/doc/css/style.css +328 -0
  43. data/doc/file.README.html +113 -0
  44. data/doc/file_list.html +55 -0
  45. data/doc/frames.html +28 -0
  46. data/doc/index.html +113 -0
  47. data/doc/js/app.js +214 -0
  48. data/doc/js/full_list.js +173 -0
  49. data/doc/js/jquery.js +4 -0
  50. data/doc/method_list.html +628 -0
  51. data/doc/top-level-namespace.html +114 -0
  52. data/feature_support/testapp/app/controllers/heroes_controller.rb +6 -0
  53. data/feature_support/testapp/app/controllers/users_controller.rb +6 -0
  54. data/feature_support/testapp/app/helpers/application_helper.rb +8 -0
  55. data/feature_support/testapp/app/models/hero.rb +8 -0
  56. data/feature_support/testapp/app/models/user.rb +3 -0
  57. data/feature_support/testapp/app/view_models/hero.rb +8 -0
  58. data/feature_support/testapp/app/view_models/test.rb +8 -0
  59. data/feature_support/testapp/app/view_models/user.rb +14 -0
  60. data/feature_support/testapp/app/views/heroes/show.html.slim +6 -0
  61. data/feature_support/testapp/app/views/users/_box.html.slim +8 -0
  62. data/feature_support/testapp/app/views/users/show.html.slim +6 -0
  63. data/feature_support/testapp/config/application.rb +64 -0
  64. data/feature_support/testapp/config/cucumber.yml +8 -0
  65. data/feature_support/testapp/config/database.yml +28 -0
  66. data/feature_support/testapp/config/environments/cucumber.rb +11 -0
  67. data/feature_support/testapp/config/environments/test.rb +27 -0
  68. data/feature_support/testapp/config/routes.rb +4 -0
  69. data/feature_support/testapp/db/migrate/1_create_users.rb +13 -0
  70. data/feature_support/testapp/features/inheritance.feature +16 -0
  71. data/feature_support/testapp/features/step_definitions/testapp_steps.rb +16 -0
  72. data/feature_support/testapp/features/support/env.rb +13 -0
  73. data/feature_support/testapp/features/users.feature +15 -0
  74. data/feature_support/testapp/lib/tasks/cucumber.rake +31 -0
  75. data/feature_support/testapp/spec/factories/heroes.rb +7 -0
  76. data/feature_support/testapp/spec/factories/users.rb +7 -0
  77. data/features/rails_integration.feature +21 -0
  78. data/features/step_definitions/rails_steps.rb +112 -0
  79. data/features/support/env.rb +6 -0
  80. data/gemfiles/3.0.Gemfile +13 -0
  81. data/gemfiles/3.1.Gemfile +15 -0
  82. data/gemfiles/3.2.gemfile +15 -0
  83. data/lib/rails/generators/view_models/USAGE +6 -0
  84. data/lib/rails/generators/view_models/templates/views/_collection.html.erb +6 -0
  85. data/lib/{rails2/generators/view_models/templates/views/view_models/collection → rails/generators/view_models/templates/views}/_collection.html.haml +1 -2
  86. data/lib/rails/generators/view_models/templates/views/_collection.html.slim +6 -0
  87. data/lib/{rails2/generators/view_models/templates/views/_empty.html.haml → rails/generators/view_models/templates/views/_empty.html.erb} +0 -0
  88. data/lib/rails/generators/view_models/templates/views/_empty.html.haml +0 -0
  89. data/lib/rails/generators/view_models/templates/views/_empty.html.slim +0 -0
  90. data/lib/rails/generators/view_models/templates/views/_list.html.erb +6 -0
  91. data/lib/rails/generators/view_models/templates/views/_list.html.haml +4 -0
  92. data/lib/rails/generators/view_models/templates/views/_list.html.slim +5 -0
  93. data/lib/rails/generators/view_models/templates/views/_pagination.html.erb +18 -0
  94. data/lib/{rails2/generators/view_models/templates/views/view_models/collection → rails/generators/view_models/templates/views}/_pagination.html.haml +2 -2
  95. data/lib/rails/generators/view_models/templates/views/_pagination.html.slim +12 -0
  96. data/lib/rails/generators/view_models/templates/views/_table.html.erb +10 -0
  97. data/lib/{rails2/generators/view_models/templates/views/view_models/collection → rails/generators/view_models/templates/views}/_table.html.haml +0 -0
  98. data/lib/rails/generators/view_models/templates/views/_table.html.slim +5 -0
  99. data/lib/rails/generators/view_models/view_models_generator.rb +57 -0
  100. data/lib/view_models.rb +15 -5
  101. data/lib/{shared/lib/view_models → view_models}/base.rb +148 -37
  102. data/lib/{shared/lib/view_models → view_models}/context_extractor.rb +6 -2
  103. data/lib/{shared/lib/view_models → view_models}/extensions/model_reader.rb +27 -13
  104. data/lib/{rails2/lib → view_models}/extensions/view.rb +6 -1
  105. data/lib/view_models/helpers/collection.rb +113 -0
  106. data/lib/{shared/lib/view_models → view_models}/helpers/mapping.rb +12 -15
  107. data/lib/{rails2/lib → view_models}/helpers/view.rb +5 -1
  108. data/lib/{shared/lib/view_models → view_models}/path_store.rb +6 -1
  109. data/lib/{shared/lib/view_models → view_models}/render_options.rb +19 -4
  110. data/lib/view_models/version.rb +5 -0
  111. data/lib/{rails2/lib/view_models → view_models}/view.rb +7 -6
  112. data/spec/{rails2/lib → lib}/view_models/base_spec.rb +38 -5
  113. data/spec/{rails2/lib → lib/view_models}/extensions/model_reader_spec.rb +4 -4
  114. data/spec/{shared/lib → lib/view_models}/helpers/collection_spec.rb +21 -1
  115. data/spec/{shared/lib → lib/view_models}/helpers/mapping_spec.rb +6 -5
  116. data/spec/{rails2/lib → lib/view_models}/helpers/view_spec.rb +1 -1
  117. data/spec/lib/view_models/view_spec.rb +42 -0
  118. data/spec/spec_helper.rb +32 -0
  119. data/spec/spec_helper_extensions.rb +13 -0
  120. data/view_models.gemspec +36 -0
  121. metadata +411 -142
  122. data/lib/init.rb +0 -1
  123. data/lib/padrino/README.textile +0 -3
  124. data/lib/padrino/init.rb +0 -10
  125. data/lib/padrino/lib/helpers/collection.rb +0 -27
  126. data/lib/padrino/lib/padrino/view_models.rb +0 -19
  127. data/lib/padrino/lib/view_models/base.rb +0 -65
  128. data/lib/rails2/README.textile +0 -3
  129. data/lib/rails2/TODO.textile +0 -5
  130. data/lib/rails2/generators/view_models/USAGE +0 -6
  131. data/lib/rails2/generators/view_models/templates/README +0 -1
  132. data/lib/rails2/generators/view_models/templates/spec/view_model_spec.rb +0 -7
  133. data/lib/rails2/generators/view_models/templates/view_models/view_model.rb +0 -5
  134. data/lib/rails2/generators/view_models/templates/views/view_models/collection/_collection.html.erb +0 -1
  135. data/lib/rails2/generators/view_models/templates/views/view_models/collection/_collection.text.erb +0 -6
  136. data/lib/rails2/generators/view_models/templates/views/view_models/collection/_list.html.erb +0 -1
  137. data/lib/rails2/generators/view_models/templates/views/view_models/collection/_list.text.erb +0 -6
  138. data/lib/rails2/generators/view_models/templates/views/view_models/collection/_pagination.text.erb +0 -3
  139. data/lib/rails2/generators/view_models/templates/views/view_models/collection/_table.text.erb +0 -10
  140. data/lib/rails2/generators/view_models/view_models_generator.rb +0 -47
  141. data/lib/rails2/init.rb +0 -18
  142. data/lib/rails2/lib/experimental/README.textile +0 -32
  143. data/lib/rails2/lib/experimental/modules_in_render_hierarchy.rb +0 -21
  144. data/lib/rails2/lib/helpers/collection.rb +0 -27
  145. data/lib/rails2/lib/view_models.rb +0 -1
  146. data/lib/rails2/lib/view_models/base.rb +0 -99
  147. data/lib/shared/README.textile +0 -3
  148. data/lib/shared/init.rb +0 -11
  149. data/lib/shared/lib/view_models.rb +0 -4
  150. data/lib/shared/lib/view_models/extensions/active_record.rb +0 -27
  151. data/lib/shared/lib/view_models/helpers/collection.rb +0 -110
  152. data/spec/padrino/integration/integration_spec.rb +0 -287
  153. data/spec/padrino/lib/helpers/collection_spec.rb +0 -30
  154. data/spec/rails2/integration/integration_spec.rb +0 -279
  155. data/spec/rails2/lib/extensions/active_record_spec.rb +0 -31
  156. data/spec/rails2/lib/helpers/collection_spec.rb +0 -30
  157. data/spec/rails2/lib/view_models/view_spec.rb +0 -12
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_WITHOUT: ""
@@ -0,0 +1,8 @@
1
+ .DS_Store
2
+ log/*.log
3
+ tmp
4
+ coverage
5
+ pkg
6
+ .rbx
7
+
8
+ rails/log/*.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --profile
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@view_models
@@ -0,0 +1,19 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ree
6
+ - rbx-18mode
7
+ - rbx-19mode
8
+ - jruby
9
+
10
+ script: "bundle exec rake spec cucumber"
11
+
12
+ gemfile:
13
+ - gemfiles/3.2.gemfile
14
+ - gemfiles/3.1.Gemfile
15
+ - gemfiles/3.0.Gemfile
16
+
17
+ matrix:
18
+ allow_failures:
19
+ - rvm: jruby
@@ -0,0 +1,13 @@
1
+ lib/view_models.rb cdce5ced48e3d6147b31568f800e5222317b54f2
2
+ lib/view_models/base.rb 75e818e1f843a43cf8194a92dc77f4019362e68f
3
+ lib/view_models/view.rb 438b98e8068703cf99e010b10b01e6e484b3b8bf
4
+ lib/view_models/version.rb db9c82d8d0eca0c06c6c984da4e1deb4883b382b
5
+ lib/view_models/path_store.rb 8e4b11a73e6d8f1a89bad01b143ddd8a4a20136f
6
+ lib/view_models/helpers/view.rb 6633aced3a9aa969a7b724ed5569b405a4eb3485
7
+ lib/view_models/render_options.rb 7aaf1f6a8f23dddd7da5edc54a57eec5559e5aa3
8
+ lib/view_models/extensions/view.rb 6a5397c357ec1c602ae5d0b8022fa8c10411301c
9
+ lib/view_models/helpers/mapping.rb adf576f9fa3b2a99697e4c2851ae79a1fcf15811
10
+ lib/view_models/context_extractor.rb 37a7419a5b04f7aff344ddf130dbdaee0f9f4fed
11
+ lib/view_models/helpers/collection.rb 57aabb6a4738cfe2c2f2795b561b0d58ffa1ac67
12
+ lib/view_models/extensions/model_reader.rb 1f7c1cc73fad44d30bc66a76720d9ee237ba63fe
13
+ lib/rails/generators/view_models/view_models_generator.rb 8e3754d601a82bcbe71665e0cd810c3336b19e3e
Binary file
Binary file
Binary file
@@ -0,0 +1,15 @@
1
+ appraise '3.0' do
2
+ gem 'rails', '~> 3.0.0'
3
+ end
4
+
5
+ appraise '3.1' do
6
+ gem 'rails', '~> 3.1.0'
7
+ gem 'jquery-rails'
8
+ gem 'sass-rails'
9
+ end
10
+
11
+ appraise '3.2' do
12
+ gem 'rails', '~> 3.2.0'
13
+ gem 'jquery-rails'
14
+ gem 'sass-rails'
15
+ end
@@ -0,0 +1,31 @@
1
+ 3.0.0 - 28.10.12 - beatrichartz: Rails 3 Version of view models
2
+ 2.0.0 - 21.06.10 - floere: Dualboot (Padrino/Rails2) gem.
3
+ 1.6.0 - 15.06.10 - floere: Added Padrino to the frameworks.
4
+ Changed visibility of methods model, context (controller, app) from public to protected.
5
+ (Opinionated Discouragement – make them public if you feel accessing the model directly is ok.)
6
+ 1.5.2 - 25.02.10 - floere: The capture method - if included per Capturehelper - works now in view models.
7
+ 1.5.1 - 22.02.10 - floere: Renamed ViewModels::Helper to ViewModels::Helpers.
8
+ 1.5.0 - 20.02.10 - floere: format propagates through collection rendering
9
+ render_as, new sig: :partial => to explicitly define the partial. (Syntactic Discouragement)
10
+ Added: render_with, an alias of render_as.
11
+ Added: render_template, to render non-partials.
12
+ 1.4.2 - 10.02.10 - floere: render_as does not check the deprecated API anymore. Use the new options
13
+ form to pass a format.
14
+ - floere: MissingViewModelError is not thrown anymore.
15
+ - floere: include ViewModels::Extensions::ActiveRecord in your Project view model to
16
+ give id, dom_id, to_param capabilities to your view_models. Or include in a
17
+ subclass.
18
+ 1.4.0 - 08.02.10 - floere: Changed Api of ViewModels::Base#render_as to go up through the view model
19
+ class hierarchy to find a partial.
20
+ 1.3.0 - 29.01.10 - andi: Changed Api of ViewModels::Base#render_as to take an options hash. Now supports
21
+ passing locals to the render call.
22
+ 1.2.0 - 13.01.10 - floere: Simple generator written.
23
+ 1.1.0 - 30.06.09 - floere: Rewrite: Representer => ViewModel.
24
+ 1.0.2 - 08.08.08 - floere: Renamed Representers::Helper::Rails to Representers::Helper::Rails.
25
+ - floere: Added Representers::Helpers::View for conveniently integrating common view-helpers.
26
+ - floere: Added controller_methods for RequestForgeryProtection in ViewModels::Base.
27
+ - floere: Added methods for id and dom_id in Representers::ActiveRecord.
28
+ - floere: Included ActionController::Helpers in Representers::Base and removed own helper-method.
29
+ - floere: Changed visibility of method view_instance in Representers::Base from private to protected.
30
+ 1.0.1 - 24.07.08 - floere: Rewrite: Presenter => Representer.
31
+ 1.0.0 - May 2008 - floere: Initial commit.
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem 'sqlite3', :platform => :ruby
6
+
7
+ # Can't wrap in platform :jruby do...end block because appraisal doesn't support
8
+ # it
9
+ gem 'activerecord-jdbc-adapter', :platform => :jruby
10
+ gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
11
+ gem 'jdbc-sqlite3', :platform => :jruby
12
+ gem 'jruby-openssl', :platform => :jruby
13
+ gem 'therubyrhino', :platform => :jruby
@@ -0,0 +1,174 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ view_models (3.0.0)
5
+ actionmailer (>= 3.0.0)
6
+ actionpack (>= 3.0.0)
7
+ activerecord (>= 3.0.0)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ RedCloth (4.2.9)
13
+ actionmailer (3.2.8)
14
+ actionpack (= 3.2.8)
15
+ mail (~> 2.4.4)
16
+ actionpack (3.2.8)
17
+ activemodel (= 3.2.8)
18
+ activesupport (= 3.2.8)
19
+ builder (~> 3.0.0)
20
+ erubis (~> 2.7.0)
21
+ journey (~> 1.0.4)
22
+ rack (~> 1.4.0)
23
+ rack-cache (~> 1.2)
24
+ rack-test (~> 0.6.1)
25
+ sprockets (~> 2.1.3)
26
+ activemodel (3.2.8)
27
+ activesupport (= 3.2.8)
28
+ builder (~> 3.0.0)
29
+ activerecord (3.2.8)
30
+ activemodel (= 3.2.8)
31
+ activesupport (= 3.2.8)
32
+ arel (~> 3.0.2)
33
+ tzinfo (~> 0.3.29)
34
+ activesupport (3.2.8)
35
+ i18n (~> 0.6)
36
+ multi_json (~> 1.0)
37
+ addressable (2.3.2)
38
+ appraisal (0.4.1)
39
+ bundler
40
+ rake
41
+ arel (3.0.2)
42
+ aruba (0.4.11)
43
+ childprocess (>= 0.2.3)
44
+ cucumber (>= 1.1.1)
45
+ ffi (>= 1.0.11)
46
+ rspec (>= 2.7.0)
47
+ builder (3.0.3)
48
+ capybara (1.1.2)
49
+ mime-types (>= 1.16)
50
+ nokogiri (>= 1.3.3)
51
+ rack (>= 1.0.0)
52
+ rack-test (>= 0.5.4)
53
+ selenium-webdriver (~> 2.0)
54
+ xpath (~> 0.1.4)
55
+ childprocess (0.3.5)
56
+ ffi (~> 1.0, >= 1.0.6)
57
+ cucumber (1.2.1)
58
+ builder (>= 2.1.2)
59
+ diff-lcs (>= 1.1.3)
60
+ gherkin (~> 2.11.0)
61
+ json (>= 1.4.6)
62
+ cucumber-rails (1.3.0)
63
+ capybara (>= 1.1.2)
64
+ cucumber (>= 1.1.8)
65
+ nokogiri (>= 1.5.0)
66
+ database_cleaner (0.8.0)
67
+ diff-lcs (1.1.3)
68
+ erubis (2.7.0)
69
+ factory_girl (2.6.4)
70
+ activesupport (>= 2.3.9)
71
+ factory_girl_rails (1.7.0)
72
+ factory_girl (~> 2.6.0)
73
+ railties (>= 3.0.0)
74
+ ffi (1.1.5)
75
+ gherkin (2.11.2)
76
+ json (>= 1.4.6)
77
+ hike (1.2.1)
78
+ i18n (0.6.1)
79
+ journey (1.0.4)
80
+ json (1.7.5)
81
+ libwebsocket (0.1.5)
82
+ addressable
83
+ mail (2.4.4)
84
+ i18n (>= 0.4.0)
85
+ mime-types (~> 1.16)
86
+ treetop (~> 1.4.8)
87
+ mime-types (1.19)
88
+ multi_json (1.3.6)
89
+ nokogiri (1.5.5)
90
+ polyglot (0.3.3)
91
+ rack (1.4.1)
92
+ rack-cache (1.2)
93
+ rack (>= 0.4)
94
+ rack-ssl (1.3.2)
95
+ rack
96
+ rack-test (0.6.1)
97
+ rack (>= 1.0)
98
+ railties (3.2.8)
99
+ actionpack (= 3.2.8)
100
+ activesupport (= 3.2.8)
101
+ rack-ssl (~> 1.3.2)
102
+ rake (>= 0.8.7)
103
+ rdoc (~> 3.4)
104
+ thor (>= 0.14.6, < 2.0)
105
+ rake (0.9.2.2)
106
+ rdoc (3.12)
107
+ json (~> 1.4)
108
+ rspec (2.11.0)
109
+ rspec-core (~> 2.11.0)
110
+ rspec-expectations (~> 2.11.0)
111
+ rspec-mocks (~> 2.11.0)
112
+ rspec-core (2.11.1)
113
+ rspec-expectations (2.11.3)
114
+ diff-lcs (~> 1.1.3)
115
+ rspec-mocks (2.11.3)
116
+ rspec-rails (2.11.0)
117
+ actionpack (>= 3.0)
118
+ activesupport (>= 3.0)
119
+ railties (>= 3.0)
120
+ rspec (~> 2.11.0)
121
+ rubyzip (0.9.9)
122
+ selenium-webdriver (2.25.0)
123
+ childprocess (>= 0.2.5)
124
+ libwebsocket (~> 0.1.3)
125
+ multi_json (~> 1.0)
126
+ rubyzip
127
+ slim (1.3.0)
128
+ temple (~> 0.4.1)
129
+ tilt (~> 1.3.3)
130
+ slim-rails (1.0.3)
131
+ actionpack (~> 3.0)
132
+ activesupport (~> 3.0)
133
+ railties (~> 3.0)
134
+ slim (~> 1.0)
135
+ sprockets (2.1.3)
136
+ hike (~> 1.2)
137
+ rack (~> 1.0)
138
+ tilt (~> 1.1, != 1.3.0)
139
+ sqlite3 (1.3.6)
140
+ temple (0.4.1)
141
+ thor (0.16.0)
142
+ tilt (1.3.3)
143
+ treetop (1.4.11)
144
+ polyglot
145
+ polyglot (>= 0.3.1)
146
+ tzinfo (0.3.33)
147
+ xpath (0.1.4)
148
+ nokogiri (~> 1.3)
149
+ yard (0.8.3)
150
+
151
+ PLATFORMS
152
+ ruby
153
+
154
+ DEPENDENCIES
155
+ RedCloth
156
+ activerecord-jdbc-adapter
157
+ activerecord-jdbcsqlite3-adapter
158
+ appraisal (~> 0.4.0)
159
+ aruba
160
+ bundler (>= 1.1.0)
161
+ cucumber
162
+ cucumber-rails
163
+ database_cleaner
164
+ factory_girl (~> 2.6.4)
165
+ factory_girl_rails (~> 1.7.0)
166
+ jdbc-sqlite3
167
+ jruby-openssl
168
+ rake (>= 0.8.7)
169
+ rspec-rails (~> 2.11.0)
170
+ slim-rails (~> 1.0.0)
171
+ sqlite3
172
+ therubyrhino
173
+ view_models!
174
+ yard
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Florian Hanke & Kaspar Schiess
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,199 @@
1
+ h1. View Models !https://secure.travis-ci.org/beatrichartz/view_models.png(Build Status)!:http://travis-ci.org/beatrichartz/view_models "!https://codeclimate.com/badge.png!":https://codeclimate.com/github/beatrichartz/view_models
2
+
3
+ A representer solution for Rails 3. For older versions of Rails please use versions up to 3. You may find view models useful (or not). Fact: They will keep code out of your views. Because view models do not like code in your view.
4
+
5
+ h2. Installing View Models
6
+
7
+ Add this to your gemfile
8
+
9
+ <pre><code>gem "view_models", ">= 3.0.0"
10
+ </code></pre>
11
+
12
+ And this to your application.rb: (It adds the app folder to the autoload paths, which is necessary for the view models to load)
13
+ <pre><code>config.autoload_paths += %W(#{config.root}/app)
14
+ </code></pre>
15
+
16
+ Create a directory "view_models" in your app folder, and you're good to go.
17
+ <pre><code>mkdir ./app/view_models
18
+ </code></pre>
19
+
20
+ h2. TODOs
21
+
22
+ What you can look forward to in future versions of this gem:
23
+ - Bootstrapping for easier installation
24
+ - JSON generation out of view models
25
+
26
+ h2. Basic Usage
27
+
28
+ Let's say you have a model User (with a first and a last name and an address in the database):
29
+
30
+ <pre><code>class User < ActiveRecord::Base
31
+
32
+ has_many :posts
33
+
34
+ end
35
+ </code></pre>
36
+
37
+ Write a corresponding view model user.rb in your view_models folder
38
+
39
+ <pre><code>class ViewModels::User < ViewModels::Base
40
+
41
+ # model readers make model methods accessible on the view model object
42
+ #
43
+ model_reader :first_name, :last_name, :street, :street_number, :zip_code, :city
44
+
45
+ # Write helper methods which benefit from model readers
46
+ #
47
+ def name
48
+ [first_name, last_name].join ' '
49
+ end
50
+
51
+ # Access the model by using «model»
52
+ #
53
+ def creation_time
54
+ time_ago_in_words model.created_at
55
+ end
56
+
57
+ end
58
+ </code></pre>
59
+
60
+ In your view, call the view_model for a model by using «view_model_for»
61
+
62
+ <pre><code>- view_model = view_model_for(@user)
63
+ %h2= view_model.name
64
+ %h2= view_model.creation_time
65
+ </code></pre>
66
+
67
+ All beautiful, you may think, but...
68
+
69
+ h2. Why View Models? (aka «The Problem»)
70
+
71
+ Ever felt like putting something like this in your views (example in haml)?
72
+
73
+ <pre><code>#user
74
+ .name= [@user.first_name, @user.last_name].join ' '
75
+ .address= [@user.street, @user.street_number, @user.zip_code, @user.city].join ' '
76
+ </code></pre>
77
+
78
+ Well, that may feel good if you're in a hurry. Soon there comes the time when you use this code in more than one place. Time to build a helper:
79
+
80
+ <pre><code>module UserHelper
81
+ def user_name user
82
+ [user.first_name, user.last_name].join ' '
83
+ end
84
+
85
+ def user_address user
86
+ [user.street, user.street_number, user.zip_code, user.city].join ' '
87
+ end
88
+ end
89
+
90
+ #user
91
+ .name= user_name @user
92
+ .address= user_address @user
93
+ </code></pre>
94
+
95
+ It may be a lot cleaner, but something just does not feel right. Right, but what? Well, for instance, you have to namespace all your methods with «user» so your methods don't get messy. Second, you have to include the helper either in every context you use it, or even in the whole app. If only you had a polymorphic object to represent your models in the views...
96
+
97
+ h3. Meet View Models (aka «The Solution»)
98
+
99
+ View models are pretty, because they represent your models in your views. They look good in every context, and therefore make you look good, too. Take our example from before:
100
+
101
+ <pre><code>class ViewModels::User < ViewModels::Base
102
+
103
+ model_reader :first_name, :last_name, :street, :street_number, :zip_code, :city
104
+
105
+ def name
106
+ [first_name, last_name].join ' '
107
+ end
108
+
109
+ def address
110
+ [street, street_number, zip_code, city].join ' '
111
+ end
112
+
113
+ end
114
+ </code></pre>
115
+
116
+ And your view will look like this:
117
+
118
+ <pre><code>- user_view_model = view_model_for(@user)
119
+ #user
120
+ .name= user_view_model.name
121
+ .address= user_view_model.address
122
+ </code></pre>
123
+
124
+ No helper inclusion needed, no further noise involved. In fact, you can make it even prettier: What if you needed that partial with the user name and address somewhere else in your code?
125
+
126
+ h3. Meet View Models render_as method
127
+
128
+ View models feature template rendering: You can render any partial in your views, following your views directory tree structure: A view_model variable will automatically be included as a local variable in your partial if you render it with view models:
129
+
130
+ Let's say you have the user model from before, and the following partial written for the view model to render named "info":
131
+
132
+ <pre><code>#user
133
+ .name= view_model.name
134
+ .address= view_model.address
135
+ </code></pre>
136
+
137
+ Now everything you have to do to render that partial is:
138
+
139
+ <pre><code>= view_model_for(@user).render_as :info
140
+ </code></pre>
141
+
142
+ View models feature hierarchical template rendering. That means, if you have a parent view model which has an identical partial already installed, you do not need to copy identical code just to render the same template. The view model will lookup its inheritance chain and Rails template paths to find the suitable partial. Which brings us to another great feature:
143
+
144
+ h3. View Models can haz inheritance
145
+
146
+ Ever tried to do inheritance in Rails helpers? Right. View Models, on the other side, love inheritance. They do not need arguments to display a formatted creation time for all your models. Consider the following:
147
+
148
+ h4. The View Model Way
149
+
150
+ You can generate a view model tree structure with a view model for your whole app for your other view models to inherit from. The polymorphic class matching of the view models ignores the missing class YourApp candidly.
151
+
152
+ <pre><code>class ViewModels::YourApp < ViewModels::Base
153
+
154
+ def creation_time
155
+ time_ago_in_words model.created_at
156
+ end
157
+
158
+ end
159
+
160
+ class ViewModels::User < ViewModels::YourApp
161
+ end
162
+ </code></pre>
163
+
164
+ In your view:
165
+
166
+ <pre><code>= view_model_for(@user).creation_time
167
+ </code></pre>
168
+
169
+ h4. The Helper Way
170
+
171
+ Imagine how to do this in a helper ? Well, better go ahead and use time_ago_in_words everywhere.
172
+
173
+ h2. Where is it used?
174
+
175
+ There are known some places in the big place called internet to use this gem:
176
+
177
+ "rightclearing.com [Music Licensing Provider]": http://rightclearing.com
178
+ "restorm.com [Music Platform]": http://restorm.com
179
+
180
+ h2. Testing View Models
181
+
182
+ Testing View Models is easy. You can use the view models initializer instead of the view_model_for mapping (example in rspec with factory girl):
183
+
184
+ <pre><code>describe "ViewModels::User" do
185
+ let(:user) { build_stubbed(:user) }
186
+ subject { ViewModels::User.new(user, @controller) } # @controller may be nil or the controller
187
+
188
+ describe "model_readers"
189
+ .. there you go
190
+ end
191
+ end
192
+ </code></pre>
193
+
194
+ h2. Further reads
195
+
196
+ "Mailing List":http://groups.google.com/group/view_models/topics
197
+ "Rubygems":http://rubygems.org/gems/view_models
198
+ "Bug Tracker":http://github.com/floere/view_models/issues
199
+ "Source [Github]":http://github.com/floere/view_models