zena 1.0.0.rc2 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (274) hide show
  1. data/History.txt +23 -0
  2. data/README.rdoc +1 -1
  3. data/app/controllers/columns_controller.rb +3 -31
  4. data/app/controllers/comments_controller.rb +8 -3
  5. data/app/controllers/data_entries_controller.rb +1 -1
  6. data/app/controllers/documents_controller.rb +2 -2
  7. data/app/controllers/nodes_controller.rb +29 -12
  8. data/app/controllers/relations_controller.rb +2 -2
  9. data/app/controllers/sites_controller.rb +1 -1
  10. data/app/controllers/user_sessions_controller.rb +6 -3
  11. data/app/controllers/users_controller.rb +18 -16
  12. data/app/controllers/versions_controller.rb +20 -18
  13. data/app/controllers/virtual_classes_controller.rb +103 -17
  14. data/app/helpers/users_helper.rb +1 -1
  15. data/app/models/column.rb +19 -50
  16. data/app/models/comment.rb +2 -1
  17. data/app/models/node.rb +45 -22
  18. data/app/models/relation.rb +13 -0
  19. data/app/models/relation_proxy.rb +3 -2
  20. data/app/models/role.rb +213 -4
  21. data/app/models/site.rb +18 -11
  22. data/app/models/template.rb +37 -35
  23. data/app/models/version.rb +1 -1
  24. data/app/models/virtual_class.rb +154 -86
  25. data/app/views/columns/_li.html.erb +1 -1
  26. data/app/views/columns/index.html.erb +1 -9
  27. data/app/views/comments/index.rhtml +10 -8
  28. data/app/views/documents/_crop.rhtml +5 -6
  29. data/app/views/documents/crop_form.rjs +3 -2
  30. data/app/views/groups/index.rhtml +1 -1
  31. data/app/views/iformats/index.rhtml +1 -1
  32. data/app/views/nodes/_import_results.rhtml +1 -1
  33. data/app/views/nodes/_parent.rhtml +1 -2
  34. data/app/views/nodes/update.rjs +3 -4
  35. data/app/views/relations/index.erb +1 -1
  36. data/app/views/sites/index.erb +1 -1
  37. data/app/views/templates/drive_tabs/_drive.rhtml +0 -2
  38. data/app/views/templates/edit_tabs/_image.rhtml +1 -1
  39. data/app/views/templates/edit_tabs/_title.rhtml +0 -6
  40. data/app/views/users/index.rhtml +1 -1
  41. data/app/views/users/preferences.html.erb +2 -2
  42. data/app/views/versions/backup.rjs +1 -1
  43. data/app/views/versions/custom_tab.rhtml +9 -4
  44. data/app/views/versions/destroy.rjs +2 -2
  45. data/app/views/versions/update.rjs +2 -9
  46. data/app/views/virtual_classes/_form.erb +3 -2
  47. data/app/views/virtual_classes/import_prepare.html.erb +13 -0
  48. data/app/views/virtual_classes/index.erb +28 -8
  49. data/app/views/zafu/default/Node-+adminLayout.zafu +1 -13
  50. data/app/views/zafu/default/Node-+login.zafu +1 -0
  51. data/app/views/zafu/default/Node-+notFound.zafu +1 -1
  52. data/app/views/zafu/default/Node-+popupLayout.zafu +1 -2
  53. data/app/views/zafu/default/Node-+search.zafu +1 -1
  54. data/app/views/zafu/default/Node-admin.zafu +205 -0
  55. data/app/views/zafu/default/Node.zafu +11 -11
  56. data/bricks/captcha/lib/bricks/captcha.rb +3 -2
  57. data/bricks/mongrel/zena/init.rb +2 -1
  58. data/bricks/pdf/README +5 -5
  59. data/bricks/pdf/lib/bricks/pdf/engine/prince.rb +2 -2
  60. data/bricks/pdf/lib/bricks/pdf/engine/xhtml2pdf.rb +2 -2
  61. data/bricks/pdf/lib/bricks/pdf/install.rb +5 -5
  62. data/bricks/pdf/lib/bricks/pdf.rb +11 -11
  63. data/bricks/pdf/test/engines/test_prince.rb +4 -4
  64. data/bricks/pdf/test/engines/test_xhtml2pdf.rb +4 -4
  65. data/bricks/pdf/test/shoulda_macros/shoulda_pdf.rb +2 -2
  66. data/bricks/pdf/zena/init.rb +2 -2
  67. data/bricks/pdf/zena/tasks.rb +2 -2
  68. data/bricks/sphinx/lib/bricks/sphinx.rb +6 -2
  69. data/bricks/sphinx/zena/{sphinx.yml → sphinx.yml.erb} +2 -2
  70. data/bricks/sphinx/zena/tasks.rb +28 -2
  71. data/bricks/tags/lib/bricks/tags.rb +16 -1
  72. data/bricks/tags/zena/test/unit/tags_test.rb +15 -0
  73. data/bricks/tags/zena/test/zafu/tags.yml +5 -1
  74. data/bricks/worker/lib/bricks/worker.rb +39 -0
  75. data/bricks/worker/zena/deploy.rb +0 -2
  76. data/bricks/worker/zena/init.rb +1 -0
  77. data/bricks/worker/zena/test/sites/zena/delayed_jobs.yml +16 -0
  78. data/bricks/worker/zena/test/zafu/worker.yml +8 -0
  79. data/bricks/zena/zena/migrate/01_base.rb +36 -60
  80. data/bricks/zena/zena/migrate/02_zerox1_schema.rb +388 -0
  81. data/bricks/zena/zena/migrate/03_zerox1_data.rb +380 -0
  82. data/bricks/zena/zena/migrate/20110315161158_add_reverse_scope_to_roles.rb +9 -0
  83. data/config/database_example.yml +1 -1
  84. data/config/environment.rb +1 -1
  85. data/config/gems.yml +17 -14
  86. data/db/init/base/skins/default/Node-+index.zafu +8 -1
  87. data/db/init/base/skins/default/Node-+login.zafu +1 -0
  88. data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -2
  89. data/db/init/base/skins/default/Node-+search.zafu +2 -2
  90. data/db/init/base/skins/default/Node.zafu +9 -9
  91. data/db/init/base/skins/default/{favicon.png → img/favicon.png} +0 -0
  92. data/db/init/base/skins/default/{style.css → img/style.css} +0 -0
  93. data/db/init/base/skins/default/img/translations.yml +11 -0
  94. data/db/init/base/skins/default/notes.zafu +7 -9
  95. data/doc/zafu_changes.yml +12 -0
  96. data/lib/bricks/loader.rb +38 -15
  97. data/lib/tasks/zena.rake +74 -24
  98. data/lib/zena/acts/enrollable.rb +4 -1
  99. data/lib/zena/acts/secure.rb +2 -48
  100. data/lib/zena/acts/serializable.rb +13 -1
  101. data/lib/zena/app.rb +9 -0
  102. data/lib/zena/code_syntax.rb +154 -151
  103. data/lib/zena/console.rb +141 -0
  104. data/lib/zena/controller/test_case.rb +1 -1
  105. data/lib/zena/db_helper/abstract_db.rb +17 -5
  106. data/lib/zena/db_helper/mysql.rb +14 -12
  107. data/lib/zena/db_helper/postgresql.rb +1 -2
  108. data/lib/zena/db_helper/sqlite3.rb +6 -6
  109. data/lib/zena/deploy/awstats.conf.rhtml +1 -1
  110. data/lib/zena/deploy/httpd.rhtml +6 -1
  111. data/lib/zena/deploy/vhost.rhtml +9 -1
  112. data/lib/zena/deploy.rb +12 -7
  113. data/lib/zena/foxy_parser.rb +3 -1
  114. data/lib/zena/info.rb +1 -1
  115. data/lib/zena/parser/zafu_tags.rb +1 -0
  116. data/lib/zena/parser/zazen_rules.rb +1 -1
  117. data/lib/zena/remote/node.rb +15 -3
  118. data/lib/zena/remote/serializable_array.rb +19 -0
  119. data/lib/zena/remote.rb +1 -0
  120. data/lib/zena/routes.rb +7 -2
  121. data/lib/zena/site_worker.rb +11 -1
  122. data/lib/zena/unit/test_case.rb +68 -0
  123. data/lib/zena/use/action.rb +6 -2
  124. data/lib/zena/use/ajax.rb +127 -53
  125. data/lib/zena/use/ancestry.rb +11 -8
  126. data/lib/zena/use/calendar.rb +265 -129
  127. data/lib/zena/use/conditional.rb +1 -1
  128. data/lib/zena/use/context.rb +5 -5
  129. data/lib/zena/use/dates.rb +172 -60
  130. data/lib/zena/use/display.rb +70 -39
  131. data/lib/zena/use/error_rendering.rb +1 -3
  132. data/lib/zena/use/field_index.rb +4 -1
  133. data/lib/zena/use/forms.rb +94 -72
  134. data/lib/zena/use/fulltext.rb +16 -24
  135. data/lib/zena/use/html_tags.rb +20 -12
  136. data/lib/zena/use/i18n.rb +37 -37
  137. data/lib/zena/use/image_builder.rb +8 -1
  138. data/lib/zena/use/ml_index.rb +16 -16
  139. data/lib/zena/use/prop_eval.rb +10 -5
  140. data/lib/zena/use/query_builder.rb +55 -23
  141. data/lib/zena/use/query_node.rb +51 -25
  142. data/lib/zena/use/refactor.rb +2 -28
  143. data/lib/zena/use/relations.rb +1 -1
  144. data/lib/zena/use/rendering.rb +29 -0
  145. data/lib/zena/use/scope_index.rb +75 -14
  146. data/lib/zena/use/search.rb +5 -10
  147. data/lib/zena/use/test_helper.rb +2 -2
  148. data/lib/zena/use/urls.rb +125 -104
  149. data/lib/zena/use/workflow.rb +2 -1
  150. data/lib/zena/use/zafu_attributes.rb +2 -2
  151. data/lib/zena/use/zafu_safe_definitions.rb +20 -0
  152. data/lib/zena/use/zafu_templates.rb +20 -6
  153. data/lib/zena/use/zazen.rb +31 -20
  154. data/lib/zena/view/test_case.rb +5 -0
  155. data/lib/zena/zafu_compiler.rb +24 -2
  156. data/lib/zena.rb +12 -6
  157. data/locale/de/LC_MESSAGES/zena.mo +0 -0
  158. data/locale/de/zena.po +1345 -1164
  159. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  160. data/locale/en/zena.po +1275 -1129
  161. data/locale/fr/LC_MESSAGES/zena.mo +0 -0
  162. data/locale/fr/zena.mo +0 -0
  163. data/locale/fr/zena.po +1617 -1441
  164. data/locale/log.txt +9 -0
  165. data/locale/zena.pot +957 -748
  166. data/public/javascripts/prototype.js +1 -1
  167. data/public/javascripts/zena.js +99 -44
  168. data/public/stylesheets/admin.css +6 -4
  169. data/public/stylesheets/backend.css +71 -0
  170. data/public/stylesheets/calendar.css +24 -25
  171. data/public/stylesheets/code.css +11 -6
  172. data/public/stylesheets/comment.css +2 -1
  173. data/public/stylesheets/popup.css +7 -8
  174. data/test/custom_queries/complex.host.yml +15 -1
  175. data/test/fixtures/files/Node-test.zafu +29 -28
  176. data/test/fixtures/files/translations_de.yml +12 -1
  177. data/test/fixtures/files/translations_fr.yml +12 -1
  178. data/test/functional/comments_controller_test.rb +9 -0
  179. data/test/functional/iformats_controller_test.rb +1 -1
  180. data/test/functional/nodes_controller_test.rb +124 -35
  181. data/test/functional/users_controller_test.rb +132 -3
  182. data/test/functional/virtual_classes_controller_test.rb +75 -4
  183. data/test/integration/navigation_test.rb +51 -9
  184. data/test/integration/query_node/basic.yml +19 -7
  185. data/test/integration/query_node/complex.yml +1 -1
  186. data/test/integration/query_node/dates.yml +27 -1
  187. data/test/integration/query_node/filters.yml +1 -1
  188. data/test/integration/query_node/relations.yml +13 -4
  189. data/test/integration/query_node_test.rb +4 -0
  190. data/test/integration/xml_api_test.rb +6 -1
  191. data/test/integration/zafu_compiler/action.yml +3 -3
  192. data/test/integration/zafu_compiler/ajax.yml +103 -22
  193. data/test/integration/zafu_compiler/basic.yml +0 -52
  194. data/test/integration/zafu_compiler/calendar.yml +44 -20
  195. data/test/integration/zafu_compiler/comments.yml +53 -0
  196. data/test/integration/zafu_compiler/complex.yml +11 -11
  197. data/test/integration/zafu_compiler/complex_ok.yml +16 -3
  198. data/test/integration/zafu_compiler/conditional.yml +15 -5
  199. data/test/integration/zafu_compiler/context.yml +9 -0
  200. data/test/integration/zafu_compiler/dates.yml +43 -15
  201. data/test/integration/zafu_compiler/display.yml +60 -6
  202. data/test/integration/zafu_compiler/errors.yml +6 -2
  203. data/test/integration/zafu_compiler/forms.yml +45 -6
  204. data/test/integration/zafu_compiler/i18n.yml +8 -1
  205. data/test/integration/zafu_compiler/meta.yml +38 -0
  206. data/test/integration/zafu_compiler/query.yml +43 -4
  207. data/test/integration/zafu_compiler/relations.yml +26 -33
  208. data/test/integration/zafu_compiler/rubyless.yml +10 -0
  209. data/test/integration/zafu_compiler/safe_definitions.yml +21 -1
  210. data/test/integration/zafu_compiler/urls.yml +75 -5
  211. data/test/integration/zafu_compiler/version.yml +2 -2
  212. data/test/integration/zafu_compiler/zafu_attributes.yml +5 -1
  213. data/test/integration/zafu_compiler/zazen.yml +14 -6
  214. data/test/integration/zafu_compiler_test.rb +5 -1
  215. data/test/sites/complex/columns.yml +5 -0
  216. data/test/sites/complex/roles.yml +4 -0
  217. data/test/sites/zena/nodes.yml +13 -2
  218. data/test/sites/zena/roles.yml +13 -5
  219. data/test/sites/zena/versions.yml +27 -9
  220. data/test/unit/column_test.rb +51 -5
  221. data/test/unit/iformat_test.rb +2 -2
  222. data/test/unit/node_test.rb +29 -17
  223. data/test/unit/note_test.rb +1 -1
  224. data/test/unit/relation_proxy_test.rb +4 -5
  225. data/test/unit/relation_test.rb +16 -0
  226. data/test/unit/remote_test.rb +2 -2
  227. data/test/unit/role_test.rb +292 -4
  228. data/test/unit/site_test.rb +12 -0
  229. data/test/unit/template_test.rb +1 -1
  230. data/test/unit/text_document_test.rb +1 -1
  231. data/test/unit/virtual_class_test.rb +200 -83
  232. data/test/unit/zena/acts/enrollable_test.rb +26 -31
  233. data/test/unit/zena/use/calendar_test.rb +90 -37
  234. data/test/unit/zena/use/field_index_test.rb +28 -0
  235. data/test/unit/zena/use/html_tags_test.rb +7 -3
  236. data/test/unit/zena/use/ml_index_test.rb +2 -16
  237. data/test/unit/zena/use/nested_attributes_alias_view_test.rb +2 -2
  238. data/test/unit/zena/use/prop_eval_test.rb +50 -8
  239. data/test/unit/zena/use/query_node_test.rb +11 -0
  240. data/test/unit/zena/use/rendering_test.rb +72 -0
  241. data/test/unit/zena/use/scope_index_test.rb +37 -2
  242. data/test/unit/zena/use/urls_test.rb +10 -0
  243. data/test/unit/zena/use/zazen_test.rb +3 -3
  244. data/vendor/plugins/gettext_i18n_rails/Gemfile +11 -0
  245. data/vendor/plugins/gettext_i18n_rails/Gemfile.lock +92 -0
  246. data/vendor/plugins/gettext_i18n_rails/Rakefile +12 -17
  247. data/vendor/plugins/gettext_i18n_rails/Readme.md +215 -0
  248. data/vendor/plugins/gettext_i18n_rails/VERSION +1 -1
  249. data/vendor/plugins/gettext_i18n_rails/gettext_i18n_rails.gemspec +38 -34
  250. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/active_record.rb +1 -1
  251. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/backend.rb +30 -14
  252. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/haml_parser.rb +1 -1
  253. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/html_safe_translations.rb +29 -0
  254. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/i18n_hacks.rb +29 -1
  255. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/model_attributes_finder.rb +7 -1
  256. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/railtie.rb +10 -0
  257. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/ruby_gettext_extractor.rb +6 -2
  258. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/string_interpolate_fix.rb +20 -0
  259. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/tasks.rb +120 -0
  260. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails.rb +10 -3
  261. data/vendor/plugins/gettext_i18n_rails/lib/tasks/gettext_rails_i18n.rake +1 -74
  262. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/active_record_spec.rb +51 -20
  263. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/backend_spec.rb +12 -7
  264. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb +32 -0
  265. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails_spec.rb +38 -1
  266. data/vendor/plugins/gettext_i18n_rails/spec/rails2/Gemfile +11 -0
  267. data/vendor/plugins/gettext_i18n_rails/spec/spec_helper.rb +1 -8
  268. data/zena.gemspec +2241 -2217
  269. metadata +123 -83
  270. data/.gitignore +0 -36
  271. data/app/views/nodes/_dates.rhtml +0 -13
  272. data/db/init/base/skins/default/Node-+adminLayout.zafu +0 -46
  273. data/db/init/base/skins/default/Node-tree.zafu +0 -19
  274. data/vendor/plugins/gettext_i18n_rails/README.markdown +0 -143
