radiant 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of radiant might be problematic. Click here for more details.

Files changed (197) hide show
  1. data/CHANGELOG +61 -7
  2. data/CONTRIBUTORS +15 -0
  3. data/app/controllers/admin/export_controller.rb +1 -1
  4. data/app/controllers/admin/page_controller.rb +1 -0
  5. data/app/controllers/admin/user_controller.rb +2 -1
  6. data/app/controllers/application.rb +7 -8
  7. data/app/helpers/admin/node_helper.rb +84 -0
  8. data/app/helpers/admin/page_helper.rb +1 -19
  9. data/app/helpers/application_helper.rb +15 -9
  10. data/app/models/file_not_found_page.rb +2 -2
  11. data/app/models/page.rb +22 -18
  12. data/app/models/page_context.rb +9 -0
  13. data/app/models/radiant/config.rb +4 -2
  14. data/app/models/response_cache.rb +18 -12
  15. data/app/models/standard_tags.rb +111 -50
  16. data/app/views/admin/extension/index.rhtml +2 -2
  17. data/app/views/admin/layout/edit.rhtml +2 -2
  18. data/app/views/admin/layout/remove.rhtml +2 -2
  19. data/app/views/admin/page/_node.rhtml +4 -26
  20. data/app/views/admin/page/_part.rhtml +9 -14
  21. data/app/views/admin/page/edit.rhtml +38 -121
  22. data/app/views/admin/page/index.rhtml +2 -6
  23. data/app/views/admin/page/remove.rhtml +2 -2
  24. data/app/views/admin/snippet/edit.rhtml +3 -3
  25. data/app/views/admin/snippet/index.rhtml +2 -2
  26. data/app/views/admin/snippet/remove.rhtml +2 -2
  27. data/app/views/admin/user/edit.rhtml +4 -4
  28. data/app/views/admin/user/preferences.rhtml +2 -2
  29. data/app/views/admin/welcome/login.rhtml +1 -1
  30. data/config/environment.rb +79 -78
  31. data/db/schema.rb +2 -0
  32. data/lib/local_time.rb +12 -0
  33. data/lib/plugins/extension_patches/lib/fixture_loading_extension.rb +1 -1
  34. data/lib/plugins/extension_patches/lib/mailer_view_paths_extension.rb +3 -3
  35. data/lib/radiant.rb +1 -1
  36. data/lib/radiant/extension.rb +9 -3
  37. data/lib/radiant/extension_loader.rb +2 -2
  38. data/lib/tasks/extensions.rake +23 -8
  39. data/public/javascripts/admin.js +89 -0
  40. data/public/javascripts/controls.js +486 -354
  41. data/public/javascripts/dragdrop.js +90 -58
  42. data/public/javascripts/effects.js +398 -364
  43. data/public/javascripts/pngfix.js +37 -37
  44. data/public/javascripts/prototype.js +2764 -1095
  45. data/public/javascripts/ruledtable.js +10 -25
  46. data/public/javascripts/sitemap.js +74 -112
  47. data/public/javascripts/string.js +1 -7
  48. data/public/javascripts/tabcontrol.js +71 -86
  49. data/public/javascripts/tag_reference_search.js +19 -26
  50. data/public/stylesheets/admin/main.css +11 -5
  51. data/test/fixtures/extensions/01_basic/lib/new_module.rb +2 -0
  52. data/test/fixtures/page_parts.yml +16 -1
  53. data/test/fixtures/pages.yml +47 -84
  54. data/test/functional/extension_initialization_test.rb +11 -0
  55. data/test/helpers/login_test_helper.rb +12 -1
  56. data/test/helpers/page_test_helper.rb +6 -0
  57. data/test/helpers/render_test_helper.rb +11 -8
  58. data/test/test_helper.rb +1 -12
  59. data/test/unit/file_not_found_page_test.rb +5 -1
  60. data/test/unit/local_time_test.rb +45 -0
  61. data/test/unit/page_context_test.rb +32 -1
  62. data/test/unit/page_test.rb +45 -11
  63. data/test/unit/radiant/config_test.rb +1 -1
  64. data/test/unit/response_cache_test.rb +27 -2
  65. data/test/unit/standard_tags_test.rb +60 -15
  66. data/vendor/extensions/archive/README +29 -0
  67. data/vendor/extensions/archive/Rakefile +25 -0
  68. data/{app → vendor/extensions/archive/app}/models/archive_day_index_page.rb +0 -0
  69. data/{app → vendor/extensions/archive/app}/models/archive_finder.rb +8 -6
  70. data/{app → vendor/extensions/archive/app}/models/archive_month_index_page.rb +0 -0
  71. data/{app → vendor/extensions/archive/app}/models/archive_page.rb +0 -0
  72. data/{app → vendor/extensions/archive/app}/models/archive_year_index_page.rb +0 -0
  73. data/vendor/extensions/archive/archive_extension.rb +19 -0
  74. data/{lib → vendor/extensions/archive/lib}/archive_index_tags_and_methods.rb +0 -0
  75. data/vendor/extensions/archive/lib/tasks/archive_extension_tasks.rake +28 -0
  76. data/vendor/extensions/archive/test/fixtures/pages.yml +397 -0
  77. data/vendor/extensions/archive/test/functional/archive_extension_test.rb +16 -0
  78. data/{test → vendor/extensions/archive/test}/helpers/archive_index_test_helper.rb +0 -0
  79. data/vendor/extensions/archive/test/test_helper.rb +19 -0
  80. data/{test → vendor/extensions/archive/test}/unit/archive_day_index_page_test.rb +0 -0
  81. data/{test → vendor/extensions/archive/test}/unit/archive_month_index_page_test.rb +0 -0
  82. data/{test → vendor/extensions/archive/test}/unit/archive_page_test.rb +7 -1
  83. data/{test → vendor/extensions/archive/test}/unit/archive_year_index_page_test.rb +0 -0
  84. data/vendor/rails/actionmailer/CHANGELOG +10 -0
  85. data/vendor/rails/actionmailer/Rakefile +1 -1
  86. data/vendor/rails/actionmailer/lib/action_mailer/version.rb +1 -1
  87. data/vendor/rails/actionpack/CHANGELOG +51 -2
  88. data/vendor/rails/actionpack/Rakefile +1 -1
  89. data/vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb +2 -2
  90. data/vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb +1 -1
  91. data/vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb +3 -0
  92. data/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb +1 -0
  93. data/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb +2 -0
  94. data/vendor/rails/actionpack/lib/action_controller/base.rb +7 -1
  95. data/vendor/rails/actionpack/lib/action_controller/caching.rb +39 -38
  96. data/vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb +30 -0
  97. data/vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb +1 -1
  98. data/vendor/rails/actionpack/lib/action_controller/cgi_process.rb +13 -4
  99. data/vendor/rails/actionpack/lib/action_controller/cookies.rb +5 -3
  100. data/vendor/rails/actionpack/lib/action_controller/filters.rb +176 -77
  101. data/vendor/rails/actionpack/lib/action_controller/integration.rb +31 -21
  102. data/vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb +1 -1
  103. data/vendor/rails/actionpack/lib/action_controller/pagination.rb +7 -1
  104. data/vendor/rails/actionpack/lib/action_controller/resources.rb +117 -32
  105. data/vendor/rails/actionpack/lib/action_controller/routing.rb +56 -23
  106. data/vendor/rails/actionpack/lib/action_controller/test_process.rb +5 -2
  107. data/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb +4 -1
  108. data/vendor/rails/actionpack/lib/action_controller/verification.rb +1 -0
  109. data/vendor/rails/actionpack/lib/action_pack/version.rb +1 -1
  110. data/vendor/rails/actionpack/lib/action_view/base.rb +25 -19
  111. data/vendor/rails/actionpack/lib/action_view/compiled_templates.rb +2 -2
  112. data/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb +18 -18
  113. data/vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb +10 -0
  114. data/vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb +3 -0
  115. data/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb +33 -17
  116. data/vendor/rails/actionpack/test/activerecord/pagination_test.rb +9 -0
  117. data/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb +13 -0
  118. data/vendor/rails/actionpack/test/controller/addresses_render_test.rb +4 -1
  119. data/vendor/rails/actionpack/test/controller/base_test.rb +1 -1
  120. data/vendor/rails/actionpack/test/controller/caching_test.rb +3 -2
  121. data/vendor/rails/actionpack/test/controller/cookie_test.rb +11 -0
  122. data/vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb +18 -0
  123. data/vendor/rails/actionpack/test/controller/filter_params_test.rb +1 -0
  124. data/vendor/rails/actionpack/test/controller/filters_test.rb +149 -26
  125. data/vendor/rails/actionpack/test/controller/integration_test.rb +93 -8
  126. data/vendor/rails/actionpack/test/controller/resources_test.rb +215 -36
  127. data/vendor/rails/actionpack/test/controller/routing_test.rb +2 -2
  128. data/vendor/rails/actionpack/test/controller/test_test.rb +16 -0
  129. data/vendor/rails/actionpack/test/controller/url_rewriter_test.rb +66 -10
  130. data/vendor/rails/actionpack/test/controller/verification_test.rb +15 -0
  131. data/vendor/rails/actionpack/test/fixtures/test/hello_world.rxml +2 -1
  132. data/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb +5 -0
  133. data/vendor/rails/actionpack/test/template/compiled_templates_test.rb +29 -17
  134. data/vendor/rails/actionpack/test/template/javascript_helper_test.rb +4 -4
  135. data/vendor/rails/actionpack/test/template/number_helper_test.rb +1 -1
  136. data/vendor/rails/actionpack/test/template/prototype_helper_test.rb +13 -13
  137. data/vendor/rails/actionwebservice/CHANGELOG +14 -0
  138. data/vendor/rails/actionwebservice/Rakefile +2 -2
  139. data/vendor/rails/actionwebservice/lib/action_web_service/version.rb +1 -1
  140. data/vendor/rails/activerecord/CHANGELOG +34 -0
  141. data/vendor/rails/activerecord/Rakefile +1 -1
  142. data/vendor/rails/activerecord/lib/active_record/acts/list.rb +14 -2
  143. data/vendor/rails/activerecord/lib/active_record/acts/tree.rb +7 -0
  144. data/vendor/rails/activerecord/lib/active_record/associations.rb +29 -14
  145. data/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb +5 -1
  146. data/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb +2 -2
  147. data/vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb +10 -0
  148. data/vendor/rails/activerecord/lib/active_record/base.rb +12 -3
  149. data/vendor/rails/activerecord/lib/active_record/calculations.rb +2 -2
  150. data/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  151. data/vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  152. data/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +2 -2
  153. data/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb +54 -38
  154. data/vendor/rails/activerecord/lib/active_record/deprecated_finders.rb +3 -3
  155. data/vendor/rails/activerecord/lib/active_record/fixtures.rb +1 -1
  156. data/vendor/rails/activerecord/lib/active_record/timestamp.rb +0 -9
  157. data/vendor/rails/activerecord/lib/active_record/version.rb +1 -1
  158. data/vendor/rails/activerecord/test/associations/eager_test.rb +13 -0
  159. data/vendor/rails/activerecord/test/associations/join_model_test.rb +10 -1
  160. data/vendor/rails/activerecord/test/associations_test.rb +36 -3
  161. data/vendor/rails/activerecord/test/base_test.rb +17 -4
  162. data/vendor/rails/activerecord/test/defaults_test.rb +15 -0
  163. data/vendor/rails/activerecord/test/fixtures/author.rb +1 -0
  164. data/vendor/rails/activerecord/test/fixtures/binaries.yml +437 -0
  165. data/vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb +13 -0
  166. data/vendor/rails/activerecord/test/fixtures/developer.rb +10 -0
  167. data/vendor/rails/activerecord/test/fixtures_test.rb +9 -5
  168. data/vendor/rails/activerecord/test/migration_test.rb +9 -10
  169. data/vendor/rails/activerecord/test/mixin_test.rb +47 -0
  170. data/vendor/rails/activerecord/test/validations_test.rb +2 -2
  171. data/vendor/rails/activesupport/CHANGELOG +16 -0
  172. data/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb +9 -3
  173. data/vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb +48 -3
  174. data/vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb +14 -0
  175. data/vendor/rails/activesupport/lib/active_support/dependencies.rb +3 -3
  176. data/vendor/rails/activesupport/lib/active_support/json/encoders/core.rb +5 -3
  177. data/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb +6 -6
  178. data/vendor/rails/activesupport/lib/active_support/version.rb +1 -1
  179. data/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb +37 -0
  180. data/vendor/rails/activesupport/test/core_ext/module_test.rb +8 -0
  181. data/vendor/rails/activesupport/test/dependencies_test.rb +11 -0
  182. data/vendor/rails/activesupport/test/{json.rb → json_test.rb} +15 -5
  183. data/vendor/rails/railties/CHANGELOG +25 -1
  184. data/vendor/rails/railties/README +32 -3
  185. data/vendor/rails/railties/Rakefile +5 -5
  186. data/vendor/rails/railties/environments/boot.rb +12 -18
  187. data/vendor/rails/railties/environments/environment.rb +15 -15
  188. data/vendor/rails/railties/lib/dispatcher.rb +1 -2
  189. data/vendor/rails/railties/lib/initializer.rb +33 -9
  190. data/vendor/rails/railties/lib/rails/version.rb +1 -1
  191. data/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +1 -1
  192. data/vendor/rails/railties/lib/rails_generator/generators/components/scaffold_resource/scaffold_resource_generator.rb +1 -0
  193. data/vendor/rails/railties/lib/railties_path.rb +1 -1
  194. data/vendor/rails/railties/lib/tasks/framework.rake +4 -4
  195. data/vendor/rails/railties/lib/tasks/routes.rake +17 -0
  196. data/vendor/rails/release.rb +2 -2
  197. metadata +1877 -1848
