spiderfw 0.5.10 → 0.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. data/CHANGELOG +6 -0
  2. data/Rakefile +4 -1
  3. data/VERSION +1 -0
  4. data/apps/core/auth/controllers/login_controller.rb +10 -1
  5. data/apps/core/auth/controllers/mixins/auth_helper.rb +4 -2
  6. data/apps/core/auth/views/login.shtml +1 -1
  7. data/apps/core/components/_init.rb +1 -1
  8. data/apps/core/components/public/css/spider.css +0 -1
  9. data/apps/core/components/public/js/jquery/plugins/jquery.form.js +2 -1
  10. data/apps/core/components/public/js/list.js +14 -126
  11. data/apps/core/components/public/js/plugins/plugin.js +7 -0
  12. data/apps/core/components/public/js/plugins/sortable.js +124 -0
  13. data/apps/core/components/public/js/spider.js +212 -51
  14. data/apps/core/components/widgets/list/list.shtml +1 -0
  15. data/apps/core/components/widgets/table/table.rb +1 -1
  16. data/apps/core/components/widgets/table/table.shtml +3 -3
  17. data/apps/core/components/widgets/tabs/tabs.rb +70 -22
  18. data/apps/core/components/widgets/tabs/tabs.shtml +8 -2
  19. data/apps/core/forms/widgets/inputs/file_input/file_input.rb +4 -1
  20. data/data/locale/it/LC_MESSAGES/cms.mo +0 -0
  21. data/data/locale/it/LC_MESSAGES/spider.mo +0 -0
  22. data/data/locale/it/LC_MESSAGES/spider_files.mo +0 -0
  23. data/data/locale/it/LC_MESSAGES/spider_images.mo +0 -0
  24. data/lib/spiderfw.rb +3 -1
  25. data/lib/spiderfw/config/configuration.rb +3 -1
  26. data/lib/spiderfw/controller/controller.rb +8 -0
  27. data/lib/spiderfw/controller/mixins/static_content.rb +14 -2
  28. data/lib/spiderfw/controller/mixins/visual.rb +25 -25
  29. data/lib/spiderfw/controller/page_controller.rb +3 -0
  30. data/lib/spiderfw/controller/request.rb +4 -1
  31. data/lib/spiderfw/controller/session.rb +7 -6
  32. data/lib/spiderfw/create.rb +10 -1
  33. data/lib/spiderfw/model/base_model.rb +104 -57
  34. data/lib/spiderfw/model/condition.rb +9 -1
  35. data/lib/spiderfw/model/data_type.rb +15 -0
  36. data/lib/spiderfw/model/datatypes/uuid.rb +5 -0
  37. data/lib/spiderfw/model/extended_models/managed.rb +2 -2
  38. data/lib/spiderfw/model/mappers/db_mapper.rb +46 -21
  39. data/lib/spiderfw/model/mappers/mapper.rb +34 -8
  40. data/lib/spiderfw/model/mixins/list.rb +2 -0
  41. data/lib/spiderfw/model/mixins/tree.rb +2 -1
  42. data/lib/spiderfw/model/mixins/versioned.rb +12 -9
  43. data/lib/spiderfw/model/model.rb +72 -0
  44. data/lib/spiderfw/model/query_set.rb +7 -0
  45. data/lib/spiderfw/model/storage/base_storage.rb +5 -1
  46. data/lib/spiderfw/model/storage/db/adapters/mysql.rb +5 -2
  47. data/lib/spiderfw/model/storage/db/adapters/oci8.rb +9 -3
  48. data/lib/spiderfw/model/storage/db/db_storage.rb +8 -5
  49. data/lib/spiderfw/model/sync.rb +12 -6
  50. data/lib/spiderfw/requires.rb +1 -0
  51. data/lib/spiderfw/templates/blocks/parent_context.rb +26 -0
  52. data/lib/spiderfw/templates/blocks/widget.rb +17 -7
  53. data/lib/spiderfw/templates/layout.rb +11 -1
  54. data/lib/spiderfw/templates/template.rb +36 -3
  55. data/lib/spiderfw/templates/template_blocks.rb +36 -26
  56. data/lib/spiderfw/utils/annotations.rb +2 -1
  57. data/lib/spiderfw/utils/thread_out.rb +15 -0
  58. data/lib/spiderfw/widget/widget.rb +58 -16
  59. data/spider.gemspec +3 -0
  60. metadata +143 -48