@@ -6,6 +6,18 @@ class PropEvalTest < Zena::Unit::TestCase
6
6
  set_table_name :nodes_roles
7
7
  end
8
8
 
9
+ def idx_ml_value(obj_id, key, lang=visitor.lang)
10
+ IdxNodesMlString.find(:first,
11
+ :conditions => {:node_id => obj_id, :lang => lang, :key => key}
12
+ ).value
13
+ end
14
+
15
+ def idx_value(obj_id, key)
16
+ IdxNodesString.find(:first,
17
+ :conditions => {:node_id => obj_id, :key => key}
18
+ ).value
19
+ end
20
+
9
21
  context 'A visitor with admin rights' do
10
22
  setup do
11
23
  login(:lion)
@@ -98,21 +110,35 @@ class PropEvalTest < Zena::Unit::TestCase
98
110
  end
99
111
 
100
112
  should 'use evaluated prop in ml prop indices' do
101
- idx = IdxNodesMlString.find(:first,
102
- :conditions => {:node_id => subject.id, :lang => visitor.lang, :key => 'search'}
103
- )
104
- assert_equal 'zena enhancements paper:Origami', idx.value
113
+ assert_equal 'zena enhancements paper:Origami', idx_ml_value(subject.id, 'search')
105
114
  end
106
115
 