@@ -151,7 +151,7 @@ spec = Gem::Specification.new do |s|
151
151
  s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
152
152
  end
153
153
 
154
- s.add_dependency('activesupport', '= 1.4.2' + PKG_BUILD)
154
+ s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD)
155
155
 
156
156
  s.files.delete "test/fixtures/fixture_database.sqlite"
157
157
  s.files.delete "test/fixtures/fixture_database_2.sqlite"
@@ -63,7 +63,7 @@ module ActiveRecord
63
63
 
64
64
  #{scope_condition_method}
65
65
 
66
- after_destroy :remove_from_list
66
+ before_destroy :remove_from_list
67
67
  before_create :add_to_list_bottom
68
68
  EOV
69
69
  end
@@ -74,6 +74,7 @@ module ActiveRecord
74
74
  # lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return true if that chapter is
75
75
  # the first in the list of all chapters.
76
76
  module InstanceMethods
77
+ # Insert the item at the given position (defaults to the top position of 1).
77
78
  def insert_at(position = 1)
78
79
  insert_at_position(position)
79
80
  end
@@ -118,8 +119,12 @@ module ActiveRecord
118
119
  end
119
120
  end
120
121
 
122
+ # Removes the item from the list.
121
123
  def remove_from_list
122
- decrement_positions_on_lower_items if in_list?
124
+ if in_list?
125
+ decrement_positions_on_lower_items
126
+ update_attribute position_column, nil
127
+ end
123
128
  end