@@ -44,6 +44,12 @@ module Spider; module Model
44
44
  return true
45
45
  end
46
46
 
47
+ def sortable?(element)
48
+ element = element.name if (element.is_a? Element)
49
+ element = @model.elements[element]
50
+ mapped?(element) || element.attributes[:sortable]
51
+ end
52
+
47
53
  # Utility methods
48
54
 
49
55
  # An array of mapped elements.
@@ -136,11 +142,19 @@ module Spider; module Model
136
142
  raise NotUniqueError.new(el)
137
143
  end
138
144
  end
145
+ if mode == :insert && !el.integrated?
146
+ obj.set(el.name, el.type.auto_value) if el.type < Spider::DataType && el.type.auto?(el) && !obj.element_has_value?(el)
147
+ obj.set(el, obj.get(el)) if el.attributes[:default] && !obj.element_modified?(el)
148
+ end
139
149
  end
140
150
  if (@model.extended_models)
141
151
  @model.extended_models.each do |m, el|
142
152
  sub = obj.get(el)
143
- sub.save if (obj.element_modified?(el) || !obj.primary_keys_set?) && sub.mapper.class.write?
153
+ if mode == :update || sub.class.auto_primary_keys?
154
+ sub.save if (obj.element_modified?(el) || !obj.primary_keys_set?) && sub.mapper.class.write?
155
+ else
156
+ sub.insert unless sub.in_storage?
157
+ end
144
158
  end
145
159
  end
146
160
  @model.elements_array.select{ |el| el.attributes[:integrated_model] }.each do |el|
@@ -219,7 +233,9 @@ module Spider; module Model
219
233
 
220
234
  # Elements that are associated to this one externally.
221
235
  def association_elements
222
- @model.elements_array.select{ |el| mapped?(el) && !el.integrated? && !have_references?(el) }
236
+ @model.elements_array.select{ |el|
237
+ mapped?(el) && !el.integrated? && !have_references?(el) && !(el.attributes[:added_reverse] && el.type == @model)
238
+ }
223
239
  end
224
240
 
225
241
  # Saves object associations.
@@ -261,7 +277,6 @@ module Spider; module Model
261
277
  def save_element_associations(obj, element, mode)
262
278
  our_element = element.attributes[:reverse]
263
279
  val = obj.get(element)
264
-
265
280
  if (element.attributes[:junction])
266
281
  their_element = element.attributes[:junction_their_element]
267
282
  if (val.model != element.model) # dereferenced junction
@@ -269,12 +284,12 @@ module Spider; module Model
269
284
  current = obj.get_new
270
285
  current_val = current.get(element)
271
286
  condition = Condition.and
287
+ val_condition = Condition.or
272
288
  current_val.each do |row|
273
289
  next if val.include?(row)
274
- condition_row = Condition.or
275
- condition_row[their_element] = row
276
- condition << condition_row
290
+ val_condition[their_element] = row
277
291
  end
292
+ condition << val_condition
278
293
  unless condition.empty?
279
294
  condition[our_element] = obj
280
295
  element.model.mapper.delete(condition)
@@ -319,8 +334,12 @@ module Spider; module Model
319
334
  element.mapper.bulk_update({our_element => nil}, condition)
320
335
  end
321
336
  end
322
- val.set(our_element, obj)
323
- val.save
337
+ val.each do |v|
338
+ if v.get(our_element) != obj
339
+ v.set(our_element, obj)
340
+ v.save
341
+ end
342
+ end
324
343
  end
