spiderfw 0.5.10 → 0.5.11

Sign up to get free protection for your applications and to get access to all the features.
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