spiderfw 0.5.9 → 0.5.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/apps/app_server/_init.rb +8 -0
  2. data/apps/app_server/app_server.rb +60 -0
  3. data/apps/app_server/config/options.rb +2 -0
  4. data/apps/app_server/controllers/app_server_controller.rb +20 -0
  5. data/apps/app_server/lib/app.rb +21 -0
  6. data/apps/app_server/lib/git_app.rb +22 -0
  7. data/apps/app_server/views/app_list.shtml +8 -0
  8. data/apps/app_server/views/app_server.layout.shtml +14 -0
  9. data/apps/cas_server/_init.rb +1 -1
  10. data/apps/config_editor/_init.rb +14 -0
  11. data/apps/config_editor/config_editor.appspec +3 -0
  12. data/apps/config_editor/controllers/config_editor_controller.rb +88 -0
  13. data/apps/config_editor/views/config_editor.layout.shtml +20 -0
  14. data/apps/config_editor/views/index.shtml +23 -0
  15. data/apps/config_editor/widgets/edit/edit.rb +13 -0
  16. data/apps/config_editor/widgets/edit/edit.shtml +4 -0
  17. data/apps/core/auth/models/group.rb +2 -2
  18. data/apps/core/components/public/js/jquery/plugins/jtree/jquery.jtree.1.0.js +187 -0
  19. data/apps/core/components/public/js/jquery/plugins/jtree/jquery.jtree.1.0.min.js +1 -0
  20. data/apps/core/components/public/js/jquery/plugins/jtree/jquery.jtree.spider.1.0.js +193 -0
  21. data/apps/core/components/widgets/table/table.rb +19 -9
  22. data/apps/core/components/widgets/table/table.shtml +2 -2
  23. data/apps/core/forms/widgets/inputs/subform/subform.rb +10 -0
  24. data/apps/core/forms/widgets/inputs/subform/subform.shtml +5 -0
  25. data/apps/hippo/script/converti_strutture.rb +335 -0
  26. data/apps/master/_init.rb +12 -0
  27. data/apps/master/controllers/master_controller.rb +110 -0
  28. data/apps/master/master.appspec +5 -0
  29. data/apps/master/models/customer.rb +13 -0
  30. data/apps/master/models/installation.rb +10 -0
  31. data/apps/master/models/resource.rb +10 -0
  32. data/apps/master/models/servant.rb +25 -0
  33. data/apps/master/views/customer.shtml +20 -0
  34. data/apps/master/views/customers.shtml +10 -0
  35. data/apps/master/views/index.shtml +4 -0
  36. data/apps/master/views/installation.shtml +36 -0
  37. data/apps/master/views/master.layout.shtml +14 -0
  38. data/apps/master/views/servant.shtml +26 -0
  39. data/apps/master/views/servants.shtml +7 -0
  40. data/apps/servant/_init.rb +5 -0
  41. data/apps/servant/bin/spider-servant.rb +47 -0
  42. data/apps/servant/lib/resource.rb +11 -0
  43. data/apps/servant/lib/resources/db/mysql.rb +31 -0
  44. data/apps/servant/lib/resources/db.rb +54 -0
  45. data/apps/servant/lib/servant.rb +82 -0
  46. data/apps/servant/servant.appspec +4 -0
  47. data/apps/servant/var/log/error.log +1 -0
  48. data/apps/worker/worker.rb +1 -1
  49. data/blueprints/install/config.ru +12 -0
  50. data/lib/spiderfw/app.rb +8 -0
  51. data/lib/spiderfw/cmd/cmd.rb +4 -2
  52. data/lib/spiderfw/cmd/commands/content.rb +33 -0
  53. data/lib/spiderfw/cmd/commands/{init.rb → create.rb} +4 -4
  54. data/lib/spiderfw/config/options/spider.rb +4 -0
  55. data/lib/spiderfw/controller/controller.rb +11 -1
  56. data/lib/spiderfw/controller/dispatcher.rb +2 -0
  57. data/lib/spiderfw/controller/home_controller.rb +7 -1
  58. data/lib/spiderfw/controller/mixins/static_content.rb +17 -3
  59. data/lib/spiderfw/controller/mixins/visual.rb +2 -2
  60. data/lib/spiderfw/controller/session.rb +2 -0
  61. data/lib/spiderfw/create.rb +2 -2
  62. data/lib/spiderfw/model/base_model.rb +11 -0
  63. data/lib/spiderfw/model/condition.rb +37 -7
  64. data/lib/spiderfw/model/mappers/db_mapper.rb +67 -71
  65. data/lib/spiderfw/model/mappers/mapper.rb +92 -31
  66. data/lib/spiderfw/model/model.rb +1 -0
  67. data/lib/spiderfw/model/query.rb +1 -3
  68. data/lib/spiderfw/model/query_funcs.rb +51 -0
  69. data/lib/spiderfw/model/storage/db/adapters/oci8.rb +4 -1
  70. data/lib/spiderfw/model/storage/db/db_schema.rb +15 -1
  71. data/lib/spiderfw/model/storage/db/db_storage.rb +8 -2
  72. data/lib/spiderfw/static_content.rb +84 -0
  73. data/lib/spiderfw/utils/monkey/date_time.rb +4 -0
  74. data/lib/spiderfw/utils/monkey/hpricot_compat.rb +0 -0
  75. data/lib/spiderfw/utils/monkey/object.rb +25 -0
  76. data/lib/spiderfw/utils/test_case.rb +24 -0
  77. metadata +54 -24
  78. data/apps/cms/models/content.rb +0 -16
  79. data/apps/cms/models/news_item.rb +0 -7
  80. data/apps/cms/models/translation.rb +0 -14
  81. data/apps/cms/views/admin/admin.shtml +0 -16
  82. data/apps/cms/views/admin/content.shtml +0 -4
  83. data/apps/core/acl/_init.rb +0 -10
  84. data/apps/core/acl/controllers/acl_controller.rb +0 -14
  85. data/apps/core/acl/models/permission.rb +0 -11
  86. data/apps/core/acl/views/acl.layout.shtml +0 -8
  87. data/apps/core/acl/views/index.shtml +0 -3
  88. data/apps/git_model_versioning/models/mixins/git_versioned.rb +0 -91
  89. data/apps/master/controllers/git.rb +0 -32
  90. data/apps/saml/_init.rb +0 -13
  91. data/apps/saml/controllers/saml2idp.rb +0 -18
  92. data/apps/saml/lib/bindings/http_redirect_binding.rb +0 -14
  93. data/apps/saml/lib/messages/authn_request.rb +0 -52
  94. data/apps/saml/lib/saml.rb +0 -10
  95. data/apps/soap/soap.gemspec +0 -10
  96. data/blueprints/model.rb +0 -15
  97. /data/blueprints/{install → home}/config/config.yml +0 -0
  98. /data/blueprints/{install → home}/init.rb +0 -0