325
344
  end
326
345
 
@@ -650,6 +669,13 @@ module Spider; module Model
650
669
  result = objects.element_queryset(element).index_by(*index_by)
651
670
  @model.primary_keys.each{ |key| result.request[key.name] = true }
652
671
  result.request[element.attributes[:reverse]] = true
672
+ if element.attributes[:polymorph]
673
+ element.type.polymorphic_models.each do |mod, params|
674
+ poly_req = Spider::Model::Request.new
675
+ mod.primary_keys.each{ |k| poly_req.request(k) }
676
+ result.request.with_polymorphs(mod, poly_req)
677
+ end
678
+ end
653
679
  result.load
654
680
  return associate_external(element, objects, result)
655
681
  end
@@ -79,6 +79,7 @@ module Spider; module Model
79
79
  return nil unless l_cond
80
80
  cond = l_cond.call(obj)
81
81
  cond = Condition.new(cond) unless cond.is_a?(Condition)
82
+ preprocess_condition(cond)
82
83
  return cond
83
84
  end
84
85
 
@@ -101,6 +102,7 @@ module Spider; module Model
101
102
 
102
103
  def list(name, attributes={})
103
104
  attributes[:list] = true
105
+ attributes[:order] ||= true
104
106
  element(name, Fixnum, attributes)
105
107
  observe_element(name) do |obj, el, new_val|
106
108
  obj.save_mode do
@@ -36,10 +36,11 @@ module Spider; module Model
36
36
  attributes[:association] = :tree
37
37
  attributes[:multiple] = true
38
38
  attributes[:reverse] ||= :"#{name}_parent"
39
+ attributes[:reverse_attributes] = {:association => :tree_parent}.merge(attributes[:reverse_attributes] || {})
39
40
  attributes[:tree_left] ||= :"#{name}_left"
40
41
  attributes[:tree_right] ||= :"#{name}_right"
41
42
  attributes[:tree_depth] ||= :"#{name}_depth"
42
- choice(attributes[:reverse], self, :association => :tree_parent)
43
+ choice(attributes[:reverse], self, attributes[:reverse_attributes])
43
44
  element(name, self, attributes)
44
45
  element(attributes[:tree_left], Fixnum, :hidden => true)
45
46
  element(attributes[:tree_right], Fixnum, :hidden => true)
@@ -5,16 +5,16 @@ module Spider; module Model
5
5
  module Versioned
6
6
 
7
7
  def self.included(model)
8
-
9
8
  model.extend(ClassMethods)
10
9
  model.mapper_include(Mapper)
10
+ #model.versioning
11
11
  vmod = Class.new(model)
12
12
  vmod.primary_keys.each do |pk|
13
13
  vmod.element_attributes(pk.name, :primary_key => false)
14
14
  end
15
- model.const_set("Versioned", vmod)
15
+ model.const_set(:Versioned, vmod)
16
16
  model.set_version_model(nil, vmod)
17
- model.element(:sha1, String, :length => 40)
17
+ model.element(:v_sha1, String, :length => 40)
18
18
  end
19
19
 
20
20
  module ClassMethods
@@ -31,13 +31,16 @@ module Spider; module Model
31
31
  end
32
32
  vmod = @version_models[branch]
33
33
  vmod.primary_keys.each do |pk|
34
- vmod.delete_element(pk.name)
34
+ vmod.remove_element(pk.name)
35
35
  end
36
36
  vmod.elements_array.each do |el|
37
37
  el.attributes[:autoincrement] = false
38
38
  end
39
- vmod.element(:sha1, String, :primary_key => true, :length => 40)
40
- vmod.element(self.short_name.to_sym, self, :add_multiple_reverse => :history)
39
+ vmod.remove_element(:v_sha1) if vmod.elements[:v_sha1]
40
+ vmod.remove_element(:v_original) if vmod.elements[:v_original]
41
+ vmod.remove_element(:version_date) if vmod.elements[:version_date]
42
+ vmod.element(:v_sha1, String, :primary_key => true, :length => 40)
43
+ vmod.element(:v_original, self, :add_multiple_reverse => :history)
41
44
  vmod.element(:version_date, DateTime)