107
116
  should 'use evaluated prop in prop indices' do
108
- idx = IdxNodesString.find(:first,
109
- :conditions => {:node_id => subject.id, :key => 'search_mono'}
110
- )
111
- assert_equal 'Origami mono', idx.value
117
+ assert_equal 'Origami mono', idx_value(subject.id, 'search_mono')
112
118
  end
113
119
  end # with property indices
114
120
 
115
121
  end # updating attributes
122
+
123
+ context 'rebuilding index' do
124
+ setup do
125
+ login(:lion)
126
+ vclass = secure(Role) { roles(:Contact) }
127
+ # changed prop_eval
128
+ assert vclass.update_attributes(:prop_eval => %q[{'title' => "LAST:#{name} FIRST:#{first_name}"}])
129
+ end
130
+
131
+ subject do
132
+ secure(Node) { nodes(:ant) }
133
+ end
134
+
135
+ should 'evaluate prop' do
136
+ subject.rebuild_index!
137
+ assert_equal 'LAST:Invicta FIRST:Solenopsis', idx_ml_value(subject.id, 'title')
138
+ assert_equal 'LAST:Invicta FIRST:Solenopsis', nodes(:ant).title
139
+ end
140
+ end # rebuilding index
141
+
116
142
  end # from a class with evaluated properties