@@ -1,10 +1,10 @@
1
1
  require 'spiderfw/create'
2
2
 
3
- class InitCommand < CmdParse::Command
3
+ class CreateCommand < CmdParse::Command
4
4
 
5
5
 
6
6
  def initialize
7
- super( 'init', true, true )
7
+ super( 'create', true, true )
8
8
  @short_desc = _("Create a working dir for development or installation")
9
9
  # @description = _("")
10
10
 
@@ -29,7 +29,7 @@ class InitCommand < CmdParse::Command
29
29
  end
30
30
  self.add_command(app, false)
31
31
 
32
- install = CmdParse::Command.new('install', false)
32
+ install = CmdParse::Command.new('home', false)
33
33
  install.short_desc = _("Create an installation")
34
34
  install.options = CmdParse::OptionParserWrapper.new do |opt|
35
35
  opt.on("--path",
@@ -41,7 +41,7 @@ class InitCommand < CmdParse::Command
41
41
  install.set_execution_block do |installs|
42
42
  @path ||= Dir.pwd
43
43
  installs.each do |inst|
44
- Spider::Create.install(inst, @path)
44
+ Spider::Create.home(inst, @path)
45
45
  end
46
46
  end
47
47
  self.add_command(install, false)
@@ -31,6 +31,10 @@ module Spider
31
31
  config_option 'webserver.force_threads', _("Force threading on non-threaded adapters"),
32
32
  :default => Proc.new{ RUBY_VERSION_PARTS[1] == '8' ? true : false }
33
33
  config_option 'webserver.timeout', _("Time allowed for each request (in seconds)"), :type=> Fixnum, :default => nil
34
+ config_option 'static_content.mode', _("Mode to use for serving static files"), :type => String,
35
+ :choices => [nil, 'x-sendfile', 'x-accel-redirect', 'published'], :default => nil
36
+ config_option 'static_content.auto_publish', _("Automatically publish content to the home's public folder"),
37
+ :type => Spider::DataTypes::Bool, :default => false
34
38
  # Client
35
39
  config_option 'client.text_editor', _("The text editor installed on the client")
36
40
 
@@ -54,7 +54,17 @@ module Spider
54
54
  return self.app.path+'/views'
55
55
  end
56
56
 
57
-
57
+ # Defines a method that will be called before the controller's before,
58
+ # if the action matches the given conditions.
59
+ # - The first argument, the condition(s), may be a String, a Regexp, a Proc or a Symbol,
60
+ # that will be checked against the action, or an Array containing several conditions.
61
+ # - The second argument, a Symbol, is the method to be called if the conditions match.
62
+ # - The third optional argument, an Hash, may contain :unless => true: in this case,
63
+ # the conditions will be inverted, that is, the method will be executed unless the conditions
64
+ # match.
65
+ # Example:
66
+ # before('list_', :before_lists)
67
+ # will call the method before_lists if the action starts with 'list_'
58
68
  def before(conditions, method, params={})
59
69
  @dispatch_methods ||= {}
60
70
  @dispatch_methods[:before] ||= []
@@ -238,6 +238,8 @@ module Spider
238
238
  return true if (action == check || (action[-1].chr == '/' && action[0..-2] == check))
239
239
  elsif check.is_a?(Regexp)
240
240
  return true if action =~ check
241
+ elsif check.is_a?(Proc)
242
+ return true if check.call(action)
241
243
  elsif (check.is_a?(Symbol))
242
244
  first, rest = action.split('/', 2)
243
245
  return true if first && first.to_sym == check
@@ -18,7 +18,13 @@ module Spider
18
18
 
19
19
  def self.pub_url
20
20
  HTTPMixin.reverse_proxy_mapping('/public')
21
- end
21
+ end
22
+
23
+ def self.app_pub_path(app=nil)
24
+ path = self.pub_path+'/apps'
25
+ path += '/'+app.short_name if app
26
+ path
27
+ end
22
28
 
23
29
  end
24
30
 
@@ -50,6 +50,12 @@ module Spider; module ControllerMixins
50
50
  path += ".#{@request.format}" if @request.format
51
51
  raise Spider::Controller::NotFound.new(path) unless path
52
52
  path = sanitize_path(path)
53
+ mode = Spider.conf.get('static_content.mode')
54
+ if mode == 'publish' && self.class != Spider::HomeController
55
+ url = self.pub_url
56
+ url += "/"+path
57
+ return redirect(url)
58
+ end
53
59
  full_path = pub_path+'/'+path
54
60
  raise Spider::Controller::NotFound.new(path) unless File.exist?(full_path)
55
61
  output_static(full_path)
@@ -66,6 +72,7 @@ module Spider; module ControllerMixins
66
72
 
67
73
  def output_static(full_path)
68
74
  debug("Serving asset: #{full_path}")
75
+ mode = Spider.conf.get('static_content.mode')
69
76
  raise Spider::Controller::NotFound.new(full_path) unless File.exist?(full_path)
70
77
  stat = File.lstat(full_path)
71
78
  if File.directory?(full_path)
@@ -78,9 +85,16 @@ module Spider; module ControllerMixins
78
85
  @response.headers['Content-Type'] = ct
79
86
  @response.headers['Content-Length'] = stat.size
80
87
  @response.headers['Last-Modified'] = stat.mtime.httpdate
81
- f = File.open(full_path, 'r')
82
- while (block = f.read(1024)) do
83
- $out << block
88
+
89
+ if mode == 'x-sendfile'
90
+ @response.headers['X-Sendfile'] = full_path
91
+ elsif mode == 'x-accel-redirect'
92
+ @response.headers['X-Accel-Redirect'] = full_path
93
+ else
94
+ f = File.open(full_path, 'r')
95
+ while (block = f.read(1024)) do
96
+ $out << block
97
+ end
84
98
  end
85
99
  end
86
100
 
@@ -5,7 +5,7 @@ module Spider; module ControllerMixins
5
5
 
6
6
  # Mixin for objects using templates
7
7
  module Visual
8
-
8
+ attr_reader :template
9
9
  attr_accessor :layout, :dispatcher_layout
10
10
 
11
11
  def self.included(klass)
@@ -68,7 +68,6 @@ module Spider; module ControllerMixins
68
68
  first, rest = widget_target.split('/', 2)
69
69
  @_widget = find_widget(first)
70
70
  raise Spider::Controller::NotFound.new("Widget #{widget_target}") unless @_widget
71
- @is_target = false
72
71
  @_widget.is_target = true unless rest
73
72
  @_widget.set_action(widget_execute) if widget_execute
74
73
  @_widget.target_mode = true
@@ -83,6 +82,7 @@ module Spider; module ControllerMixins
83
82
 
84
83
  def execute(action='', *params)
85
84
  @visual_params = @executed_format_params
85
+ @is_target = false if @request.params['_wt']
86
86
  if (self.is_a?(Widget) && @is_target && @request.params['_wp'])
87
87
  params = @request.params['_wp']
88
88
  elsif (@visual_params.is_a?(Hash) && @visual_params[:params])
@@ -56,6 +56,8 @@ module Spider
56
56
 
57
57
  def []=(key, val)
58
58
  restore unless @restored
59
+ raise "You can't overwrite the :_flash Hash" if key == :_flash
60
+ raise "You can't overwrite the :_transient Hash" if key == :_transient
59
61
  @data[key] = val
60
62
  end
61
63
 
@@ -28,9 +28,9 @@ module Spider
28
28
  create(source_folder, dest_folder, replacements, erb_binding)
29
29
  end
30
30
 
31
- def self.install(name, path)
31
+ def self.home(name, path)
32
32
  dest_path = path+'/'+name
33
- source_path = $SPIDER_PATH+'/blueprints/install'
33
+ source_path = $SPIDER_PATH+'/blueprints/home'
34
34
  create(source_path, dest_path)
35
35
  end
36
36
 
@@ -53,6 +53,7 @@ module Spider; module Model
53
53
  class BaseModel
54
54
  include Spider::Logger
55
55
  include DataTypes
56
+ include Spider::QueryFuncs
56
57
  # include StateMachine
57
58
 
58
59
  # The BaseModel class itself. Used when dealing with proxy objects.
@@ -167,6 +168,8 @@ module Spider; module Model
167
168
  # :read_only:: (bool) hint to the UI that the element should not be user modifiable.
168
169
  # :owned:: (bool) only this model holds references to type
169
170
  # :condition:: (hash or Condition) Restricts an association always adding the condition.
171
+ # :order:: (true or Fixnum) When doing queries, sort by this element. More than one element can have the
172
+ # :order attribute; if it is a Fixnum, it will mean the position in the ordering.
170
173
  #
171
174
  # Other attributes may be used by DataTypes (see #DataType::ClassMethods.take_attributes), and other code.
172
175
  # See also Element.
@@ -503,6 +506,7 @@ module Spider; module Model
503
506
  attributes.delete(:add_multiple_reverse)
504
507
  end
505
508
  attributes.delete(:primary_key) unless (params[:keep_pks])
509
+ attributes.delete(:required)
506
510
  name = params[:mapping] && params[:mapping][el.name] ? params[:mapping][el.name] : el.name
507
511
  element(name, el.type, attributes)
508
512
  end
@@ -1756,6 +1760,13 @@ module Spider; module Model
1756
1760
  mapper.delete_element_associations(self, element, object)
1757
1761
  end
1758
1762
 
1763
+ # Method that will be called by the mapper before a query. May be overridden to preprocess the query.
1764
+ # Must return the modified query. Note: to prepare conditions, use prepare_condition, since it will
1765
+ # be called on subconditions as well.
1766
+ def self.prepare_query(query)
1767
+ query
1768
+ end
1769
+
1759
1770
  ##############################################################
1760
1771
  # Method missing #
1761
1772
  ##############################################################
@@ -125,7 +125,16 @@ module Spider; module Model
125
125
  # Yields each key, value and comparison.
126
126
  def each_with_comparison
127
127
  self.each do |k, v|
128
- yield k, v, @comparisons[k.to_sym] || '='
128
+ k = k.to_sym if k.respond_to?(:to_sym)
129
+ yield k, v, @comparisons[k] || '='
130
+ end
131
+ end
132
+
133
+ # Yields each key, value and comparison, for this condition and its subconditions
134
+ def all_each_with_comparison
135
+ self.each_with_comparison{ |k, v, c| yield k, v, c }
136
+ @subconditions.each do |sub|
137
+ sub.all_each_with_comparison{ |k, v, c| yield k, v, c }
129
138
  end
130
139
  end
131
140
 
@@ -164,10 +173,13 @@ module Spider; module Model
164
173
  @subconditions << or_cond
165
174
  return self
166
175
  end
167
- field = field.to_s
168
- parts = field.split('.', 2)
169
- parts[0] = parts[0].to_sym
170
- field = field.to_sym unless parts[1]
176
+ parts = []
177
+ unless field.is_a?(Spider::QueryFuncs::Function)
178
+ field = field.to_s
179
+ parts = field.split('.', 2)
180
+ parts[0] = parts[0].to_sym
181
+ field = field.to_sym unless parts[1]
182
+ end
171
183
  if (parts[1])
172
184
  hash_set(parts[0], get_deep_obj()) unless self[parts[0]]
173
185
  self[parts[0]].set(parts[1], comparison, value)
@@ -190,7 +202,8 @@ module Spider; module Model
190
202
  def [](key)
191
203
  # TODO: deep
192
204
  key = key.name if key.class == Element
193
- super(key.to_sym)
205
+ key = key.to_sym if key.respond_to?(:to_sym) # might be a QueryFunc
206
+ super(key)
194
207
  end
195
208
 
196
209
  # Adds a range condition. This creates a subcondition with >= and <= conditions.
@@ -203,8 +216,12 @@ module Spider; module Model
203
216
 
204
217
  # Deletes a field from the Condition.
205
218
  def delete(field)
219
+ field = field.to_sym
220
+ return nil unless self[field] || @comparisons[field]
221
+ cur = [self[field], @comparisons[field]]
206
222
  super
207
- @comparisons.delete(field.to_sym)
223
+ @comparisons.delete(field)
224
+ cur
208
225
  end
209
226
 
210
227
  # Parses a string comparison.
@@ -343,6 +360,19 @@ module Spider; module Model
343
360
  pol << @polymorph if @polymorph
344
361
  return pol + @subconditions.inject([]){ |arr, s| arr += s.polymorphs }
345
362
  end
363
+
364
+ # Returns, from self and subconditions, all those who define a condition for one of the given element names.
365
+ def conditions_for(*element_names)
366
+ conds = []
367
+ element_names.each do |el|
368
+ if self[el]
369
+ conds << self
370
+ break
371
+ end
372
+ end
373
+ @subconditions.map{ |s| s.conditions_for(*element_names) }.each{ |c| conds += c }
374
+ conds
375
+ end
346
376
 
347
377
  end
348
378
 
@@ -136,7 +136,7 @@ module Spider; module Model; module Mappers
136
136
  @model.primary_keys.each do |key|
137
137
  condition[key.name] = map_condition_value(key.type, obj.get(key))
138
138
  end
139
- prepare_query_condition(condition)
139
+ preprocess_condition(condition)
140
140
  save[:condition], save[:joins] = prepare_condition(condition)
141
141
  save[:joins] = prepare_joins(save[:joins])
142
142
  save[:table] = @schema.table
@@ -148,7 +148,7 @@ module Spider; module Model; module Mappers
148
148
  db_values = {}
149
149
  joins = []
150
150
  integrated = {}
151
- condition = prepare_query_condition(condition)
151
+ condition = preprocess_condition(condition)
152
152
  values.each do |key, val|
153
153
  element = @model.elements[key]
154
154
  if (element.integrated?)
@@ -299,7 +299,6 @@ module Spider; module Model; module Mappers
299
299
 
300
300
  # Returns true if an element can be loaded joined-in.
301
301
  def can_join?(element)
302
- return false if element.multiple?
303
302
  return false if element.storage != @storage
304
303
  return true
305
304
  end
@@ -471,60 +470,47 @@ module Spider; module Model; module Mappers
471
470
  #--
472
471
  # TODO: better name for :values
473
472
  def prepare_condition(condition, options={})
474
- # FIXME: move to mapper
475
473
  model = condition.polymorph ? condition.polymorph : @model
476
474
  model_schema = model.mapper.schema
477
475
  cond = {}
478
- # debugger if condition.polymorph
479
- condition.each_with_comparison do |k, v, comp|
480
- # normalize condition values
481
- element = model.elements[k.to_sym]
482
- if (v && !v.is_a?(Condition) && element.model?)
483
- condition.delete(element.name)
484
- def set_pks_condition(condition, el, val, prefix)
485
- el.model.primary_keys.each do |primary_key|
486
- new_prefix = "#{prefix}.#{primary_key.name}"
487
- if (primary_key.model?)
488
- if (primary_key.model.primary_keys.length == 1)
489
- # FIXME: this should not be needed, see below
490
- condition.set(new_prefix, '=', val.get(primary_key).get(primary_key.model.primary_keys[0]))
491
- else
492
- # FIXME! does not work, the subcondition does not get processed
493
- raise "Subconditions on multiple key elements not supported yet"
494
- subcond = Condition.new
495
- set_pks_condition(subcond, primary_key, val.get(primary_key), new_prefix)
496
- condition << subcond
497
- end
498
- else
499
- condition.set(new_prefix, '=', val.get(primary_key))
500
- end
501
- end
502
- end
503
- if v.is_a?(BaseModel)
504
- set_pks_condition(condition, element, v, element.name)
505
- elsif element.model.primary_keys.length == 1
506
- new_v = Condition.new
507
- if (model.mapper.have_references?(element.name))
508
- new_v.set(element.model.primary_keys[0].name, comp, v)
509
- else
510
- new_v.set(element.reverse, comp, v)
511
- end
512
- condition.set(element.name, comp, new_v)
513
- else
514
- raise MapperError, "Value condition passed on #{k}, but #{element.model} has more then one primary key"
515
- end
516
- end
517
- end
476
+
518
477
  bind_values = []
519
478
  joins = options[:joins] || []
520
479
  remaining_condition = Condition.new # TODO: implement
521
480
  cond[:conj] = condition.conjunction.to_s
522
481
  cond[:values] = []
482
+
483
+ # find out which elements have non nil conditions to figure out joins
484
+ def get_not_nil(model, condition, not_nil)
485
+ condition.all_each_with_comparison do |k, v, comp|
486
+ next unless k.respond_to?(:to_sym)
487
+ element = model.elements[k.to_sym]
488
+ next unless element
489
+ next unless model.mapper.mapped?(element)
490
+ next unless element.model?
491
+ not_nil[k] = {} if !v.nil? || comp != '='
492
+ get_not_nil(element.model, v, not_nil[k]) if v.is_a?(Condition)
493
+ end
494
+ end
495
+
496
+ not_nil = options[:not_nil]
497
+ unless not_nil
498
+ not_nil = {}
499
+ get_not_nil(@model, condition, not_nil)
500
+ end
501
+
523
502
  condition.each_with_comparison do |k, v, comp|
503
+ if k.is_a?(QueryFuncs::Function)
504
+ field = prepare_queryfunc(k)
505
+ cond[:values] << [field, comp, v]
506
+ joins += field.joins
507
+ next
508
+ end
524
509
  element = model.elements[k.to_sym]
525
510
  next unless model.mapper.mapped?(element)
526
511
  if (element.model?)
527
- if (v && model.mapper.have_references?(element.name) && v.select{ |key, value| !element.model.elements[key].primary_key? }.empty?)
512
+ if (v && model.mapper.have_references?(element.name) && v.select{ |key, value|
513
+ !element.model.elements[key] || !element.model.elements[key].primary_key? }.empty?)
528
514
  # 1/n <-> 1 with only primary keys
529
515
  element_cond = {:conj => 'AND', :values => []}
530
516
  v.each_with_comparison do |el_k, el_v, el_comp|
@@ -537,11 +523,7 @@ module Spider; module Model; module Mappers
537
523
  cond[:values] << element_cond
538
524
  else
539
525
  if (element.storage == model.mapper.storage)
540
- if v.nil?
541
- join_type = comp == '=' ? :left : :inner
542
- else
543
- join_type = :inner
544
- end
526
+ join_type = (v.nil? && comp == '=') ? :left : :inner
545
527
  sub_join = model.mapper.get_join(element, join_type)
546
528
  # FIXME! cleanup, and apply the check to joins acquired in other places, too (maybe pass the current joins to get_join)
547
529
  existent = joins.select{ |j| j[:to] == sub_join[:to] }
@@ -560,17 +542,25 @@ module Spider; module Model; module Mappers
560
542
  sub_join[:as] = "#{sub_join[:to]}#{j_cnt}" if j_cnt
561
543
  joins << sub_join unless had_join
562
544
 
563
- if v.nil? && comp == '='
545
+ if v.nil? && comp == '=' && !not_nil[element.name]
564
546
  element_cond = {:conj => 'AND', :values => []}
565
- element.model.primary_keys.each do |k|
566
- field = model_schema.qualified_foreign_key_field(element.name, k.name)
547
+ if model.mapper.have_references?(element.name)
548
+ el_name = element.name
549
+ el_model = element.model
550
+ else
551
+ el_model = element.type
552
+ model_schema = element.model.mapper.schema
553
+ el_name = element.attributes[:junction_their_element]
554
+ end
555
+ el_model.primary_keys.each do |k|
556
+ field = model_schema.qualified_foreign_key_field(el_name, k.name)
567
557
  field_cond = [field, comp, map_condition_value(element.model.elements[k.name].type, nil)]
568
558
  element_cond[:values] << field_cond
569
559
  end
570
560
  cond[:values] << element_cond
571
561
  elsif v
572
- element.model.mapper.prepare_query_condition(v)
573
- sub_condition, sub_joins = element.mapper.prepare_condition(v, :table => sub_join[:as], :joins => joins)
562
+ v = element.model.mapper.preprocess_condition(v)
563
+ sub_condition, sub_joins = element.mapper.prepare_condition(v, :table => sub_join[:as], :joins => joins, :not_nil => not_nil[element.name])
574
564
  sub_condition[:table] = sub_join[:as] if sub_join[:as]
575
565
  joins = sub_joins
576
566
  cond[:values] << sub_condition
@@ -597,7 +587,7 @@ module Spider; module Model; module Mappers
597
587
  sub_sqls = []
598
588
  sub_bind_values = []
599
589
  condition.subconditions.each do |sub|
600
- sub_res = self.prepare_condition(sub, :joins => joins)
590
+ sub_res = self.prepare_condition(sub, :joins => joins, :not_nil => not_nil)
601
591
  cond[:values] << sub_res[0]
602
592
  joins = sub_res[1]
603
593
  remaining_condition += sub_res[2]
@@ -605,6 +595,7 @@ module Spider; module Model; module Mappers
605
595
  return [cond, joins, remaining_condition]
606
596
  end
607
597
 
598
+
608
599
  # Figures out a join for element. Returns join hash description, i.e. :
609
600
  # join = {
610
601
  # :type => :inner|:outer|...,
@@ -615,11 +606,11 @@ module Spider; module Model; module Mappers
615
606
  # }
616
607
  def get_join(element, join_type = :inner)
617
608
  return unless element.model?
618
- Spider::Logger.debug("Getting join for model #{@model} to element #{element}")
619
- Spider::Logger.debug(@model.primary_keys.map{|k| k.name})
609
+ #Spider::Logger.debug("Getting join for model #{@model} to element #{element}")
610
+ #Spider::Logger.debug(@model.primary_keys.map{|k| k.name})
620
611
  element_table = element.mapper.schema.table
621
612
  if (schema.has_foreign_fields?(element.name))
622
- Spider::Logger.debug("JOIN A from #{@model} to #{element.name}")
613
+ #Spider::Logger.debug("JOIN A from #{@model} to #{element.name}")
623
614
  keys = {}
624
615
  element.model.primary_keys.each do |key|
625
616
  if (key.integrated?)
@@ -631,7 +622,6 @@ module Spider; module Model; module Mappers
631
622
  end
632
623
 
633
624
  fk = schema.foreign_key_field(element.name, key.name)
634
- fk = fk.expression if fk.is_a?(FieldExpression)
635
625
  keys[fk] = el_field
636
626
  # FIXME: works with models as primary keys through a hack in the field method of db_schema,
637
627
  # assuming the model has only one key. the correct way would be to get another join
@@ -652,7 +642,7 @@ module Spider; module Model; module Mappers
652
642
  :as => as
653
643
  }