42
45
  self.elements_array.each do |el|
43
46
  elh = dump_element(el)
@@ -74,7 +77,7 @@ module Spider; module Model
74
77
  end
75
78
 
76
79
  def version_element(el=nil)
77
- return :sha1 unless el
80
+ return :v_sha1 unless el
78
81
  el = el.name if el.respond_to?(:name)
79
82
  @version_elements[el]
80
83
  end
@@ -96,7 +99,7 @@ module Spider; module Model
96
99
  def save_done(obj, mode)
97
100
  obj.set(obj.class.version_element, obj.version_sha1)
98
101
  obj.reset_modified_elements
99
- obj.set_modified(:sha1 => true)
102
+ obj.set_modified(:v_sha1 => true)
100
103
  obj.mapper.do_update(obj)
101
104
  super
102
105
  end
@@ -104,7 +107,7 @@ module Spider; module Model
104
107
  end
105
108
 
106
109
  def version_sha1
107
- yaml = self.to_yaml(:except => [:sha1])
110
+ yaml = self.to_yaml(:except => [:v_sha1])
108
111
  sha1 = Digest::SHA1.hexdigest(yaml)
109
112
  end
110
113
 
@@ -207,6 +207,78 @@ module Spider
207
207
 
208
208
  end
209
209
 
210
+ def self.sort(models)
211
+
212
+ sorter = Sorter.new(models)
213
+ sorter.sort
214
+ end
215
+
216
+ require 'tsort'
217
+
218
+ class Sorter
219
+ include TSort
220
+
221
+ def initialize(models)
222
+ @model_tasks = {}
223
+ @processed_deps = {}
224
+ @processed = {}
225
+ @models = models
226
+ @models.each{ |m| collect_dependencies(m) }
227
+ end
228
+
229
+ def tsort_each_node(&block)
230
+ @model_tasks.each_value(&block)
231
+ end
232
+
233
+ def tsort_each_child(node, &block)
234
+ node.dependencies.each(&block)
235
+ end
236
+
237
+ def collect_dependencies(model)
238
+ return if model.subclass_of?(Spider::Model::InlineModel)
239
+ @processed_deps[model] = true
240
+ @model_tasks[model] ||= SortTask.new(model)
241
+ if @models.include?(model.superclass)
242
+ @model_tasks[model.superclass] ||= SortTask.new(model.superclass)
243
+ @model_tasks[model] << @model_tasks[model.superclass]
244
+ end
245
+ end
246
+
247
+
248
+ def sort
249
+ tasks = tsort
250
+ tasks.map{ |t| t.model }
251
+ end
252
+
253
+
254
+ def length
255
+ @model_tasks.keys.length
256
+ end
257
+
258
+ end
259
+
260
+ class SortTask
261
+ attr_reader :model, :dependencies
262
+
263
+ def initialize(model)
264
+ @model = model
265
+ @dependencies = []
266
+ end
267
+
268
+ def <<(model)
269
+ @dependencies << model
270
+ end
271
+
272
+ def eql?(other)
273
+ @model == other.model
274
+ end
275
+
276
+ def inspect
277
+ "#{@model.name} -> (#{dependencies.map{|d| d.model.name }.join(', ')})"
278
+ end
279
+
280
+ end
281
+
210
282
  end
211
283
 
212
284
 
@@ -406,6 +406,13 @@ module Spider; module Model
406
406
  return self
407
407
  end
408
408
 
409
+ def with_polymorphs
410
+ @model.polymorphic_models.each do |model, attributes|
411
+ @query.with_polymorph(model)
412
+ end
413
+ self
414
+ end
415
+
409
416
  # Sets the value of an element on all currently loaded objects.
410
417
  def set(element, value)
411
418
  element_name = element.is_a?(Element) ? element.name : element