117
143
 
118
144
  context 'from a class with prop eval used as default' do
@@ -163,8 +189,24 @@ class PropEvalTest < Zena::Unit::TestCase
163
189
  end
164
190
  assert_equal 'Hyperion', subject.title
165
191
  end
192
+
193
+ should 'rebuild prop_eval on klass change' do
194
+ assert subject.update_attributes(:klass => 'Letter')
195
+ node = secure(Node) { Node.find(subject.id)}
196
+ assert_equal 'projects list paper:', node.search
197
+ end
166
198
  end # from a native class
167
199
 
168
200
  end # on a node
169
201
  end # A visitor with write access
202
+
203
+ context 'The VirtualClass class' do
204
+ subject do
205
+ VirtualClass
206
+ end
207
+
208
+ should 'contain prop_eval in export attributes' do
209
+ assert subject.export_attributes.include?('prop_eval')
210
+ end
211
+ end # A VirtualClass
170
212
  end
@@ -89,6 +89,17 @@ class QueryNodeTest < Zena::Unit::TestCase
89
89
  should 'set main_class' do
90
90
  assert_equal VirtualClass['Document'], subject.main_class
91
91
  end
92
+
93
+ context 'with core context' do
94
+ subject do
95
+ Node.build_query(:all, 'project')
96
+ end
97
+
98
+ should 'set main_class' do
99
+ assert_equal VirtualClass['Project'], subject.main_class
100
+ end
101
+ end # with core context
102
+
92
103
  end # with a real class filter
93
104
 
94
105
  context 'with root' do
@@ -41,6 +41,12 @@ class RenderingInControllerTest < Zena::Controller::TestCase
41
41
  end
42
42
  end
43
43
 
44
+ def make_template(zafu, mode = 'special')
45
+ login(:lion)
46
+ # create template for 'special' mode
47
+ secure(Template) { Template.create(:parent_id => nodes_id(:default), :title => "Node-#{mode}.zafu", :text => zafu, :v_status => Zena::Status[:pub]) }
48
+ end
49
+
44
50
  context 'A custom rendering engine' do
45
51
  setup do
46
52
  login(:anon)
@@ -102,6 +108,72 @@ class RenderingInControllerTest < Zena::Controller::TestCase
102
108
  end
103
109
  end # Custom rendering options
104
110
 
