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.
- data/History.txt +23 -0
- data/README.rdoc +1 -1
- data/app/controllers/columns_controller.rb +3 -31
- data/app/controllers/comments_controller.rb +8 -3
- data/app/controllers/data_entries_controller.rb +1 -1
- data/app/controllers/documents_controller.rb +2 -2
- data/app/controllers/nodes_controller.rb +29 -12
- data/app/controllers/relations_controller.rb +2 -2
- data/app/controllers/sites_controller.rb +1 -1
- data/app/controllers/user_sessions_controller.rb +6 -3
- data/app/controllers/users_controller.rb +18 -16
- data/app/controllers/versions_controller.rb +20 -18
- data/app/controllers/virtual_classes_controller.rb +103 -17
- data/app/helpers/users_helper.rb +1 -1
- data/app/models/column.rb +19 -50
- data/app/models/comment.rb +2 -1
- data/app/models/node.rb +45 -22
- data/app/models/relation.rb +13 -0
- data/app/models/relation_proxy.rb +3 -2
- data/app/models/role.rb +213 -4
- data/app/models/site.rb +18 -11
- data/app/models/template.rb +37 -35
- data/app/models/version.rb +1 -1
- data/app/models/virtual_class.rb +154 -86
- data/app/views/columns/_li.html.erb +1 -1
- data/app/views/columns/index.html.erb +1 -9
- data/app/views/comments/index.rhtml +10 -8
- data/app/views/documents/_crop.rhtml +5 -6
- data/app/views/documents/crop_form.rjs +3 -2
- data/app/views/groups/index.rhtml +1 -1
- data/app/views/iformats/index.rhtml +1 -1
- data/app/views/nodes/_import_results.rhtml +1 -1
- data/app/views/nodes/_parent.rhtml +1 -2
- data/app/views/nodes/update.rjs +3 -4
- data/app/views/relations/index.erb +1 -1
- data/app/views/sites/index.erb +1 -1
- data/app/views/templates/drive_tabs/_drive.rhtml +0 -2
- data/app/views/templates/edit_tabs/_image.rhtml +1 -1
- data/app/views/templates/edit_tabs/_title.rhtml +0 -6
- data/app/views/users/index.rhtml +1 -1
- data/app/views/users/preferences.html.erb +2 -2
- data/app/views/versions/backup.rjs +1 -1
- data/app/views/versions/custom_tab.rhtml +9 -4
- data/app/views/versions/destroy.rjs +2 -2
- data/app/views/versions/update.rjs +2 -9
- data/app/views/virtual_classes/_form.erb +3 -2
- data/app/views/virtual_classes/import_prepare.html.erb +13 -0
- data/app/views/virtual_classes/index.erb +28 -8
- data/app/views/zafu/default/Node-+adminLayout.zafu +1 -13
- data/app/views/zafu/default/Node-+login.zafu +1 -0
- data/app/views/zafu/default/Node-+notFound.zafu +1 -1
- data/app/views/zafu/default/Node-+popupLayout.zafu +1 -2
- data/app/views/zafu/default/Node-+search.zafu +1 -1
- data/app/views/zafu/default/Node-admin.zafu +205 -0
- data/app/views/zafu/default/Node.zafu +11 -11
- data/bricks/captcha/lib/bricks/captcha.rb +3 -2
- data/bricks/mongrel/zena/init.rb +2 -1
- data/bricks/pdf/README +5 -5
- data/bricks/pdf/lib/bricks/pdf/engine/prince.rb +2 -2
- data/bricks/pdf/lib/bricks/pdf/engine/xhtml2pdf.rb +2 -2
- data/bricks/pdf/lib/bricks/pdf/install.rb +5 -5
- data/bricks/pdf/lib/bricks/pdf.rb +11 -11
- data/bricks/pdf/test/engines/test_prince.rb +4 -4
- data/bricks/pdf/test/engines/test_xhtml2pdf.rb +4 -4
- data/bricks/pdf/test/shoulda_macros/shoulda_pdf.rb +2 -2
- data/bricks/pdf/zena/init.rb +2 -2
- data/bricks/pdf/zena/tasks.rb +2 -2
- data/bricks/sphinx/lib/bricks/sphinx.rb +6 -2
- data/bricks/sphinx/zena/{sphinx.yml → sphinx.yml.erb} +2 -2
- data/bricks/sphinx/zena/tasks.rb +28 -2
- data/bricks/tags/lib/bricks/tags.rb +16 -1
- data/bricks/tags/zena/test/unit/tags_test.rb +15 -0
- data/bricks/tags/zena/test/zafu/tags.yml +5 -1
- data/bricks/worker/lib/bricks/worker.rb +39 -0
- data/bricks/worker/zena/deploy.rb +0 -2
- data/bricks/worker/zena/init.rb +1 -0
- data/bricks/worker/zena/test/sites/zena/delayed_jobs.yml +16 -0
- data/bricks/worker/zena/test/zafu/worker.yml +8 -0
- data/bricks/zena/zena/migrate/01_base.rb +36 -60
- data/bricks/zena/zena/migrate/02_zerox1_schema.rb +388 -0
- data/bricks/zena/zena/migrate/03_zerox1_data.rb +380 -0
- data/bricks/zena/zena/migrate/20110315161158_add_reverse_scope_to_roles.rb +9 -0
- data/config/database_example.yml +1 -1
- data/config/environment.rb +1 -1
- data/config/gems.yml +17 -14
- data/db/init/base/skins/default/Node-+index.zafu +8 -1
- data/db/init/base/skins/default/Node-+login.zafu +1 -0
- data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -2
- data/db/init/base/skins/default/Node-+search.zafu +2 -2
- data/db/init/base/skins/default/Node.zafu +9 -9
- data/db/init/base/skins/default/{favicon.png → img/favicon.png} +0 -0
- data/db/init/base/skins/default/{style.css → img/style.css} +0 -0
- data/db/init/base/skins/default/img/translations.yml +11 -0
- data/db/init/base/skins/default/notes.zafu +7 -9
- data/doc/zafu_changes.yml +12 -0
- data/lib/bricks/loader.rb +38 -15
- data/lib/tasks/zena.rake +74 -24
- data/lib/zena/acts/enrollable.rb +4 -1
- data/lib/zena/acts/secure.rb +2 -48
- data/lib/zena/acts/serializable.rb +13 -1
- data/lib/zena/app.rb +9 -0
- data/lib/zena/code_syntax.rb +154 -151
- data/lib/zena/console.rb +141 -0
- data/lib/zena/controller/test_case.rb +1 -1
- data/lib/zena/db_helper/abstract_db.rb +17 -5
- data/lib/zena/db_helper/mysql.rb +14 -12
- data/lib/zena/db_helper/postgresql.rb +1 -2
- data/lib/zena/db_helper/sqlite3.rb +6 -6
- data/lib/zena/deploy/awstats.conf.rhtml +1 -1
- data/lib/zena/deploy/httpd.rhtml +6 -1
- data/lib/zena/deploy/vhost.rhtml +9 -1
- data/lib/zena/deploy.rb +12 -7
- data/lib/zena/foxy_parser.rb +3 -1
- data/lib/zena/info.rb +1 -1
- data/lib/zena/parser/zafu_tags.rb +1 -0
- data/lib/zena/parser/zazen_rules.rb +1 -1
- data/lib/zena/remote/node.rb +15 -3
- data/lib/zena/remote/serializable_array.rb +19 -0
- data/lib/zena/remote.rb +1 -0
- data/lib/zena/routes.rb +7 -2
- data/lib/zena/site_worker.rb +11 -1
- data/lib/zena/unit/test_case.rb +68 -0
- data/lib/zena/use/action.rb +6 -2
- data/lib/zena/use/ajax.rb +127 -53
- data/lib/zena/use/ancestry.rb +11 -8
- data/lib/zena/use/calendar.rb +265 -129
- data/lib/zena/use/conditional.rb +1 -1
- data/lib/zena/use/context.rb +5 -5
- data/lib/zena/use/dates.rb +172 -60
- data/lib/zena/use/display.rb +70 -39
- data/lib/zena/use/error_rendering.rb +1 -3
- data/lib/zena/use/field_index.rb +4 -1
- data/lib/zena/use/forms.rb +94 -72
- data/lib/zena/use/fulltext.rb +16 -24
- data/lib/zena/use/html_tags.rb +20 -12
- data/lib/zena/use/i18n.rb +37 -37
- data/lib/zena/use/image_builder.rb +8 -1
- data/lib/zena/use/ml_index.rb +16 -16
- data/lib/zena/use/prop_eval.rb +10 -5
- data/lib/zena/use/query_builder.rb +55 -23
- data/lib/zena/use/query_node.rb +51 -25
- data/lib/zena/use/refactor.rb +2 -28
- data/lib/zena/use/relations.rb +1 -1
- data/lib/zena/use/rendering.rb +29 -0
- data/lib/zena/use/scope_index.rb +75 -14
- data/lib/zena/use/search.rb +5 -10
- data/lib/zena/use/test_helper.rb +2 -2
- data/lib/zena/use/urls.rb +125 -104
- data/lib/zena/use/workflow.rb +2 -1
- data/lib/zena/use/zafu_attributes.rb +2 -2
- data/lib/zena/use/zafu_safe_definitions.rb +20 -0
- data/lib/zena/use/zafu_templates.rb +20 -6
- data/lib/zena/use/zazen.rb +31 -20
- data/lib/zena/view/test_case.rb +5 -0
- data/lib/zena/zafu_compiler.rb +24 -2
- data/lib/zena.rb +12 -6
- data/locale/de/LC_MESSAGES/zena.mo +0 -0
- data/locale/de/zena.po +1345 -1164
- data/locale/en/LC_MESSAGES/zena.mo +0 -0
- data/locale/en/zena.po +1275 -1129
- data/locale/fr/LC_MESSAGES/zena.mo +0 -0
- data/locale/fr/zena.mo +0 -0
- data/locale/fr/zena.po +1617 -1441
- data/locale/log.txt +9 -0
- data/locale/zena.pot +957 -748
- data/public/javascripts/prototype.js +1 -1
- data/public/javascripts/zena.js +99 -44
- data/public/stylesheets/admin.css +6 -4
- data/public/stylesheets/backend.css +71 -0
- data/public/stylesheets/calendar.css +24 -25
- data/public/stylesheets/code.css +11 -6
- data/public/stylesheets/comment.css +2 -1
- data/public/stylesheets/popup.css +7 -8
- data/test/custom_queries/complex.host.yml +15 -1
- data/test/fixtures/files/Node-test.zafu +29 -28
- data/test/fixtures/files/translations_de.yml +12 -1
- data/test/fixtures/files/translations_fr.yml +12 -1
- data/test/functional/comments_controller_test.rb +9 -0
- data/test/functional/iformats_controller_test.rb +1 -1
- data/test/functional/nodes_controller_test.rb +124 -35
- data/test/functional/users_controller_test.rb +132 -3
- data/test/functional/virtual_classes_controller_test.rb +75 -4
- data/test/integration/navigation_test.rb +51 -9
- data/test/integration/query_node/basic.yml +19 -7
- data/test/integration/query_node/complex.yml +1 -1
- data/test/integration/query_node/dates.yml +27 -1
- data/test/integration/query_node/filters.yml +1 -1
- data/test/integration/query_node/relations.yml +13 -4
- data/test/integration/query_node_test.rb +4 -0
- data/test/integration/xml_api_test.rb +6 -1
- data/test/integration/zafu_compiler/action.yml +3 -3
- data/test/integration/zafu_compiler/ajax.yml +103 -22
- data/test/integration/zafu_compiler/basic.yml +0 -52
- data/test/integration/zafu_compiler/calendar.yml +44 -20
- data/test/integration/zafu_compiler/comments.yml +53 -0
- data/test/integration/zafu_compiler/complex.yml +11 -11
- data/test/integration/zafu_compiler/complex_ok.yml +16 -3
- data/test/integration/zafu_compiler/conditional.yml +15 -5
- data/test/integration/zafu_compiler/context.yml +9 -0
- data/test/integration/zafu_compiler/dates.yml +43 -15
- data/test/integration/zafu_compiler/display.yml +60 -6
- data/test/integration/zafu_compiler/errors.yml +6 -2
- data/test/integration/zafu_compiler/forms.yml +45 -6
- data/test/integration/zafu_compiler/i18n.yml +8 -1
- data/test/integration/zafu_compiler/meta.yml +38 -0
- data/test/integration/zafu_compiler/query.yml +43 -4
- data/test/integration/zafu_compiler/relations.yml +26 -33
- data/test/integration/zafu_compiler/rubyless.yml +10 -0
- data/test/integration/zafu_compiler/safe_definitions.yml +21 -1
- data/test/integration/zafu_compiler/urls.yml +75 -5
- data/test/integration/zafu_compiler/version.yml +2 -2
- data/test/integration/zafu_compiler/zafu_attributes.yml +5 -1
- data/test/integration/zafu_compiler/zazen.yml +14 -6
- data/test/integration/zafu_compiler_test.rb +5 -1
- data/test/sites/complex/columns.yml +5 -0
- data/test/sites/complex/roles.yml +4 -0
- data/test/sites/zena/nodes.yml +13 -2
- data/test/sites/zena/roles.yml +13 -5
- data/test/sites/zena/versions.yml +27 -9
- data/test/unit/column_test.rb +51 -5
- data/test/unit/iformat_test.rb +2 -2
- data/test/unit/node_test.rb +29 -17
- data/test/unit/note_test.rb +1 -1
- data/test/unit/relation_proxy_test.rb +4 -5
- data/test/unit/relation_test.rb +16 -0
- data/test/unit/remote_test.rb +2 -2
- data/test/unit/role_test.rb +292 -4
- data/test/unit/site_test.rb +12 -0
- data/test/unit/template_test.rb +1 -1
- data/test/unit/text_document_test.rb +1 -1
- data/test/unit/virtual_class_test.rb +200 -83
- data/test/unit/zena/acts/enrollable_test.rb +26 -31
- data/test/unit/zena/use/calendar_test.rb +90 -37
- data/test/unit/zena/use/field_index_test.rb +28 -0
- data/test/unit/zena/use/html_tags_test.rb +7 -3
- data/test/unit/zena/use/ml_index_test.rb +2 -16
- data/test/unit/zena/use/nested_attributes_alias_view_test.rb +2 -2
- data/test/unit/zena/use/prop_eval_test.rb +50 -8
- data/test/unit/zena/use/query_node_test.rb +11 -0
- data/test/unit/zena/use/rendering_test.rb +72 -0
- data/test/unit/zena/use/scope_index_test.rb +37 -2
- data/test/unit/zena/use/urls_test.rb +10 -0
- data/test/unit/zena/use/zazen_test.rb +3 -3
- data/vendor/plugins/gettext_i18n_rails/Gemfile +11 -0
- data/vendor/plugins/gettext_i18n_rails/Gemfile.lock +92 -0
- data/vendor/plugins/gettext_i18n_rails/Rakefile +12 -17
- data/vendor/plugins/gettext_i18n_rails/Readme.md +215 -0
- data/vendor/plugins/gettext_i18n_rails/VERSION +1 -1
- data/vendor/plugins/gettext_i18n_rails/gettext_i18n_rails.gemspec +38 -34
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/active_record.rb +1 -1
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/backend.rb +30 -14
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/haml_parser.rb +1 -1
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/html_safe_translations.rb +29 -0
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/i18n_hacks.rb +29 -1
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/model_attributes_finder.rb +7 -1
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/railtie.rb +10 -0
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/ruby_gettext_extractor.rb +6 -2
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/string_interpolate_fix.rb +20 -0
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/tasks.rb +120 -0
- data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails.rb +10 -3
- data/vendor/plugins/gettext_i18n_rails/lib/tasks/gettext_rails_i18n.rake +1 -74
- data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/active_record_spec.rb +51 -20
- data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/backend_spec.rb +12 -7
- data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb +32 -0
- data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails_spec.rb +38 -1
- data/vendor/plugins/gettext_i18n_rails/spec/rails2/Gemfile +11 -0
- data/vendor/plugins/gettext_i18n_rails/spec/spec_helper.rb +1 -8
- data/zena.gemspec +2241 -2217
- metadata +123 -83
- data/.gitignore +0 -36
- data/app/views/nodes/_dates.rhtml +0 -13
- data/db/init/base/skins/default/Node-+adminLayout.zafu +0 -46
- data/db/init/base/skins/default/Node-tree.zafu +0 -19
- data/vendor/plugins/gettext_i18n_rails/README.markdown +0 -143
@@ -5,14 +5,20 @@ module Zena
|
|
5
5
|
module ViewMethods
|
6
6
|
include RubyLess
|
7
7
|
safe_method [:query_parse, String] => {:class => String, :accept_nil => true}
|
8
|
+
safe_method :query_errors => {:class => String, :nil => true}
|
8
9
|
|
9
10
|
def find_node_by_zip(zip)
|
10
11
|
return nil unless zip
|
11
12
|
secure(Node) { Node.find_by_zip(zip) }
|
12
13
|
end
|
13
14
|
|
15
|
+
def query_errors
|
16
|
+
@query_errors
|
17
|
+
end
|
18
|
+
|
14
19
|
def query(class_name, node_name, pseudo_sql, opts = {})
|
15
20
|
type = opts[:type] || :find
|
21
|
+
@query_errors = nil
|
16
22
|
if klass = VirtualClass[class_name]
|
17
23
|
begin
|
18
24
|
query = klass.build_query(:all, pseudo_sql,
|
@@ -28,7 +34,7 @@ module Zena
|
|
28
34
|
return klass.do_find(:all, eval(query.to_s))
|
29
35
|
end
|
30
36
|
rescue ::QueryBuilder::Error => err
|
31
|
-
|
37
|
+
@query_errors = "<span class='query'>#{pseudo_sql}</span> <span class='error'>#{err}</span>"
|
32
38
|
end
|
33
39
|
end
|
34
40
|
# error
|
@@ -71,6 +77,7 @@ module Zena
|
|
71
77
|
end
|
72
78
|
|
73
79
|
if arg =~ DATE_FIELD_REGEXP
|
80
|
+
# FIXME: Use to_utc and date function in Zena::Db
|
74
81
|
arg = query_parse_dates(arg)
|
75
82
|
first = arg.first
|
76
83
|
end
|
@@ -202,7 +209,7 @@ module Zena
|
|
202
209
|
|
203
210
|
# Resolve unknown methods by trying to build a pseudo-sql query with QueryBuilder.
|
204
211
|
def querybuilder_eval(method = @method)
|
205
|
-
|
212
|
+
node = single_node
|
206
213
|
|
207
214
|
if method =~ /^\d+$/
|
208
215
|
finder = {:method => "find_node_by_zip(#{method})", :class => Node, :nil => true}
|
@@ -234,34 +241,54 @@ module Zena
|
|
234
241
|
def node_context_vars(finder)
|
235
242
|
sub_context = super
|
236
243
|
query = finder[:query]
|
237
|
-
if query && (pagination_key = query.pagination_key)
|
238
|
-
set_context_var('paginate', 'key', pagination_key, sub_context)
|
239
|
-
|
244
|
+
if query && ((pagination_key = query.pagination_key) || child['count'])
|
240
245
|
node_count = get_var_name('paginate', 'nodes', sub_context)
|
241
|
-
page_count = get_var_name('paginate', 'count', sub_context)
|
242
|
-
curr_page = get_var_name('paginate', 'current', sub_context)
|
243
|
-
|
244
|
-
# Give access to the page number through the pagination key.
|
245
|
-
set_context_var('set_var', pagination_key, RubyLess::TypedString.new(curr_page, Number))
|
246
|
-
# Give access to page_count and count
|
247
|
-
# FIXME: DOC
|
248
|
-
set_context_var('set_var', 'page_count', RubyLess::TypedString.new(page_count, Number))
|
249
246
|
set_context_var('set_var', 'count', RubyLess::TypedString.new(node_count, Number))
|
250
247
|
|
251
|
-
|
248
|
+
res = "#{node_count} = Node.do_find(:count, #{query.to_s(:count)})"
|
249
|
+
if pagination_key
|
250
|
+
# Full pagination needed
|
251
|
+
set_context_var('paginate', 'key', pagination_key, sub_context)
|
252
|
+
|
253
|
+
page_count = get_var_name('paginate', 'count', sub_context)
|
254
|
+
curr_page = get_var_name('paginate', 'current', sub_context)
|
255
|
+
|
256
|
+
# Give access to the page number through the pagination key.
|
257
|
+
set_context_var('set_var', pagination_key, RubyLess::TypedString.new(curr_page, Number))
|
258
|
+
# Give access to page_count and count
|
259
|
+
# FIXME: DOC
|
260
|
+
set_context_var('set_var', 'page_count', RubyLess::TypedString.new(page_count, Number))
|
261
|
+
|
262
|
+
res << "; #{page_count} = (#{node_count} / #{query.page_size.to_f}).ceil; #{curr_page} = [1,params[:#{pagination_key}].to_i].max"
|
263
|
+
end
|
264
|
+
|
265
|
+
out "<% #{res} %>"
|
266
|
+
|
252
267
|
elsif finder[:method].kind_of?(RubyLess::TypedString)
|
253
268
|
# Hash passed with :zafu => {} is inserted into context
|
254
269
|
sub_context.merge!(finder[:method].opts[:zafu] || {})
|
255
270
|
end
|
256
271
|
|
257
|
-
sub_context[:has_link_id] = query && query.
|
272
|
+
sub_context[:has_link_id] = query && query.select_keys.include?('link_id')
|
258
273
|
|
259
274
|
sub_context
|
260
275
|
end
|
261
276
|
|
262
277
|
private
|
278
|
+
def single_node
|
279
|
+
node = self.node
|
280
|
+
while node.list_context?
|
281
|
+
node = node.up
|
282
|
+
if !node
|
283
|
+
raise ::QueryBuilder::Error.new("Could not access node context query builder from list #{self.node.class_name}")
|
284
|
+
end
|
285
|
+
end
|
286
|
+
node
|
287
|
+
end
|
288
|
+
|
263
289
|
# Build a Query object from SQLiss.
|
264
290
|
def build_query(count, pseudo_sql, raw_filters = [])
|
291
|
+
node = single_node
|
265
292
|
|
266
293
|
if !node.klass.respond_to?(:build_query)
|
267
294
|
raise ::QueryBuilder::Error.new("No query builder for class #{node.klass}")
|
@@ -299,8 +326,12 @@ module Zena
|
|
299
326
|
|
300
327
|
finder = get_finder(query, count)
|
301
328
|
|
302
|
-
if count != :count &&
|
303
|
-
|
329
|
+
if count != :count && params[:else]
|
330
|
+
begin
|
331
|
+
else_clause = RubyLess.translate(self, params[:else])
|
332
|
+
rescue RubyLess::Error
|
333
|
+
else_clause = RubyLess.translate(self, "find(#{params[:else].inspect})")
|
334
|
+
end
|
304
335
|
|
305
336
|
if else_clause.klass == Array
|
306
337
|
else_klass = else_clause.opts[:elem]
|
@@ -367,6 +398,7 @@ module Zena
|
|
367
398
|
def get_pseudo_sql(rel, params)
|
368
399
|
parts = [rel.dup]
|
369
400
|
filters = []
|
401
|
+
group_order_limit = ''
|
370
402
|
|
371
403
|
if params[:from]
|
372
404
|
parts << params[:from]
|
@@ -389,21 +421,21 @@ module Zena
|
|
389
421
|
# [group by GROUP_CLAUSE] [order by ORDER_CLAUSE] [limit num(,num)] [offset num] [paginate key]
|
390
422
|
|
391
423
|
if group = params[:group]
|
392
|
-
|
424
|
+
group_order_limit << " group by #{group}" unless parts[0] =~ /group by/
|
393
425
|
end
|
394
426
|
|
395
427
|
if order = params[:order]
|
396
|
-
|
428
|
+
group_order_limit << " order by #{order}" unless parts[0] =~ /order by/
|
397
429
|
end
|
398
430
|
|
399
431
|
if paginate = params[:paginate]
|
400
432
|
page_size = params[:limit].to_i
|
401
433
|
page_size = 20 if page_size < 1
|
402
|
-
|
434
|
+
group_order_limit << " limit #{page_size} paginate #{paginate.gsub(/[^a-z_A-Z]/,'')}"
|
403
435
|
else
|
404
436
|
[:limit, :offset].each do |k|
|
405
437
|
next unless params[k]
|
406
|
-
|
438
|
+
group_order_limit << " #{k} #{params[k]}" unless parts[0] =~ / #{k} /
|
407
439
|
end
|
408
440
|
end
|
409
441
|
|
@@ -421,9 +453,9 @@ module Zena
|
|
421
453
|
end
|
422
454
|
|
423
455
|
if finders.size > 1
|
424
|
-
finders = "(#{finders.join(') or (')})"
|
456
|
+
finders = "(#{finders.join(') or (')})#{group_order_limit}"
|
425
457
|
else
|
426
|
-
finders = finders.first
|
458
|
+
finders = finders.first + group_order_limit
|
427
459
|
end
|
428
460
|
|
429
461
|
return [finders, parse_raw_filters(params)]
|
data/lib/zena/use/query_node.rb
CHANGED
@@ -29,19 +29,18 @@ module Zena
|
|
29
29
|
|
30
30
|
# Find related nodes.
|
31
31
|
# See Node#build_find for details on the options available.
|
32
|
-
# TODO: do we need rubyless translate here ?
|
33
|
-
def find(count,
|
34
|
-
if !opts[:skip_rubyless] &&
|
32
|
+
# TODO: do we need rubyless translate here ? It should be removed.
|
33
|
+
def find(count, pseudo_sql, opts = {})
|
34
|
+
if !opts[:skip_rubyless] && type = RubyLess::SafeClass.safe_method_type_for(self.class, [pseudo_sql])
|
35
35
|
self.send(type[:method])
|
36
36
|
else
|
37
37
|
begin
|
38
|
-
query = self.class.build_query(count,
|
38
|
+
query = self.class.build_query(count, pseudo_sql,
|
39
39
|
:node_name => 'self',
|
40
40
|
:main_class => virtual_class,
|
41
41
|
:rubyless_helper => (opts[:rubyless_helper] || virtual_class), # should it be || self ?
|
42
42
|
:default => opts[:default]
|
43
43
|
)
|
44
|
-
|
45
44
|
if limit = opts[:limit]
|
46
45
|
query.limit = " LIMIT #{limit.to_i}"
|
47
46
|
query.offset = " OFFSET #{opts[:offset].to_i}"
|
@@ -52,7 +51,7 @@ module Zena
|
|
52
51
|
|
53
52
|
type = [:all, :first].include?(count) ? :find : :count
|
54
53
|
|
55
|
-
|
54
|
+
Node.do_find(count, eval(query.to_s(type)))
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
@@ -105,7 +104,7 @@ module Zena
|
|
105
104
|
after_process :insert_links_fields
|
106
105
|
after_process :secure_query
|
107
106
|
|
108
|
-
load_custom_queries Bricks.paths_for('queries')
|
107
|
+
load_custom_queries Bricks.paths_for('zena/queries')
|
109
108
|
|
110
109
|
CORE_CONTEXTS = %w{parent project section}
|
111
110
|
|
@@ -187,7 +186,7 @@ module Zena
|
|
187
186
|
end
|
188
187
|
end
|
189
188
|
|
190
|
-
# Overwrite this and take
|
189
|
+
# Overwrite this and take care to check for valid fields.
|
191
190
|
def process_field(field_name)
|
192
191
|
if fld = @query.attributes_alias[field_name]
|
193
192
|
# use custom query alias value defined in select clause: 'custom_a AS validation'
|
@@ -238,6 +237,11 @@ module Zena
|
|
238
237
|
end
|
239
238
|
|
240
239
|
# property or real column
|
240
|
+
|
241
|
+
# FIXME !!!! Why does this happen ?
|
242
|
+
return nil if @query.main_class.columns.kind_of?(Array)
|
243
|
+
|
244
|
+
|
241
245
|
column = @query.main_class.columns[field_name]
|
242
246
|
if column && column.indexed?
|
243
247
|
if column.index == true
|
@@ -291,6 +295,15 @@ module Zena
|
|
291
295
|
add_table('nodes_roles')
|
292
296
|
"(#{table('nodes_roles')}.node_id = #{table('nodes')}.id AND #{table('nodes_roles')}.role_id = #{role.id})"
|
293
297
|
end
|
298
|
+
elsif left.first == :function && left.last.last == 'date'
|
299
|
+
# transform "foo.date = baz"
|
300
|
+
# [:function, [:field, "foo"], [:method, "date"]]
|
301
|
+
# [:field, baz]
|
302
|
+
# ==> into
|
303
|
+
# "baz >= foo and foo < baz + 1 day"
|
304
|
+
a = left[1]
|
305
|
+
b = right
|
306
|
+
process([:and, [:<=, b, a], [:<, a, [:+, b, [:interval, [:integer, '1'], 'day']]]])
|
294
307
|
else
|
295
308
|
super
|
296
309
|
end
|
@@ -320,17 +333,10 @@ module Zena
|
|
320
333
|
elsif arg1[0] == :field && arg2[0] == :method
|
321
334
|
# contact.log_at or log_at.year
|
322
335
|
# arg1 = [:field, "contact"]
|
336
|
+
class_name = arg1[1]
|
323
337
|
# arg2 = [:method, "name"]
|
324
|
-
|
325
|
-
|
326
|
-
if @query.main_class.columns[class_or_field]
|
327
|
-
# log_at.year
|
328
|
-
return [arg1, arg2]
|
329
|
-
else
|
330
|
-
class_name = class_or_field
|
331
|
-
field_name = field_or_function
|
332
|
-
function = nil
|
333
|
-
end
|
338
|
+
field_name = arg2[1]
|
339
|
+
function = nil
|
334
340
|
else
|
335
341
|
return [arg1, arg2]
|
336
342
|
end
|
@@ -358,7 +364,7 @@ module Zena
|
|
358
364
|
# ******** And maybe overwrite these **********
|
359
365
|
def parse_custom_query_argument(key, value)
|
360
366
|
return nil unless value
|
361
|
-
super.gsub(/(RELATION_ID|NODE_ATTR)\(([^)]+)\)|(REF_DATE|NODE_ID|VISITOR_LANG)/) do
|
367
|
+
super.gsub(/(RELATION_ID|NODE_ATTR|SECURE_TABLE)\(([^)]+)\)|(REF_DATE|NODE_ID|VISITOR_LANG)/) do
|
362
368
|
type, value = $1, $2
|
363
369
|
type ||= $3
|
364
370
|
case type
|
@@ -367,16 +373,18 @@ module Zena
|
|
367
373
|
if rel = RelationProxy.find_by_role(role.singularize)
|
368
374
|
rel[:id]
|
369
375
|
else
|
370
|
-
|
371
|
-
'-1'
|
376
|
+
raise ::QueryBuilder::Error.new("Custom query: could not find Relation '#{role}'")
|
372
377
|
end
|
378
|
+
when 'SECURE_TABLE'
|
379
|
+
table_name = value
|
380
|
+
add_filter "\#{secure_scope('#{table_name}')}"
|
373
381
|
when 'NODE_ATTR'
|
374
382
|
attribute = value
|
375
383
|
if Node.safe_method_type([attribute])
|
376
384
|
insert_bind("#{node_name}.#{attribute}")
|
377
385
|
else
|
378
|
-
|
379
|
-
|
386
|
+
# not found: consider it's a property
|
387
|
+
insert_bind("#{node_name}.prop[#{attribute.inspect}]")
|
380
388
|
end
|
381
389
|
when 'REF_DATE'
|
382
390
|
context[:ref_date] ? insert_bind(context[:ref_date]) : 'now()'
|
@@ -480,25 +488,43 @@ module Zena
|
|
480
488
|
|
481
489
|
if class_name
|
482
490
|
# We have named the relation, set main_class
|
491
|
+
# We should also insert class filter...
|
483
492
|
if klass = Node.get_class(class_name)
|
484
493
|
set_main_class(klass)
|
494
|
+
kpath_filter = ".kpath LIKE #{quote("#{klass.kpath}%")}" unless klass.kpath == 'N'
|
485
495
|
else
|
486
496
|
raise QueryBuilder::QueryException.new("Unknown class #{klass} in scope '#{class_name}:#{scope}'.")
|
487
497
|
end
|
498
|
+
else
|
499
|
+
klass = nil
|
488
500
|
end
|
489
501
|
|
490
502
|
if relation == 'start'
|
491
503
|
add_table(main_table)
|
492
504
|
add_filter "#{field_or_attr('zip')} = #{insert_bind('start_node_zip')}"
|
493
505
|
add_filter "#{table}.site_id = #{insert_bind('current_site.id')}"
|
506
|
+
if kpath_filter
|
507
|
+
add_filter "#{table}#{kpath_filter}"
|
508
|
+
end
|
494
509
|
return true
|
495
510
|
end
|
496
511
|
|
497
512
|
if CORE_CONTEXTS.include?(relation)
|
513
|
+
unless class_name
|
514
|
+
if %w{project section}.include?(relation)
|
515
|
+
set_main_class(VirtualClass[relation.capitalize])
|
516
|
+
else
|
517
|
+
set_main_class(VirtualClass['Node'])
|
518
|
+
end
|
519
|
+
end
|
498
520
|
|
499
521
|
# PREVIOUS_GROUP.id = NEW_GROUP.project_id
|
500
522
|
add_table(main_table)
|
501
523
|
add_filter "#{field_or_attr('id')} = #{field_or_attr("#{relation}_id", table(main_table, -1))}"
|
524
|
+
if kpath_filter
|
525
|
+
add_filter "#{table}#{kpath_filter}"
|
526
|
+
end
|
527
|
+
true
|
502
528
|
else
|
503
529
|
nil
|
504
530
|
end
|
@@ -595,9 +621,9 @@ module Zena
|
|
595
621
|
unless @query.select
|
596
622
|
@query.select = ["#{@query.main_table}.*"]
|
597
623
|
end
|
598
|
-
add_select
|
624
|
+
add_select("#{link_table}.id", 'link_id')
|
599
625
|
Zena::Use::Relations::LINK_ATTRIBUTES.each do |l|
|
600
|
-
add_select
|
626
|
+
add_select("#{link_table}.#{l}", "l_#{l}")
|
601
627
|
end
|
602
628
|
end
|
603
629
|
end
|
data/lib/zena/use/refactor.rb
CHANGED
@@ -13,9 +13,9 @@ module Zena
|
|
13
13
|
include Common
|
14
14
|
|
15
15
|
# Read the parameters and add errors to the object if it is considered spam. Save it otherwize.
|
16
|
-
def
|
16
|
+
def should_save(obj, params)
|
17
17
|
# do nothing (overwritten by plugins like zena_captcha)
|
18
|
-
|
18
|
+
true
|
19
19
|
end
|
20
20
|
|
21
21
|
end # ControllerMethods
|
@@ -161,32 +161,6 @@ ENDTXT
|
|
161
161
|
end
|
162
162
|
trad_list
|
163
163
|
end
|
164
|
-
|
165
|
-
# This lets helpers render partials
|
166
|
-
# TODO: make sure this is the best way to handle this problem.
|
167
|
-
# def render_to_string(*args)
|
168
|
-
# controller = self.controller || begin
|
169
|
-
# # ==> this means render_to_string uses a view with everything ApplicationController has...
|
170
|
-
# ApplicationController.new.instance_eval do
|
171
|
-
# class << self
|
172
|
-
# public :render, :render_to_string
|
173
|
-
# attr_accessor :request, :response, :params
|
174
|
-
# end
|
175
|
-
#
|
176
|
-
# @request = ::ActionController::TestRequest.new
|
177
|
-
# @response = ::ActionController::TestResponse.new
|
178
|
-
#
|
179
|
-
# @params = {}
|
180
|
-
# send(:initialize_current_url)
|
181
|
-
# @template = @response.template = ::ActionView::Base.new(self.class.view_paths, {}, self)
|
182
|
-
# @template.helpers.send :include, self.class.master_helper_module
|
183
|
-
# self
|
184
|
-
# end
|
185
|
-
# end
|
186
|
-
#
|
187
|
-
# controller.render(*args)
|
188
|
-
# end
|
189
|
-
|
190
164
|
end # ViewMethods
|
191
165
|
end # Refactor
|
192
166
|
end # Use
|
data/lib/zena/use/relations.rb
CHANGED
data/lib/zena/use/rendering.rb
CHANGED
@@ -3,6 +3,14 @@ require 'tempfile'
|
|
3
3
|
module Zena
|
4
4
|
module Use
|
5
5
|
module Rendering
|
6
|
+
class Redirect < Exception
|
7
|
+
attr_reader :url
|
8
|
+
|
9
|
+
def initialize(url)
|
10
|
+
@url = url
|
11
|
+
end
|
12
|
+
end # Redirect class
|
13
|
+
|
6
14
|
module ViewMethods
|
7
15
|
# Append javascript to the end of the page.
|
8
16
|
def render_js(in_html = true)
|
@@ -174,6 +182,16 @@ module Zena
|
|
174
182
|
headers.merge!(zafu_headers)
|
175
183
|
cache_page(:url => opts[:cache_url]) if opts[:cache]
|
176
184
|
end
|
185
|
+
# This does not work, Rendering::Redirect is wrapped in TemplateError
|
186
|
+
# rescue Zena::Use::Rendering::Redirect
|
187
|
+
# This does not work either: infinity loop, CPU hog on errors.
|
188
|
+
# rescue ActionView::TemplateError => err
|
189
|
+
# orig = err.original_exception
|
190
|
+
# if orig.kind_of?(Zena::Use::Rendering::Redirect)
|
191
|
+
# redirect_to orig.url
|
192
|
+
# else
|
193
|
+
# raise err
|
194
|
+
# end
|
177
195
|
end
|
178
196
|
|
179
197
|
# Cache page content into a static file in the current sites directory : SITES_ROOT/test.host/public
|
@@ -277,6 +295,17 @@ module Zena
|
|
277
295
|
out "<% set_headers(#{headers.join(', ')}) %>"
|
278
296
|
end
|
279
297
|
end
|
298
|
+
|
299
|
+
def r_not_found
|
300
|
+
out "<% raise ActiveRecord::RecordNotFound %>"
|
301
|
+
end
|
302
|
+
|
303
|
+
# Does not work properly. FIXME.
|
304
|
+
# def r_redirect
|
305
|
+
# out parser_error('Missing "url" parameter.') unless url = @params[:url]
|
306
|
+
# code = ::RubyLess.translate_string(self, url)
|
307
|
+
# out "<% raise Zena::Use::Rendering::Redirect.new(#{code}) %>"
|
308
|
+
# end
|
280
309
|
end # ZafuMethods
|
281
310
|
end # Rendering
|
282
311
|
end # Use
|
data/lib/zena/use/scope_index.rb
CHANGED
@@ -9,16 +9,23 @@ module Zena
|
|
9
9
|
|
10
10
|
module VirtualClassMethods
|
11
11
|
def self.included(base)
|
12
|
-
base.
|
13
|
-
|
14
|
-
|
12
|
+
base.class_eval do
|
13
|
+
validate :validate_idx_class, :validate_idx_scope
|
14
|
+
attr_accessible :idx_class, :idx_scope, :idx_reverse_scope
|
15
|
+
property do |p|
|
16
|
+
p.string 'idx_class'
|
17
|
+
p.string 'idx_scope'
|
18
|
+
p.string 'idx_reverse_scope'
|
19
|
+
end
|
20
|
+
self.export_attributes += %w{idx_class idx_scope idx_reverse_scope}
|
21
|
+
end
|
15
22
|
end
|
16
23
|
|
17
24
|
protected
|
18
25
|
def validate_idx_class
|
19
|
-
self
|
26
|
+
self.idx_class = nil if self.idx_class.blank?
|
20
27
|
|
21
|
-
if model_name = self
|
28
|
+
if model_name = self.idx_class
|
22
29
|
if model_name =~ /\A[A-Z][a-zA-Z]+\Z/
|
23
30
|
if klass = Zena.const_get(model_name) rescue NilClass
|
24
31
|
if klass < Zena::Use::ScopeIndex::IndexMethods
|
@@ -36,11 +43,11 @@ module Zena
|
|
36
43
|
end
|
37
44
|
|
38
45
|
def validate_idx_scope
|
39
|
-
self
|
40
|
-
if scopes = self
|
46
|
+
self.idx_scope = nil if self.idx_scope.blank?
|
47
|
+
if scopes = self.idx_scope
|
41
48
|
# Try to compile query in instance of class self
|
42
49
|
begin
|
43
|
-
scopes = new_instance.safe_eval
|
50
|
+
scopes = new_instance.safe_eval scopes
|
44
51
|
if scopes.kind_of?(Hash)
|
45
52
|
scopes.each do |keys, query|
|
46
53
|
unless keys.kind_of?(String) &&
|
@@ -122,11 +129,34 @@ module Zena
|
|
122
129
|
end
|
123
130
|
end
|
124
131
|
|
132
|
+
def update_after_destroy(deleted_node, keys)
|
133
|
+
groups = self.class.groups
|
134
|
+
attrs = {}
|
135
|
+
keys.each do |group_key|
|
136
|
+
next unless list = groups[group_key]
|
137
|
+
next unless should_clear_group?(group_key, deleted_node)
|
138
|
+
list.each do |key|
|
139
|
+
attrs["#{group_key}_#{key}"] = nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
if !attrs.empty?
|
144
|
+
self.attributes = attrs
|
145
|
+
save
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
125
149
|
# Return true if the indices from the given group should be altered by the node.
|
126
150
|
def should_update_group?(group_key, node)
|
127
151
|
node.id >= self["#{group_key}_id"].to_i
|
128
152
|
end
|
129
153
|
|
154
|
+
# Return true if the indices from the given group should be cleared when
|
155
|
+
# the given node is deleted.
|
156
|
+
def should_clear_group?(group_key, deleted_node)
|
157
|
+
deleted_node.id == self["#{group_key}_id"].to_i
|
158
|
+
end
|
159
|
+
|
130
160
|
def set_site_id
|
131
161
|
self[:site_id] = current_site.id
|
132
162
|
end
|
@@ -134,7 +164,8 @@ module Zena
|
|
134
164
|
|
135
165
|
module ModelMethods
|
136
166
|
def self.included(base)
|
137
|
-
base.after_save
|
167
|
+
base.after_save :update_scope_indices
|
168
|
+
base.after_destroy :update_scope_indices_on_destroy
|
138
169
|
base.safe_context :scope_index => scope_index_proc
|
139
170
|
base.alias_method_chain :rebuild_index!, :scope_index
|
140
171
|
end
|
@@ -149,7 +180,7 @@ module Zena
|
|
149
180
|
end
|
150
181
|
end
|
151
182
|
|
152
|
-
#
|
183
|
+
# Rebuild 'remote' indexes based on changes in this node.
|
153
184
|
def rebuild_index_with_scope_index!
|
154
185
|
rebuild_index_without_scope_index!
|
155
186
|
update_scope_indices
|
@@ -171,6 +202,21 @@ module Zena
|
|
171
202
|
end
|
172
203
|
end
|
173
204
|
|
205
|
+
# Trigger 'rebuild_index!' in all elements that could affect this model's
|
206
|
+
# scope index.
|
207
|
+
def rebuild_scope_index!
|
208
|
+
if vclass && query = vclass.idx_reverse_scope
|
209
|
+
if nodes = find(:all, query)
|
210
|
+
nodes.each do |node|
|
211
|
+
node.rebuild_index!
|
212
|
+
end
|
213
|
+
end
|
214
|
+
else
|
215
|
+
nil
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
174
220
|
protected
|
175
221
|
# Update scope indices (project/section).
|
176
222
|
def update_scope_indices
|
@@ -182,7 +228,13 @@ module Zena
|
|
182
228
|
# FIXME: raise when we have transactional save.
|
183
229
|
end
|
184
230
|
|
185
|
-
def
|
231
|
+
def update_scope_indices_on_destroy
|
232
|
+
update_scope_indices_on_prop_change(true)
|
233
|
+
# How can we handle this ?
|
234
|
+
# update_scope_indices_on_link_change
|
235
|
+
end
|
236
|
+
|
237
|
+
def update_scope_indices_on_prop_change(deleted=false)
|
186
238
|
if virtual_class && scopes = virtual_class.idx_scope
|
187
239
|
scopes = safe_eval(scopes)
|
188
240
|
return unless scopes.kind_of?(Hash)
|
@@ -198,15 +250,24 @@ module Zena
|
|
198
250
|
mapped_scopes.each do |keys, query|
|
199
251
|
next unless query.kind_of?(String) && keys.kind_of?(Array) && keys.inject(true) {|s,k| s && k.kind_of?(String) }
|
200
252
|
if query.strip == 'self'
|
253
|
+
next if deleted
|
201
254
|
models_to_update = [self]
|
202
255
|
else
|
203
|
-
models_to_update = find(:all, query) || []
|
256
|
+
models_to_update = find(:all, query, :skip_rubyless => true) || []
|
204
257
|
end
|
205
258
|
|
206
259
|
models_to_update.each do |m|
|
260
|
+
next if m.destroyed? # on destroy, self can be in this list
|
207
261
|
if idx_model = m.scope_index
|
208
|
-
|
209
|
-
|
262
|
+
if deleted
|
263
|
+
# Clear obsolete content
|
264
|
+
idx_model.update_after_destroy(self, keys)
|
265
|
+
# Rebuild index
|
266
|
+
m.rebuild_scope_index!
|
267
|
+
else
|
268
|
+
# force creation of index record
|
269
|
+
idx_model.update_with(self, keys, true)
|
270
|
+
end
|
210
271
|
end
|
211
272
|
end
|
212
273
|
end
|
data/lib/zena/use/search.rb
CHANGED
@@ -10,17 +10,12 @@ module Zena
|
|
10
10
|
:conditions => ["parent_id = ?",node[:id]],
|
11
11
|
:order => 'zip ASC' )
|
12
12
|
elsif !query.blank?
|
13
|
-
|
14
|
-
|
15
|
-
select = sanitize_sql(["nodes.*, MATCH (vs.idx_text_high,vs.idx_text_medium,vs.idx_text_low) AGAINST (?) AS score", query, "#{query}%"])
|
16
|
-
else
|
17
|
-
match = sanitize_sql(["nodes._id LIKE ?", "#{query}%"])
|
18
|
-
select = "nodes.*, #{match} AS score"
|
19
|
-
end
|
13
|
+
match = sanitize_sql(["vs.idx_text_high LIKE ?", "%#{query.gsub('*','%')}%"])
|
14
|
+
select = "nodes.*"
|
20
15
|
|
21
16
|
case Zena::Db.adapter
|
22
17
|
when 'postgresql'
|
23
|
-
select = "DISTINCT ON (nodes.zip
|
18
|
+
select = "DISTINCT ON (nodes.zip) #{select}"
|
24
19
|
group = nil
|
25
20
|
else
|
26
21
|
group = 'nodes.id'
|
@@ -31,7 +26,7 @@ module Zena
|
|
31
26
|
:joins => "INNER JOIN versions AS vs ON vs.node_id = nodes.id AND vs.status >= #{Zena::Status[:pub]}",
|
32
27
|
:conditions => match,
|
33
28
|
:group => group,
|
34
|
-
:order => "
|
29
|
+
:order => "zip DESC") # new items first
|
35
30
|
else
|
36
31
|
# error
|
37
32
|
return options.merge(:conditions => '0')
|
@@ -69,7 +64,7 @@ module Zena
|
|
69
64
|
|
70
65
|
query = "nodes where #{query_args.join(' and ')} in site"
|
71
66
|
end
|
72
|
-
|
67
|
+
|
73
68
|
res = node.find(count, query, options.merge(:errors => true, :rubyless_helper => self, :default => default))
|
74
69
|
|
75
70
|
if res.kind_of?(::QueryBuilder::Error)
|
data/lib/zena/use/test_helper.rb
CHANGED
@@ -102,7 +102,7 @@ module Zena
|
|
102
102
|
uploaded_fixture(fname, 'image/jpeg', filename)
|
103
103
|
end
|
104
104
|
|
105
|
-
#
|
105
|
+
# Pdf helper
|
106
106
|
def uploaded_pdf(fname, filename=nil)
|
107
107
|
uploaded_fixture(fname, 'application/pdf', filename)
|
108
108
|
end
|
@@ -141,7 +141,7 @@ module Zena
|
|
141
141
|
digest = Digest::SHA1.hexdigest(content_id.to_s)
|
142
142
|
"#{SITES_ROOT}/test.host/data/#{mode}/#{digest[0..0]}/#{digest[1..1]}/#{digest[2..2]}/#{fname}"
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
def execute_after_commit!
|
146
146
|
Node.connection.instance_eval do
|
147
147
|
# Simulate commit
|