654
644
  elsif (element.has_single_reverse? && element.mapper.schema.has_foreign_fields?(element.reverse)) # n/1 <-> n
655
- Spider::Logger.debug("JOIN B from #{@model} to #{element.name}")
645
+ #Spider::Logger.debug("JOIN B from #{@model} to #{element.name}")
656
646
  keys = {}
657
647
  @model.primary_keys.each do |key|
658
648
  our_field = nil
@@ -662,7 +652,6 @@ module Spider; module Model; module Mappers
662
652
  our_field = schema.field(key.name)
663
653
  end
664
654
  keys[our_field] = element.mapper.schema.foreign_key_field(element.reverse, key.name)
665
- keys[our_field] = keys[our_field].expression if keys[our_field].is_a?(FieldExpression)
666
655
  end
667
656
  if (element.condition)
668
657
  condition, condition_joins, condition_remaining = element.mapper.prepare_condition(element.condition)
@@ -695,6 +684,7 @@ module Spider; module Model; module Mappers
695
684
  Spider::Logger.debug("GETTING DEEP JOIN TO #{dotted_element} (#{@model})")
696
685
  parts.each do |part|
697
686
  el = current_model.elements[part]
687
+ raise "Can't find element #{part} in model #{current_model}" unless el
698
688
  if (el.integrated?)