111
+ context 'special rendering zafu' do
112
+ subject do
113
+ {:action => 'show', :controller => 'nodes', :path => ["section#{nodes_zip(:people)}_#{@mode}.html"], :prefix => 'en'}
114
+ end
115
+
116
+ context 'to raise not found' do
117
+ setup do
118
+ @mode = 'nf'
119
+ make_template "<r:not_found/>", @mode
120
+ login(:anon)
121
+ end
122
+
123
+ should 'raise not found' do
124
+ # Stupid tests. Raises ActionView::TemplateError during testing and
125
+ # ActiveRecord::RecordNotFound in production.
126
+ assert_raise(ActionView::TemplateError) { get_subject }
127
+ end # Not found rendering
128
+ end # to raise not found
129
+
130
+ # Not working yet...
131
+ # context 'to redirect' do
132
+ # setup do
133
+ # @mode = 'redir'
134
+ # make_template "<r:redirect url='http://feature-space.com'/>", @mode
135
+ # login(:anon)
136
+ # end
137
+ #
138
+ # should 'redirect' do
139
+ # get_subject
140
+ # assert_redirected_to 'http://feature-space.com'
141
+ # end
142
+ # end # to redirect
143
+
144
+ context 'to update' do
145
+ setup do
146
+ @mode = 'ins'
147
+ make_template "<div id='foo' do='block'>hello <r:title/></div>", @mode
148
+ login(:anon)
149
+ # render page to build template
150
+ get 'show', :path => ["section#{nodes_zip(:people)}_#{@mode}.html"], :prefix => 'en'
151
+ assert_equal "<div id='foo'>hello people</div>", @response.body
152
+ end
153
+
154
+ should 'execute Element update' do
155
+ get 'zafu', {
156
+ :id => nodes_zip(:people),
157
+ :t_url => 'Default skin/Node-ins/foo',
158
+ :dom_id => 'foo',
159
+ }
160
+ assert_equal %Q{Element.replace("foo", "\\u003Cdiv id='foo'\\u003Ehello people\\u003C/div\\u003E");\n}, @response.body
161
+ end
162
+
163
+ context 'with insert' do
164
+ should 'execute Zena insert_inner' do
165
+ get 'zafu', {
166
+ :id => nodes_zip(:people),
167
+ :t_url => 'Default skin/Node-ins/foo',
168
+ :dom_id => 'foo',
169
+ :insert => 'bottom',
170
+ }
171
+ assert_equal %Q{Zena.insert_inner("foo", "bottom", "\\u003Cdiv id='foo'\\u003Ehello people\\u003C/div\\u003E");\n}, @response.body
172
+ end
173
+ end # with insert
174
+ end # to update
175
+ end # special rendering zafu
176
+
105
177
  context 'Custom rendering options on html' do
106
178
  subject do
107
179
  login(:lion)
@@ -76,6 +76,29 @@ class ScopeIndexTest < Zena::Unit::TestCase
76
76
  end
77
77
  end # creating a sub node
78
78
 
79
+ context 'deleting a sub node' do
80
+ setup do
81
+ secure(Node) { Node.create_node(:klass => 'Contact', :name => 'Life threat', :first_name => 'Earthquake', :parent_id => @project.zip, :v_status => Zena::Status[:pub])
82
+ }
83
+ end
84
+
85
+ subject do
86
+ secure(Node) { Node.create_node(:klass => 'Contact', :name => 'Life threat', :first_name => 'Fukushima', :parent_id => @project.zip, :v_status => Zena::Status[:pub])
87
+ }
88
+ end
89
+
90
+ should 'rebuild target indexes' do
91
+ assert_equal 'Earthquake', IdxProject.find(@project.scope_index).contact_first_name
92
+ subject
93
+ assert_equal 'Fukushima', IdxProject.find(@project.scope_index).contact_first_name
94
+ assert_difference('IdxProject.count', 0) do
95
+ subject.destroy
96
+ idx = IdxProject.find(@project.scope_index)
97
+ assert_equal 'Earthquake', idx.contact_first_name
98
+ end
99
+ end
100
+ end # deleting a sub node
101
+
79
102
  context 'moving a sub node' do
80
103
  subject do
81
104
  secure(Node) { VirtualClass['Contact'].create_instance(:first_name => 'Friedrich', :name => 'Hölderlin', :parent_id => nodes_id(:zena), :v_status => Zena::Status[:pub]) }
@@ -412,7 +435,7 @@ class ScopeIndexTest < Zena::Unit::TestCase
412
435
  vclass = VirtualClass.create(subject)
413
436
  assert_equal "Invalid entry: keys should be a String and query should be a String or an Array of strings (1 => \"project\")", vclass.errors[:idx_scope]
414
437
  end
415
-
438
+
416
439
  context 'with array keys' do
417
440
  subject do
418
441
  {:name => 'Song', :superclass => 'Post', :idx_scope => "{%w{self project} => 'project'}", :create_group_id => groups_id(:public) }
@@ -423,7 +446,7 @@ class ScopeIndexTest < Zena::Unit::TestCase
423
446
  assert_equal "Invalid rubyless: Invalid key type for hash (should be a literal value, was :array)", vclass.errors[:idx_scope]
424
447
  end
425
448
  end # with array keys
426
-
449
+
427
450
  end # with an invalid idx_scope
428
451
 
429
452
  context 'with an invalid idx_scope type' do
@@ -460,5 +483,17 @@ class ScopeIndexTest < Zena::Unit::TestCase
460
483
  end
461
484
  end # with an invalid query in idx_scope
462
485
  end # Creating a virtual class
486
+
487
+ context 'The VirtualClass class' do
488
+ subject do
489
+ VirtualClass
490
+ end
463
491
 
492
+ should 'contain scopes in export attributes' do
493
+ assert subject.export_attributes.include?('idx_class')
494
+ assert subject.export_attributes.include?('idx_scope')
495
+ assert subject.export_attributes.include?('idx_reverse_scope')
496
+ end
497
+ end # A VirtualClass
498
+
464
499
  end
@@ -27,6 +27,16 @@ class UrlsTest < Zena::View::TestCase
27
27
  assert_equal '/en/projects-list/Clean-Water-project/page22_test.html', zen_path(node, :mode=>'test')
28
28
  end
29
29
 
30
+ def test_zen_path_custom_base_with_accents
31
+ # See also test in NodesController
32
+ login(:lion)
33
+ node = secure!(Node) { nodes(:cleanWater) }
34
+ node.update_attributes(:title => 'Lignes aériennes')
35
+ assert_equal '/oo/projects-list/Lignes-a%C3%A9riennes', zen_path(node)
36
+ # Make sure this is parsed back correctly
37
+ assert_match Zena::Use::Urls::ALLOWED_REGEXP, zen_path(node).split('/').last
38
+ end
39
+
30
40
  def test_zen_path_query_params