124
129
 
125
130
  # Increase the position of this item without adjusting the rest of the list.
@@ -162,6 +167,7 @@ module ActiveRecord
162
167
  )
163
168
  end
164
169
 
170
+ # Test if this record is in a list
165
171
  def in_list?
166
172
  !send(position_column).nil?
167
173
  end
@@ -178,21 +184,26 @@ module ActiveRecord
178
184
  # Overwrite this method to define the scope of the list changes
179
185
  def scope_condition() "1" end
180
186
 
187
+ # Returns the bottom position number in the list.
188
+ # bottom_position_in_list # => 2
181
189
  def bottom_position_in_list(except = nil)
182
190
  item = bottom_item(except)
183
191
  item ? item.send(position_column) : 0
184
192
  end
185
193
 
194
+ # Returns the bottom item
186
195
  def bottom_item(except = nil)
187
196
  conditions = scope_condition
188
197
  conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
189
198
  acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
190
199
  end
191
200
 
201
+ # Forces item to assume the bottom position in the list.
192
202
  def assume_bottom_position
193
203
  update_attribute(position_column, bottom_position_in_list(self).to_i + 1)
194
204
  end
195
205
 
206
+ # Forces item to assume the top position in the list.
196
207
  def assume_top_position
197
208
  update_attribute(position_column, 1)