699
689
  joins << current_model.mapper.get_join(el.integrated_from)
700
690
  current_model = el.integrated_from.type
@@ -714,6 +704,18 @@ module Spider; module Model; module Mappers
714
704
  return [joins, current_model, el]
715
705
  end
716
706
 
707
+ def prepare_queryfunc(func)
708
+ joins = []
709
+ func_elements = func.inner_elements
710
+ func_elements.each do |el_name, owner_func|
711
+ el_joins, el_model, el = get_deep_join(el_name)
712
+ joins += el_joins
713
+ owner_func.mapper_fields ||= {}
714
+ owner_func.mapper_fields[el.name] = el_model.mapper.schema.field(el.name)
715
+ end
716
+ return FieldFunction.new(storage.function(func), schema.table, joins)
717
+ end
718
+
717
719
  # Takes a Spider::QueryFuncs::Expression, and associates the fields to the corresponding elements
718
720
  # Returns an array of needed joins
719
721
  def prepare_expression(expr)
@@ -737,15 +739,8 @@ module Spider; module Model; module Mappers
737
739
  order_element, direction = order
738
740
  el_model = @model
739
741
  if (order_element.is_a?(QueryFuncs::Function))
740
- func_fields = []
741
- func_elements = order_element.inner_elements
742
- func_elements.each do |el_name, owner_func|
743
- el_joins, el_model, el = get_deep_join(el_name)
744
- joins += el_joins
745
- owner_func.mapper_fields ||= {}
746
- owner_func.mapper_fields[el.name] = el_model.mapper.schema.field(el.name)
747
- end
748
- field = storage.function(order_element)
742
+ field = prepare_queryfunc(order_element)
743
+ joins += field.joins
749
744
  fields << [field, direction]
750
745
  else
751
746
  el_joins, el_model, el = get_deep_join(order_element)
@@ -761,6 +756,7 @@ module Spider; module Model; module Mappers
761
756
  end
762
757
  end
763
758
  else
759
+ raise "Order on unmapped element #{el_model.name}.#{el.name}" unless el_model.mapper.mapped?(el)
764
760
  field = el_model.mapper.schema.field(el.name)
765
761
  fields << [field, direction]
766
762
  end