@@ -54,6 +54,10 @@ module Spider; module Model; module Storage
54
54
  def create_sequence(name, start=1, increment=1)
55
55
  sequence_next(name, start-1, increment)
56
56
  end
57
+
58
+ def generate_uuid
59
+ Spider::DataTypes::UUID.generate
60
+ end
57
61
 
58
62
 
59
63
  def update_sequence(name, val)
@@ -65,7 +69,7 @@ module Spider; module Model; module Storage
65
69
  def sequence_next(name, newval=nil, increment=1)
66
70
  path = sequence_file_path(name)
67
71
  FileUtils.mkpath(File.dirname(path))
68
- self.class.sequence_sync.lock(Sync::EX)
72
+ self.class.sequence_sync.lock(::Sync::EX)
69
73
  if newval
70
74
  seq = newval
71
75
  else
@@ -131,7 +131,7 @@ module Spider; module Model; module Storage; module Db
131
131
  end
132
132
 
133
133
  def savepoint(name)
134
- execute("SAVEPOINT #{name}")
134
+ connection.query("SAVEPOINT #{name}")
135
135
  super
136
136
  end
137
137
 
@@ -151,7 +151,7 @@ module Spider; module Model; module Storage; module Db
151
151
  end
152
152
 
153
153
  def rollback_savepoint(name=nil)
154
- execute("ROLLBACK TO #{name}")
154
+ connection.query("ROLLBACK TO #{name}")
155
155
  super
156
156
  end
157
157
 
@@ -266,6 +266,9 @@ module Spider; module Model; module Storage; module Db
266
266
  tables_sql, tables_values = sql_tables(query)
267
267
  sql = "SELECT "
268
268
  sql += "SQL_CALC_FOUND_ROWS " unless query[:query_type] == :count
269
+ if query[:joins] && query[:joins].values.map{ |h| h.values }.flatten.select{ |v| v[:type] == :left}.length > 0
270
+ sql += "DISTINCT "
271
+ end
269
272
  sql += "#{sql_keys(query)} FROM #{tables_sql} "
270
273
  bind_vars += tables_values
271
274
  where, vals = sql_condition(query)
@@ -210,6 +210,7 @@ module Spider; module Model; module Storage; module Db
210
210
  return curr[:last_result] ? curr[:last_result].length : nil
211
211
  end
212
212
  q.delete(:offset); q.delete(:limit)
213
+ q[:query_type] = :count
213
214
  sql, vars = sql_select(q)
214
215
  res = execute("SELECT COUNT(*) AS N FROM (#{sql})", *vars)
215
216
  return nil unless res && res[0]
@@ -284,12 +285,13 @@ module Spider; module Model; module Storage; module Db
284
285
  bind_vars += vals
285
286
  sql += "WHERE #{where} " if where && !where.empty?
286
287
  order = sql_order(query, replaced_fields)
287
- if (query[:limit])
288
+ if (query[:limit] || query[:query_type] == :count)
289
+ limit = nil
288
290
  if (query[:offset])
289
291
  limit = "oci8_row_num between :#{curr[:bind_cnt]+=1} and :#{curr[:bind_cnt]+=1}"
290
292
  bind_vars << query[:offset] + 1
291
293
  bind_vars << query[:offset] + query[:limit]
292
- else
294
+ elsif query[:limit]
293
295
  limit = "oci8_row_num < :#{curr[:bind_cnt]+=1}"
294
296
  bind_vars << query[:limit] + 1
295
297
  end
@@ -303,7 +305,11 @@ module Spider; module Model; module Storage; module Db
303
305
  data_sql = "#{sql} order by #{order}"
304
306
  end
305
307
  count_sql = "SELECT /*+ FIRST_ROWS(n) */ a.*, ROWNUM oci8_row_num FROM (#{data_sql}) a"