198
209
  end
@@ -227,6 +238,7 @@ module ActiveRecord
227
238
  )
228
239
  end
229
240
 
241
+ # Increments position (<tt>position_column</tt>) of all items in the list.
230
242
  def increment_positions_on_all_items
231
243
  acts_as_list_class.update_all(
232
244
  "#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
@@ -70,16 +70,23 @@ module ActiveRecord
70
70
  nodes
71
71
  end
72
72
 
73
+ # Returns the root node of the tree.
73
74
  def root
74
75
  node = self
75
76
  node = node.parent while node.parent
76
77
  node
77
78
  end
78
79
 
80
+ # Returns all siblings of the current node.
81
+ #
82
+ # subchild1.siblings # => [subchild2]
79
83
  def siblings
80
84
  self_and_siblings - [self]
81
85
  end
82
86
 
87
+ # Returns all siblings and a reference to the current node.
88
+ #
89
+ # subchild1.self_and_siblings # => [subchild1, subchild2]
83
90
  def self_and_siblings
84
91
  parent ? parent.children : self.class.roots
85
92
  end
@@ -352,7 +352,15 @@ module ActiveRecord
352
352
  # for post in Post.find(:all, :include => [ :author, :comments ])
353
353
  #
354
354
  # That'll add another join along the lines of: LEFT OUTER JOIN comments ON comments.post_id = posts.id. And we'll be down to 1 query.
355
- # But that shouldn't fool you to think that you can pull out huge amounts of data with no performance penalty just because you've reduced
355
+ #
356
+ # To include a deep hierarchy of associations, using a hash:
357
+ #
358
+ # for post in Post.find(:all, :include => [ :author, { :comments => { :author => :gravatar } } ])
359
+ #
360
+ # That'll grab not only all the comments but all their authors and gravatar pictures. You can mix and match
361
+ # symbols, arrays and hashes in any combination to describe the associations you want to load.
362
+ #
363
+ # All of this power shouldn't fool you into thinking that you can pull out huge amounts of data with no performance penalty just because you've reduced
356
364
  # the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it's no
357
365
  # catch-all for performance problems, but it's a great way to cut down on the number of queries in a situation as the one described above.
358
366
  #
@@ -734,6 +742,7 @@ module ActiveRecord
734
742
  deprecated_association_comparison_method(reflection.name, reflection.class_name)
735
743
  end
736
744
 
745
+ # Create the callbacks to update counter cache
737
746
  if options[:counter_cache]
738
747
  cache_column = options[:counter_cache] == true ?
739
748
  "#{self.to_s.underscore.pluralize}_count" :
@@ -871,6 +880,12 @@ module ActiveRecord
871
880
  end
872
881
 
873
882
  private
883
+ # Generate a join table name from two provided tables names.
884
+ # The order of names in join name is determined by lexical precedence.
885
+ # join_table_name("members", "clubs")
886
+ # => "clubs_members"
887
+ # join_table_name("members", "special_clubs")
888
+ # => "members_special_clubs"
874
889
  def join_table_name(first_table_name, second_table_name)
875
890
  if first_table_name < second_table_name
876
891
  join_table = "#{first_table_name}_#{second_table_name}"
@@ -880,7 +895,7 @@ module ActiveRecord
880
895
 
881
896
  table_name_prefix + join_table + table_name_suffix
882
897
  end
883
-
898
+
884
899
  def association_accessor_methods(reflection, association_proxy_class)
885
900
  define_method(reflection.name) do |*params|
886
901
  force_reload = params.first unless params.empty?
@@ -901,7 +916,7 @@ module ActiveRecord
901
916
 
902
917
  define_method("#{reflection.name}=") do |new_value|
903
918
  association = instance_variable_get("@#{reflection.name}")
904
- if association.nil?
919
+ if association.nil? || association.target != new_value
905
920
  association = association_proxy_class.new(self, reflection)
906
921
  end
907
922
 
@@ -911,10 +926,7 @@ module ActiveRecord
911
926
  instance_variable_set("@#{reflection.name}", association)
912
927
  else
913
928
  instance_variable_set("@#{reflection.name}", nil)
914
- return nil
915
929
  end
916
-
917
- association
918
930
  end
919
931
 
920
932
  define_method("set_#{reflection.name}_target") do |target|
@@ -981,18 +993,21 @@ module ActiveRecord
981
993
 
982
994
  after_callback = <<-end_eval
983
995
  association = instance_variable_get("@#{association_name}")
984
-
985
- if association.respond_to?(:loaded?)
986
- if @new_record_before_save
987
- records_to_save = association
988
- else
989
- records_to_save = association.select { |record| record.new_record? }
990
- end
996
+
997
+ records_to_save = if @new_record_before_save
998
+ association
999
+ elsif association.respond_to?(:loaded?) && association.loaded?
1000
+ association.select { |record| record.new_record? }
1001
+ else
1002
+ []
1003
+ end
1004
+
1005
+ if !records_to_save.blank?
991
1006
  records_to_save.each { |record| association.send(:insert_record, record) }
992
1007
  association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id
993
1008
  end
994
1009
  end_eval
995
-
1010
+
996
1011
  # Doesn't use after_save as that would save associations added in after_create/after_update twice
997
1012
  after_create(after_callback)
998
1013
  after_update(after_callback)
@@ -91,7 +91,11 @@ module ActiveRecord
91
91
  attributes.collect { |attr| create(attr) }
92
92
  else
93
93
  record = build(attributes)
94
- record.save unless @owner.new_record?
94
+ if @owner.new_record?
95
+ ActiveSupport::Deprecation.warn("Calling .create on a has_many association without saving its owner will not work in rails 2.0, you probably want .build instead")
96
+ else
97
+ record.save
98
+ end
95
99
  record
96
100
  end
97
101
  end
@@ -50,7 +50,7 @@ module ActiveRecord
50
50
  options[:conditions] = options[:conditions].nil? ?
51
51
  @finder_sql :
52
52
  @finder_sql + " AND (#{sanitize_sql(options[:conditions])})"
53
- options[:include] = @reflection.options[:include]
53
+ options[:include] ||= @reflection.options[:include]
54
54
 
55
55
  @reflection.klass.count(column_name, options)
56
56
  end
@@ -138,7 +138,7 @@ module ActiveRecord
138
138
  elsif @reflection.options[:counter_sql]
139
139
  @reflection.klass.count_by_sql(@counter_sql)
140
140
  else
141
- @reflection.klass.count(:conditions => @counter_sql)
141
+ @reflection.klass.count(:conditions => @counter_sql, :include => @reflection.options[:include])
142
142
  end
143
143
 
144
144
  @target = [] and loaded if count == 0
@@ -101,6 +101,16 @@ module ActiveRecord
101
101
  def sum(*args, &block)
102
102
  calculate(:sum, *args, &block)
103
103
  end
104
+
105
+ def count(*args)
106
+ column_name, options = @reflection.klass.send(:construct_count_options_from_legacy_args, *args)
107
+ if @reflection.options[:uniq]
108
+ # This is needed becase 'SELECT count(DISTINCT *)..' is not valid sql statement.
109
+ column_name = "#{@reflection.klass.table_name}.#{@reflection.klass.primary_key}" if column_name == :all
110
+ options.merge!(:distinct => true)
111
+ end
112
+ @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.count(column_name, options) }
113
+ end
104
114
 