31
41
  login(:anon)
32
42
  node = secure!(Node) { nodes(:status) }
@@ -137,7 +137,7 @@ class ZazenTest < Zena::View::TestCase
137
137
  end
138
138
 
139
139
  def test_pseudo_id
140
- assert_zazen_match "a[@href='/en/contact15.html'][text()='people/Panthera Leo Verneyi']", 'This is a "link"::lio.'
140
+ assert_zazen_match "a[@href='/en/contact15.html'][text()='people/Panthera Leo Verneyi']", 'This is a "link"::Leo.'
141
141
  assert_zazen_match "a[@href='/en/image30_pv.jpg?967816914293'][text()='projects list/a wiki with Zena/bird_pv.jpg']", 'This is a "link"::bir_pv.data.'
142
142
  end
143
143
 
@@ -229,10 +229,10 @@ class ZazenTest < Zena::View::TestCase
229
229
  projects = secure!(Node) { nodes(:projects) }
230
230
  zena = secure!(Node) { nodes(:zena) }
231
231
  assert_equal "This \"is\":33 \"a\":#{nodes_zip(:wiki)} !#{nodes_zip(:bird_jpg)}! \"link\":#{nodes_zip(:lion)}.",
232
- zazen('This "is":33 "a":(projects list/a wiki with Zena) !(projects list/a wiki with Zena/bird)! "link"::lio.', :translate_ids => :zip, :node => zena)
232
+ zazen('This "is":33 "a":(projects list/a wiki with Zena) !(projects list/a wiki with Zena/bird)! "link"::Leo.', :translate_ids => :zip, :node => zena)
233
233
 
234
234
  assert_equal 'This "is":(../Collections/Art) "a":(a wiki with Zena) !(a wiki with Zena/bird)! !{(a wiki with Zena/bird)}! ![(a wiki with Zena/bird)]! "link":(../people/Panthera Leo Verneyi).',
235
- zazen('This "is":33 "a":(/projects list/a wiki with Zena) !30! !{30}! ![30]! "link"::lio.', :translate_ids => :relative_path, :node => projects)
235
+ zazen('This "is":33 "a":(/projects list/a wiki with Zena) !30! !{30}! ![30]! "link"::Leo.', :translate_ids => :relative_path, :node => projects)
236
236
 
237
237
  assert_equal "This \"is\":33 \"a\":#{nodes_zip(:wiki)} !#{nodes_zip(:bird_jpg)}! \"link\":#{nodes_zip(:lion)}.",
238
238
  zazen('This "is":(../Collections/Art) "a":(a wiki with Zena) !(a wiki with Zena/bird)! "link":(../people/Panthera Leo Verneyi).', :translate_ids => :zip, :node => projects)
@@ -0,0 +1,11 @@
1
+ source :rubygems
2
+
3
+ gem 'fast_gettext'
4
+
5
+ group :dev do
6
+ gem 'sqlite3'
7
+ gem 'rails', '~>3'
8
+ gem 'rake'
9
+ gem 'rspec', '~>2'
10
+ gem 'jeweler'
11
+ end
@@ -0,0 +1,92 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.4)
6
+ actionpack (= 3.0.4)
7
+ mail (~> 2.2.15)
8
+ actionpack (3.0.4)
9
+ activemodel (= 3.0.4)
10
+ activesupport (= 3.0.4)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.4)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.13)
16
+ rack-test (~> 0.5.7)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.4)
19
+ activesupport (= 3.0.4)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.4)
22
+ activerecord (3.0.4)
23
+ activemodel (= 3.0.4)
24
+ activesupport (= 3.0.4)
25
+ arel (~> 2.0.2)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.4)
28
+ activemodel (= 3.0.4)
29
+ activesupport (= 3.0.4)
30
+ activesupport (3.0.4)
31
+ arel (2.0.8)
32
+ builder (2.1.2)
33
+ diff-lcs (1.1.2)
34
+ erubis (2.6.6)
35
+ abstract (>= 1.0.0)
36
+ fast_gettext (0.5.10)
37
+ git (1.2.5)
38
+ i18n (0.5.0)
39
+ jeweler (1.5.2)
40
+ bundler (~> 1.0.0)
41
+ git (>= 1.2.5)
42
+ rake
43
+ mail (2.2.15)
44
+ activesupport (>= 2.3.6)
45
+ i18n (>= 0.4.0)
46
+ mime-types (~> 1.16)
47
+ treetop (~> 1.4.8)
48
+ mime-types (1.16)
49
+ polyglot (0.3.1)
50
+ rack (1.2.1)
51
+ rack-mount (0.6.13)
52
+ rack (>= 1.0.0)
53
+ rack-test (0.5.7)
54
+ rack (>= 1.0)
55
+ rails (3.0.4)
56
+ actionmailer (= 3.0.4)
57
+ actionpack (= 3.0.4)
58
+ activerecord (= 3.0.4)
59
+ activeresource (= 3.0.4)
60
+ activesupport (= 3.0.4)
61
+ bundler (~> 1.0)
62
+ railties (= 3.0.4)
63
+ railties (3.0.4)
64
+ actionpack (= 3.0.4)
65
+ activesupport (= 3.0.4)
66
+ rake (>= 0.8.7)
67
+ thor (~> 0.14.4)
68
+ rake (0.8.7)
69
+ rspec (2.5.0)
70
+ rspec-core (~> 2.5.0)
71
+ rspec-expectations (~> 2.5.0)
72
+ rspec-mocks (~> 2.5.0)
73
+ rspec-core (2.5.1)
74
+ rspec-expectations (2.5.0)
75
+ diff-lcs (~> 1.1.2)
76
+ rspec-mocks (2.5.0)
77
+ sqlite3 (1.3.3)
78
+ thor (0.14.6)
79
+ treetop (1.4.9)
80
+ polyglot (>= 0.3.1)
81
+ tzinfo (0.3.24)
82
+
83
+ PLATFORMS
84
+ ruby
85
+
86
+ DEPENDENCIES
87
+ fast_gettext
88
+ jeweler
89
+ rails (~> 3)
90
+ rake
91
+ rspec (~> 2)
92
+ sqlite3
@@ -1,32 +1,27 @@
1
- require 'spec/rake/spectask'
2
- Spec::Rake::SpecTask.new {|t| t.spec_opts = ['--color']}
1
+ require "rspec/core/rake_task"
2
+ RSpec::Core::RakeTask.new(:spec) do |t|
3
+ t.rspec_opts = '--backtrace --color'
4
+ end
3
5
 