306
- sql = "SELECT * FROM (#{count_sql}) WHERE #{limit}"
308
+ if limit
309
+ sql = "SELECT * FROM (#{count_sql}) WHERE #{limit}"
310
+ else
311
+ sql = count_sql
312
+ end
307
313
  else
308
314
  sql += "ORDER BY #{order} " if order && !order.empty?
309
315
  end
@@ -168,6 +168,7 @@ module Spider; module Model; module Storage; module Db
168
168
  end
169
169
 
170
170
  def start_transaction
171
+ return unless transactions_enabled?
171
172
  return savepoint("point#{curr[:savepoints].length}") if in_transaction?
172
173
  curr[:transaction_nesting] += 1
173
174
  Spider.logger.debug("#{self.class.name} starting transaction for connection #{connection.object_id}")
@@ -343,18 +344,20 @@ module Spider; module Model; module Storage; module Db
343
344
  else
344
345
  func.mapper_fields[func_el]
345
346
  end
346
- }.join(', ')
347
+ }
347
348
  case func.func_name
348
349
  when :length
349
- return "LENGTH(#{fields})"
350
+ return "LENGTH(#{fields.join(', ')})"
350
351
  when :trim
351
- return "TRIM(#{fields})"
352
+ return "TRIM(#{fields.join(', ')})"
352
353
  when :concat
353
- return "CONCAT(#{fields})"
354
+ return "CONCAT(#{fields.join(', ')})"
354
355
  when :substr
355
356
  arguments = "#{func.start}"
356
357
  arguments += ", #{func.length}" if func.length
357
- return "SUBSTR(#{fields}, #{arguments})"
358
+ return "SUBSTR(#{fields.join(', ')}, #{arguments})"
359
+ when :subtract
360
+ return "(#{fields[0]} - #{fields[1]})"
358
361
  end
359
362
  raise NotImplementedError, "#{self.class} does not support function #{func.func_name}"
360
363
  end
@@ -11,15 +11,21 @@ module Spider; module Model
11
11
  @processed = {}
12
12
  end
13
13
 
14
- def add(model)
15
- collect_dependencies(model)
14
+ def add(models)
15
+ models = [models] unless models.is_a?(Array)
16
+ models.each do |model|
17
+ collect_dependencies(model)
18
+ end
16
19
  end
17
20
 
18
- def each
21
+ def sorted
19
22
  tasks = tsort
20
- pp tasks
21
- tasks.each do |task|
22
- yield task.model
23
+ tasks.map{ |t| t.model }
24
+ end
25
+
26
+ def each
27
+ sorted.each do |model|
28
+ yield model
23
29
  end
24
30
  end
25
31
 
@@ -10,6 +10,7 @@ require 'spiderfw/utils/monkey/date_time'
10
10
  require 'spiderfw/utils/monkey/numeric'
11
11
  require 'spiderfw/utils/monkey/exception'
12
12
  require 'spiderfw/utils/monkey/nil_class'
13
+ require 'spiderfw/utils/monkey/object'
13
14
  require 'spiderfw/utils/multi_level_hash'
14
15
  require 'spiderfw/utils/thread_out'
15
16
  require 'spiderfw/utils/inflector'
@@ -0,0 +1,26 @@
1
+ require 'spiderfw/templates/template_blocks'
2
+
3
+ module Spider; module TemplateBlocks
4
+
5
+ # *sp:parent-context*
6
+ # Executes the content using the parent's scene
7
+
8
+ class ParentContext < Block
9
+
10
+ def compile(options={})
11
+ init = ""
12
+ c = ""
13
+ # c += "debugger\n"
14
+ parent_c, parent_init = compile_content(c, init, options)
15
+ parent_c.gsub!("'", "\\\\'")
16
+ parent_init.gsub!("'", "\\\\'")
17
+ c += "self[:_parent].instance_eval('def __run_block\n;#{parent_c}\nend\n')\n"
18
+ c += "yield :_parent\n"
19
+ return CompiledBlock.new(init, c)
20
+ end
21
+
22
+
23
+ end
24
+
25
+
26
+ end; end