105
115
  protected
106
116
  def method_missing(method, *args, &block)
@@ -575,7 +575,7 @@ module ActiveRecord #:nodoc:
575
575
 
576
576
  # Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized
577
577
  # after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized
578
- # object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised.
578
+ # object must be of that class on retrieval, or nil. Otherwise, +SerializationTypeMismatch+ will be raised.
579
579
  def serialize(attr_name, class_name = Object)
580
580
  serialized_attributes[attr_name.to_s] = class_name
581
581
  end
@@ -1188,6 +1188,9 @@ module ActiveRecord #:nodoc:
1188
1188
  #
1189
1189
  # It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount
1190
1190
  # is actually find_all_by_amount(amount, options).
1191
+ #
1192
+ # This also enables you to initialize a record if it is not found, such as find_or_initialize_by_amount(amount)
1193
+ # or find_or_create_by_user_and_password(user, password).
1191
1194
  def method_missing(method_id, *arguments)
1192
1195
  if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s)
1193
1196
  finder, deprecated_finder = determine_finder(match), determine_deprecated_finder(match)
@@ -1957,7 +1960,7 @@ module ActiveRecord #:nodoc:
1957
1960
  def unserialize_attribute(attr_name)
1958
1961
  unserialized_object = object_from_yaml(@attributes[attr_name])