4
- task :default do
5
- # test with 2.x
6
- puts `VERSION='~>2' rake spec RSPEC_COLOR=1`
6
+ task :rails2 do
7
+ sh "cd spec/rails2 && RAILS=rails rspec ../../spec"
8
+ end
7
9
 
8
- # gem 'activerecord', '>=3' did not work for me, but just require gets the right version...
9
- require 'active_record'
10
- if ActiveRecord::VERSION::MAJOR >= 3
11
- puts `rake spec RSPEC_COLOR=1`
12
- else
13
- 'install rails 3 to get full test coverage...'
14
- end
10
+ task :default do
11
+ sh "rake spec && rake rails2"
15
12
  end
16
13
 
17
14
  begin
18
15
  require 'jeweler'
19
- project_name = 'gettext_i18n_rails'
20
16
  Jeweler::Tasks.new do |gem|
21
- gem.name = project_name
17
+ gem.name = 'gettext_i18n_rails'
22
18
  gem.summary = "Simple FastGettext Rails integration."
23
19
  gem.email = "grosser.michael@gmail.com"
24
- gem.homepage = "http://github.com/grosser/#{project_name}"
20
+ gem.homepage = "http://github.com/grosser/#{gem.name}"
25
21
  gem.authors = ["Michael Grosser"]
26
- gem.add_dependency 'fast_gettext'
27
22
  end
28
23
 
29
24
  Jeweler::GemcutterTasks.new
30
25
  rescue LoadError
31
26
  puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