1959
1962
 
1960
- if unserialized_object.is_a?(self.class.serialized_attributes[attr_name])
1963
+ if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) || unserialized_object.nil?
1961
1964
  @attributes[attr_name] = unserialized_object
1962
1965
  else
1963
1966
  raise SerializationTypeMismatch,
@@ -2156,7 +2159,13 @@ module ActiveRecord #:nodoc:
2156
2159
 
2157
2160
  def clone_attribute_value(reader_method, attribute_name)
2158
2161
  value = send(reader_method, attribute_name)
2159
- value.clone
2162
+
2163
+ case value
2164
+ when nil, Fixnum, true, false
2165
+ value
2166
+ else
2167
+ value.clone
2168
+ end
2160
2169
  rescue TypeError, NoMethodError
2161
2170
  value
2162
2171
  end
@@ -242,8 +242,8 @@ module ActiveRecord
242
242
  options.assert_valid_keys(CALCULATIONS_OPTIONS)
243
243
  end
244
244
 
245
- # converts a given key to the value that the database adapter returns as
246
- #
245
+ # Converts a given key to the value that the database adapter returns as
246
+ # as a usable column name.
247
247
  # users.id #=> users_id
248
248
  # sum(id) #=> sum_id
249
249
  # count(distinct users.id) #=> count_distinct_users_id