32
- end
27
+ end
@@ -0,0 +1,215 @@
1
+ [FastGettext](http://github.com/grosser/fast_gettext) / Rails integration.
2
+
3
+ Translate via FastGettext, use any other I18n backend as extension/fallback.
4
+
5
+ Rails does: `I18n.t('syntax.with.lots.of.dots')` with nested yml files
6
+ We do: `_('Just translate my damn text!')` with simple, flat mo/po/yml files or directly from db
7
+ To use I18n calls add a `syntax.with.lots.of.dots` translation.
8
+
9
+ [See it working in the example application.](https://github.com/grosser/gettext_i18n_rails_example)
10
+
11
+ Setup
12
+ =====
13
+ ### Installation
14
+
15
+ #### Rails 3
16
+
17
+ ##### As plugin:
18
+
19
+ rails plugin install git://github.com/grosser/gettext_i18n_rails.git
20
+
21
+ # Gemfile
22
+ gem 'fast_gettext', '>=0.4.8'
23
+
24
+ ##### As gem:
25
+
26
+ # Gemfile
27
+ gem 'gettext_i18n_rails'
28
+
29
+ ##### Optional:
30
+ If you want to find translations or build .mo files
31
+ # Gemfile
32
+ gem 'gettext', '>=1.9.3', :require => false, :group => :development
33
+
34
+ #### Rails 2
35
+
36
+ ##### As plugin:
37
+
38
+ script/plugin install git://github.com/grosser/gettext_i18n_rails.git
39
+ sudo gem install fast_gettext
40
+
41
+ # config/environment.rb
42
+ config.gem "fast_gettext", :version => '>=0.4.8'
43
+
44
+ ##### As gem:
45
+
46
+ gem install gettext_i18n_rails
47
+
48
+ # config/environment.rb
49
+ config.gem 'gettext_i18n_rails'
50
+
51
+ #Rakefile
52
+ begin
53
+ require "gettext_i18n_rails/tasks"
54
+ rescue LoadError
55
+ puts "gettext_i18n_rails is not installed, you probably should run 'rake gems:install' or 'bundle install'."
56
+ end
57
+
58
+ ##### Optional:
59
+ If you want to find translations or build .mo files
60
+ # config/environments/development.rb
61
+ config.gem "gettext", :version => '>=1.9.3', :lib => false
62
+
63
+ ### Locales & initialisation
64
+ Copy default locales with dates/sentence-connectors/AR-errors you want from e.g.
65
+ [rails i18n](http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale/) into 'config/locales'
66
+
67
+ To initialize:
68
+
69
+ # config/initializers/fast_gettext.rb
70
+ FastGettext.add_text_domain 'app', :path => 'locale', :type => :po
71
+ FastGettext.default_available_locales = ['en','de'] #all you want to allow
72
+ FastGettext.default_text_domain = 'app'
73
+
74
+ And in your application:
75
+
76
+ # app/controllers/application_controller.rb
77
+ class ApplicationController < ...
78
+ before_filter :set_gettext_locale
79
+
80
+ Translating
81
+ ===========
82
+ Performance is almost the same for all backends since translations are cached after first use.
83
+
84
+ ### Option A: .po files
85
+
86
+ FastGettext.add_text_domain 'app', :path => 'locale', :type => :po
87
+
88
+ - use some _('translations')
89
+ - run `rake gettext:find`, to let GetText find all translations used
90
+ - (optional) run `rake gettext:store_model_attributes`, to parse the database for columns that can be translated
91
+ - if this is your first translation: `cp locale/app.pot locale/de/app.po` for every locale you want to use
92
+ - translate messages in 'locale/de/app.po' (leave msgstr blank and msgstr == msgid)
93
+
94
+ New translations will be marked "fuzzy", search for this and remove it, so that they will be used.
95
+ Obsolete translations are marked with ~#, they usually can be removed since they are no longer needed
96
+
97
+ #### Unfound translations with rake gettext:find
98
+ Dynamic translations like `_("x"+"u")` cannot be fond. You have 4 options:
99
+
100
+ - add `N_('xu')` somewhere else in the code, so the parser sees it
101
+ - add `N_('xu')` in a totally separate file like `locale/unfound_translations.rb`, so the parser sees it
102
+ - use the [gettext_test_log rails plugin ](http://github.com/grosser/gettext_test_log) to find all translations that where used while testing
103
+ - add a Logger to a translation Chain, so every unfound translations is logged ([example]((http://github.com/grosser/fast_gettext)))
104
+
105
+ ### Option B: Traditional .po/.mo files
106
+
107
+ FastGettext.add_text_domain 'app', :path => 'locale'
108
+
109
+ - follow Option A
110
+ - run `rake gettext:pack` to write binary GetText .mo files
111
+
112
+ ### Option C: Database
113
+ Most scalable method, all translators can work simultaneously and online.
114
+
115
+ Easiest to use with the [translation database Rails engine](http://github.com/grosser/translation_db_engine).
116
+ Translations can be edited under `/translation_keys`
117
+
118
+ FastGettext::TranslationRepository::Db.require_models
119
+ FastGettext.add_text_domain 'app', :type => :db, :model => TranslationKey
120
+
121
+ I18n
122
+ ====
123
+ I18n.locale <==> FastGettext.locale.to_sym
124
+ I18n.locale = :de <==> FastGettext.locale = 'de'
125
+
126
+ Any call to I18n that matches a gettext key will be translated through FastGettext.
127
+
128
+ Namespaces
129
+ ==========
130
+ Car|Model means Model in namespace Car.
131
+ You do not have to translate this into english "Model", if you use the
132
+ namespace-aware translation
133
+ s_('Car|Model') == 'Model' #when no translation was found
134
+
135
+ XSS / html_safe
136
+ ===============
137
+ If you trust your translators and all your usages of % on translations:<br/>
138
+ # config/environment.rb
139
+ GettextI18nRails.translations_are_html_safe = true
140
+
141
+ String % vs html_safe is buggy (can be used for XSS on 1.8 and is always non-safe in 1.9)<br/>
142
+ My recommended fix is: `require 'gettext_i18n_rails/string_interpolate_fix'`
143
+
144
+ - safe stays safe (escape added strings)
145
+ - unsafe stays unsafe (do not escape added strings)
146
+
147
+ ActiveRecord - error messages
148
+ =============================
149
+ ActiveRecord error messages are translated through Rails::I18n, but
150
+ model names and model attributes are translated through FastGettext.
151
+ Therefore a validation error on a BigCar's wheels_size needs `_('big car')` and `_('BigCar|Wheels size')`
152
+ to display localized.
153
+
154
+ The model/attribute translations can be found through `rake gettext:store_model_attributes`,
155
+ (which ignores some commonly untranslated columns like id,type,xxx_count,...).
156
+
157
+ Error messages can be translated through FastGettext, if the ':message' is a translation-id or the matching Rails I18n key is translated.
158
+
159
+ ####Option A:
160
+ Define a translation for "I need my rating!" and use it as message.
161
+ validates_inclusion_of :rating, :in=>1..5, :message=>N_('I need my rating!')
162
+
163
+ ####Option B:
164
+ validates_inclusion_of :rating, :in=>1..5
165
+ Make a translation for the I18n key: `activerecord.errors.models.rating.attributes.rating.inclusion`
166
+
167
+ ####Option C:
168
+ Add a translation to each config/locales/*.yml files
169
+ en:
170
+ activerecord:
171
+ errors:
172
+ models:
173
+ rating:
174
+ attributes:
175
+ rating:
176
+ inclusion: " -- please choose!"
177
+ The [rails I18n guide](http://guides.rubyonrails.org/i18n.html) can help with Option B and C.
178
+
179
+ Plurals
180
+ =======
181
+ FastGettext supports pluralization
182
+ n_('Apple','Apples',3) == 'Apples'
183
+
184
+ Abnormal plurals like e.g. Polish that has 4 different can also be addressed, see [FastGettext Readme](http://github.com/grosser/fast_gettext)
185
+
186
+ Customizing list of translatable files
187
+ ======================================
188
+ When you run
189
+
190
+ rake gettext:find
191
+
192
+ by default the following files are going to be scanned for translations: {app,lib,config,locale}/**/*.{rb,erb,haml}. If
193
+ you want to specify a different list, you can redefine files_to_translate in the gettext namespace in a file like
194
+ lib/tasks/gettext.rake:
195
+
196
+ namespace :gettext do
197
+ def files_to_translate
198
+ Dir.glob("{app,lib,config,locale}/**/*.{rb,erb,haml,rhtml}")
199
+ end
200
+ end
201
+
202
+ [Contributors](http://github.com/grosser/gettext_i18n_rails/contributors)
203
+ ======
204
+ - [ruby gettext extractor](http://github.com/retoo/ruby_gettext_extractor/tree/master) from [retoo](http://github.com/retoo)
205
+ - [Paul McMahon](http://github.com/pwim)
206
+ - [Duncan Mac-Vicar P](http://duncan.mac-vicar.com/blog)
207
+ - [Ramihajamalala Hery](http://my.rails-royce.org)
208
+ - [J. Pablo Fernández](http://pupeno.com)
209
+ - [Anh Hai Trinh](http://blog.onideas.ws)
210
+ - [ed0h](http://github.com/ed0h)
211
+ - [Nikos Dimitrakopoulos](http://blog.nikosd.com)
212
+
213
+ [Michael Grosser](http://grosser.it)<br/>
214
+ grosser.michael@gmail.com<br/>
215
+ Hereby placed under public domain, do what you want, just do not hold me accountable...
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.2.19