@@ -24,7 +24,7 @@ module ActiveRecord
24
24
  when Float, Fixnum, Bignum then value.to_s
25
25
  # BigDecimals need to be output in a non-normalized form and quoted.
26
26
  when BigDecimal then value.to_s('F')
27
- when Date then "'#{value.to_s}'"
27
+ when Date then "'#{value.to_s(:db)}'"
28
28
  when Time, DateTime then "'#{quoted_date(value)}'"
29
29
  else "'#{quote_string(value.to_yaml)}'"
30
30
  end
@@ -320,6 +320,7 @@ begin
320
320
  decode(data_type, 'NUMBER', data_precision,
321
321
  'FLOAT', data_precision,
322
322
  'VARCHAR2', data_length,
323
+ 'CHAR', data_length,
323
324
  null) as limit,
324
325
  decode(data_type, 'NUMBER', data_scale, null) as scale
325
326
  from all_tab_columns
@@ -68,7 +68,7 @@ module ActiveRecord
68
68
  class SQLiteColumn < Column #:nodoc:
69
69
  class << self
70
70
  def string_to_binary(value)
71
- value.gsub(/\0|\%/) do |b|
71
+ value.gsub(/\0|\%/n) do |b|
72
72
  case b
73
73
  when "\0" then "%00"
74
74
  when "%" then "%25"
@@ -77,7 +77,7 @@ module ActiveRecord
77
77
  end
78
78
 
79
79
  def binary_to_string(value)
80
- value.gsub(/%00|%25/) do |b|
80
+ value.gsub(/%00|%25/n) do |b|
81
81
  case b
82
82
  when "%00" then "\0"
83
83
  when "%25" then "%"
@@ -53,10 +53,15 @@ module ActiveRecord
53
53
  class SQLServerColumn < Column# :nodoc:
54
54
  attr_reader :identity, :is_special
55
55
 
56
- def initialize(name, default, sql_type = nil, identity = false, null = true) # TODO: check ok to remove scale_value = 0
57
- super(name, default, sql_type, null)
58
- @identity = identity
59
- @is_special = sql_type =~ /text|ntext|image/i
56
+ def initialize(info)
57
+ if info[:type] =~ /numeric|decimal/i
58
+ type = "#{info[:type]}(#{info[:numeric_precision]},#{info[:numeric_scale]})"
59
+ else
60
+ type = "#{info[:type]}(#{info[:length]})"
61
+ end
62
+ super(info[:name], info[:default_value], type, info[:is_nullable])
63
+ @identity = info[:is_identity]
64
+ @is_special = ["text", "ntext", "image"].include?(info[:type])
60
65
  # TODO: check ok to remove @scale = scale_value
61
66
  # SQL Server only supports limits on *char and float types
62
67
  @limit = nil unless @type == :float or @type == :string
@@ -252,46 +257,57 @@ module ActiveRecord
252
257
  def disconnect!
253
258
  @connection.disconnect rescue nil
254
259
  end
255
-
260
+
256
261
  def columns(table_name, name = nil)
257
262
  return [] if table_name.blank?
258
- table_name = table_name.to_s if table_name.is_a?(Symbol)
259
- table_name = table_name.split('.')[-1] unless table_name.nil?
263
+ table_name = table_name.to_s.split('.')[-1]
260
264
  table_name = table_name.gsub(/[\[\]]/, '')
261
- sql = %Q{
265
+ sql = %{
262
266
  SELECT
263
- cols.COLUMN_NAME as ColName,
264
- cols.COLUMN_DEFAULT as DefaultValue,
265
- cols.NUMERIC_SCALE as numeric_scale,
266
- cols.NUMERIC_PRECISION as numeric_precision,
267
- cols.DATA_TYPE as ColType,
268
- cols.IS_NULLABLE As IsNullable,
269
- COL_LENGTH(cols.TABLE_NAME, cols.COLUMN_NAME) as Length,
270
- COLUMNPROPERTY(OBJECT_ID(cols.TABLE_NAME), cols.COLUMN_NAME, 'IsIdentity') as IsIdentity,
271
- cols.NUMERIC_SCALE as Scale
272
- FROM INFORMATION_SCHEMA.COLUMNS cols
273
- WHERE cols.TABLE_NAME = '#{table_name}'
267
+ columns.COLUMN_NAME as name,
268
+ columns.DATA_TYPE as type,
269
+ CASE
270
+ WHEN columns.COLUMN_DEFAULT = '(null)' OR columns.COLUMN_DEFAULT = '(NULL)' THEN NULL
271
+ ELSE columns.COLUMN_DEFAULT
272
+ END default_value,
273
+ columns.NUMERIC_SCALE as numeric_scale,
274
+ columns.NUMERIC_PRECISION as numeric_precision,
275
+ COL_LENGTH(columns.TABLE_NAME, columns.COLUMN_NAME) as length,
276
+ CASE
277
+ WHEN constraint_column_usage.constraint_name IS NULL THEN NULL
278
+ ELSE 1
279
+ END is_primary_key,
280
+ CASE
281
+ WHEN columns.IS_NULLABLE = 'YES' THEN 1
282
+ ELSE NULL
283
+ end is_nullable,
284
+ CASE
285
+ WHEN COLUMNPROPERTY(OBJECT_ID(columns.TABLE_NAME), columns.COLUMN_NAME, 'IsIdentity') = 0 THEN NULL
286
+ ELSE 1
287
+ END is_identity
288
+ FROM INFORMATION_SCHEMA.COLUMNS columns
289
+ LEFT OUTER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS primary_key_constraints ON (
290
+ primary_key_constraints.table_name = columns.table_name
291
+ AND primary_key_constraints.constraint_type = 'PRIMARY KEY'
292
+ )
293
+ LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE constraint_column_usage ON (
294
+ constraint_column_usage.table_name = primary_key_constraints.table_name
295
+ AND constraint_column_usage.column_name = columns.column_name
296
+ )
297
+ WHERE columns.TABLE_NAME = '#{table_name}'
274
298
  }
275
- # Comment out if you want to have the Columns select statment logged.
276
- # Personally, I think it adds unnecessary bloat to the log.
277
- # If you do comment it out, make sure to un-comment the "result" line that follows
278
- result = log(sql, name) { @connection.select_all(sql) }
279
- #result = @connection.select_all(sql)
280
- columns = []
281
- result.each do |field|
282
- default = field[:DefaultValue].to_s.gsub!(/[()\']/,"") =~ /null/ ? nil : field[:DefaultValue]
283
- if field[:ColType] =~ /numeric|decimal/i
284
- type = "#{field[:ColType]}(#{field[:numeric_precision]},#{field[:numeric_scale]})"
285
- else
286
- type = "#{field[:ColType]}(#{field[:Length]})"
287
- end
288
- is_identity = field[:IsIdentity] == 1
289
- is_nullable = field[:IsNullable] == 'YES'
290
- columns << SQLServerColumn.new(field[:ColName], default, type, is_identity, is_nullable)
299
+
300
+ result = select(sql, name, true)
301
+ result.collect do |column_info|
302
+ # Remove brackets and outer quotes (if quoted) of default value returned by db, i.e:
303
+ # "(1)" => "1", "('1')" => "1", "((-1))" => "-1", "('(-1)')" => "(-1)"
304
+ column_info.symbolize_keys!
305
+ column_info[:default_value] = column_info[:default_value].match(/\A\(+'?(.*?)'?\)+\Z/)[1] if column_info[:default_value]
306
+ SQLServerColumn.new(column_info)
291
307
  end
292
- columns
293
308
  end
294
309
 
310
+
295
311
  def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
296
312
  execute(sql, name)
297
313
  id_value || select_one("SELECT @@IDENTITY AS Ident")["Ident"]
@@ -495,8 +511,8 @@ module ActiveRecord
495
511
  end
496
512
 
497
513
  private
498
- def select(sql, name = nil)
499
- repair_special_columns(sql)
514
+ def select(sql, name = nil, ignore_special_columns = false)
515
+ repair_special_columns(sql) unless ignore_special_columns
500
516
 
501
517
  result = []
502
518
  execute(sql) do |handle|