From d31af44012a6ba3ac5dbec45417ae9bfb5454d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 20 Apr 2011 21:54:19 +0200 Subject: [PATCH 01/21] Fix tests on 1.8 by explicitly checking for strings (which also improves performance). --- actionpack/lib/action_dispatch/http/response.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 78ecf177be..1f4f3ac0da 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -118,7 +118,15 @@ module ActionDispatch # :nodoc: def body=(body) @blank = true if body == EMPTY - @body = body.respond_to?(:each) ? body : [body] + + # Explicitly check for strings. This is *wrong* theoretically + # but if we don't check this, the performance on string bodies + # is bad on Ruby 1.8 (because strings responds to each then). + @body = if body.respond_to?(:to_str) || !body.respond_to?(:each) + [body] + else + body + end end def body_parts From 84f1b83df84d36b75cc7b6d1c84ffd84c6c07260 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 21 Apr 2011 11:03:56 -0500 Subject: [PATCH 02/21] Only include SprocketsHelper into assets context --- actionpack/lib/sprockets/railtie.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb index 2f7f95c44d..ccec65ba95 100644 --- a/actionpack/lib/sprockets/railtie.rb +++ b/actionpack/lib/sprockets/railtie.rb @@ -33,9 +33,10 @@ module Sprockets app.assets = asset_environment(app) - # FIXME: Temp hack for extending Sprockets::Context so ActiveSupport.on_load(:action_view) do - ::Sprockets::Context.send :include, ::ActionView::Helpers::SprocketsHelper + app.assets.context.instance_eval do + include ::ActionView::Helpers::SprocketsHelper + end end app.routes.append do @@ -59,4 +60,4 @@ module Sprockets env end end -end \ No newline at end of file +end From 724a7866774c7847cc79b699ccf7da9fee72b154 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 21 Apr 2011 22:47:13 -0500 Subject: [PATCH 03/21] stop using distinct on for the unique id queries. [#6450 state:resolved] --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 2 +- activerecord/lib/active_record/relation/finder_methods.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index acc3e9c5e3..66ca831d6c 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -935,7 +935,7 @@ module ActiveRecord # Return a DISTINCT ON() clause that's distinct on the columns we want but includes # all the required columns for the ORDER BY to work properly. - sql = "DISTINCT ON (#{columns}) #{columns}, " + sql = "DISTINCT #{columns}, " sql << order_columns * ', ' end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index aae257a0e7..a3d4b7f45a 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -246,6 +246,8 @@ module ActiveRecord orders = relation.order_values values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders) + relation = relation.dup + ids_array = relation.select(values).collect {|row| row[primary_key]} ids_array.empty? ? raise(ThrowResult) : table[primary_key].in(ids_array) end From ed2820d6ecef7533970952437b974c7fa10192e1 Mon Sep 17 00:00:00 2001 From: Ken Collins Date: Fri, 22 Apr 2011 20:33:43 +0800 Subject: [PATCH 04/21] Move #exec_insert to abstract adapter's database statements. --- .../connection_adapters/abstract/database_statements.rb | 7 +++++++ .../lib/active_record/connection_adapters/mysql_adapter.rb | 4 ---- .../connection_adapters/postgresql_adapter.rb | 4 ---- .../active_record/connection_adapters/sqlite_adapter.rb | 4 ---- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 6d9b5c7b32..5ff81aa023 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -55,6 +55,13 @@ module ActiveRecord def exec_query(sql, name = 'SQL', binds = []) end + # Executes insert +sql+ statement in the context of this connection using + # +binds+ as the bind substitutes. +name+ is the logged along with + # the executed +sql+ statement. + def exec_insert(sql, name, binds) + exec_query(sql, name, binds) + end + # Returns the last auto-generated ID from the affected table. # # +id_value+ will be returned unless the value is nil, in diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index c2e75acb9a..0f45565dc9 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -427,10 +427,6 @@ module ActiveRecord end end - def exec_insert(sql, name, binds) - exec_query(sql, name, binds) - end - def last_inserted_id(result) @connection.insert_id end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 66ca831d6c..5adb235835 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -552,10 +552,6 @@ module ActiveRecord end end - def exec_insert(sql, name, binds) - exec_query(sql, name, binds) - end - def sql_for_insert(sql, pk, id_value, sequence_name, binds) unless pk _, table = extract_schema_and_table(sql.split(" ", 4)[2]) diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 9e7f874f4b..8bff20fa70 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -173,10 +173,6 @@ module ActiveRecord end end - def exec_insert(sql, name, binds) - exec_query(sql, name, binds) - end - def last_inserted_id(result) @connection.last_insert_row_id end From dab96a267eeccd7380ad99fa19cefdfd3cd5ad2b Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Fri, 22 Apr 2011 10:49:55 -0500 Subject: [PATCH 05/21] Add shorthand for js and css compressors --- actionpack/lib/sprockets/railtie.rb | 37 +++++++++++++++++++ .../lib/rails/application/configuration.rb | 3 ++ 2 files changed, 40 insertions(+) diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb index ccec65ba95..9c10decd60 100644 --- a/actionpack/lib/sprockets/railtie.rb +++ b/actionpack/lib/sprockets/railtie.rb @@ -57,7 +57,44 @@ module Sprockets env.static_root = File.join(app.root.join("public"), assets.prefix) env.paths.concat assets.paths env.logger = Rails.logger + env.js_compressor = expand_js_compressor(assets.js_compressor) + env.css_compressor = expand_css_compressor(assets.css_compressor) env end + + def expand_js_compressor(sym) + case sym + when :closure + require 'closure-compiler' + Closure::Compiler.new + when :uglifier + require 'uglifier' + Uglifier.new + when :yui + require 'yui/compressor' + YUI::JavaScriptCompressor.new + else + sym + end + end + + def expand_css_compressor(sym) + case sym + when :scss + require 'sass' + compressor = Object.new + def compressor.compress(source) + Sass::Engine.new(source, + :syntax => :scss, :style => :compressed + ).render + end + compressor + when :yui + require 'yui/compressor' + YUI::JavaScriptCompressor.new(:munge => true) + else + sym + end + end end end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index bd8c314da6..f818313955 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -35,6 +35,9 @@ module Rails @assets.paths = [] @assets.precompile = [ /\w+\.(?!js|css)$/, "application.js", "application.css" ] @assets.prefix = "/assets" + + @assets.js_compressor = nil + @assets.css_compressor = nil end def compiled_asset_path From 59ce0f695bcbcb903effa490e7aa56fc86e22172 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 22 Apr 2011 18:00:19 +0200 Subject: [PATCH 06/21] Turn on JS/CSS compression by default --- railties/lib/rails/generators/rails/app/templates/Gemfile | 1 + .../rails/app/templates/config/environments/production.rb.tt | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 0cee7deb72..141d9fd15c 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -8,6 +8,7 @@ source 'http://rubygems.org' <%= "gem 'json'\n" if RUBY_VERSION < "1.9.2" -%> gem 'sass', '~> 3.1.0.alpha' gem 'coffee-script' +gem 'uglifier' # Use unicorn as the web server # gem 'unicorn' diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 80951cf73a..b00f10c545 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -15,6 +15,10 @@ # (comment out if your front-end server doesn't support this) config.action_dispatch.x_sendfile_header = "X-Sendfile" # Use 'X-Accel-Redirect' for nginx + # Compress both stylesheets and JavaScripts + config.assets.js_compressor = :uglifier + config.assets.css_compressor = :scss + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true From bc50c1cb02c317ef92e4aa0336d396dcad5bc578 Mon Sep 17 00:00:00 2001 From: Ken Collins Date: Fri, 22 Apr 2011 19:55:42 +0800 Subject: [PATCH 07/21] The #substitute_at gets an ActiveRecord::ConnectionAdapters::Column in #insert to match replacement in #exec_query. --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 359f9d8a66..45a7000cce 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -56,7 +56,7 @@ module ActiveRecord end substitutes.each_with_index do |tuple, i| - tuple[1] = conn.substitute_at(tuple.first, i) + tuple[1] = conn.substitute_at(binds[i][0], i) end if values.empty? # empty insert From fe4932b531ec9b593085c4bb115c13f0852c3fbb Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 22 Apr 2011 11:27:14 -0500 Subject: [PATCH 08/21] bumping the pg requirements --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index c720b09a2c..fa8b67a743 100644 --- a/Gemfile +++ b/Gemfile @@ -52,7 +52,7 @@ platforms :ruby do gem "sqlite3", "~> 1.3.3" group :db do - gem "pg", ">= 0.9.0" + gem "pg", ">= 0.11.0" gem "mysql", ">= 2.8.1" gem "mysql2", :git => "git://github.com/brianmario/mysql2.git" end From 96acdd3ec48594635314e768bf18805af6a40dde Mon Sep 17 00:00:00 2001 From: Pavel Forkert Date: Sun, 27 Feb 2011 23:40:10 +0200 Subject: [PATCH 09/21] Added test case and fix for proper eager loading associations --- activerecord/test/cases/associations/eager_test.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 40c82f2fb8..9bc7910fc6 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -170,6 +170,16 @@ class EagerAssociationTest < ActiveRecord::TestCase assert_equal [comment], category.posts[0].comments end end + + def test_associations_loaded_for_all_records + post = Post.create!(:title => 'foo', :body => "I like cars!") + comment = SpecialComment.create!(:body => 'Come on!', :post => post) + first_category = Category.create! :name => 'First!', :posts => [post] + second_category = Category.create! :name => 'Second!', :posts => [post] + + categories = Category.where(:id => [first_category.id, second_category.id]).includes(:posts => :special_comments) + assert_equal categories.map { |category| category.posts.first.special_comments.loaded? }, [true, true] + end def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once author_id = authors(:david).id From a37722182fd96190f2317ffd0450c49ed6d406f0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 22 Apr 2011 12:21:59 -0500 Subject: [PATCH 10/21] removing incorrect comment and string concatenation --- .../active_record/connection_adapters/postgresql_adapter.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 5adb235835..203ecd2f03 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -929,10 +929,7 @@ module ActiveRecord order_columns.delete_if { |c| c.blank? } order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" } - # Return a DISTINCT ON() clause that's distinct on the columns we want but includes - # all the required columns for the ORDER BY to work properly. - sql = "DISTINCT #{columns}, " - sql << order_columns * ', ' + "DISTINCT #{columns}, #{order_columns * ', '}" end protected From 89f315bfb287f5428e78195e7c93c85c0892ab64 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 22 Apr 2011 19:37:52 +0200 Subject: [PATCH 11/21] We cant use assert_block because its buggy in MiniTest and wont actually show you the failure message you provide -- instead you just always get a "Expected block to return true" --- actionpack/lib/action_dispatch/testing/assertions/response.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index 8a04cfa886..e209978fb7 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -42,7 +42,7 @@ module ActionDispatch elsif type.is_a?(Symbol) && @response.response_code == Rack::Utils::SYMBOL_TO_STATUS_CODE[type] assert_block("") { true } # to count the assertion else - assert_block(build_message(message, "Expected response to be a , but was ", type, @response.response_code)) { false } + assert(false, build_message(message, "Expected response to be a , but was ", type, @response.response_code)) end end From bb6b17216d05cb3c29279b13423a424fa375aaf4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 22 Apr 2011 20:03:12 +0200 Subject: [PATCH 12/21] Need this for testing --- Gemfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile b/Gemfile index fa8b67a743..5c65ebd2e6 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,7 @@ gem "rack-test", :git => "git://github.com/brynary/rack-test.git" gem "sprockets", :git => "git://github.com/sstephenson/sprockets.git" gem "coffee-script" gem "sass", ">= 3.0" +gem "uglifier" gem "rake", ">= 0.8.7" gem "mocha", ">= 0.9.8" From eb599295db00b9a614e01707db2371d8819947ed Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Sat, 23 Apr 2011 02:17:08 +0800 Subject: [PATCH 13/21] Images path fixed in test. --- railties/test/generators/app_generator_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 3ef06c7f25..58febfd9c7 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -23,7 +23,7 @@ DEFAULT_APP_FILES = %w( lib lib/tasks log - public/images + app/assets/images script/rails test/fixtures test/functional From a8870d140ececc6327533d08b112cece03c41499 Mon Sep 17 00:00:00 2001 From: Schneems Date: Sat, 23 Apr 2011 02:23:12 +0800 Subject: [PATCH 14/21] show http method in routing error message --- actionpack/lib/action_dispatch/middleware/show_exceptions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index dbe3206808..b1adf3d2d1 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -50,7 +50,7 @@ module ActionDispatch # Only this middleware cares about RoutingError. So, let's just raise # it here. if headers['X-Cascade'] == 'pass' - raise ActionController::RoutingError, "No route matches #{env['PATH_INFO'].inspect}" + raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}" end rescue Exception => exception raise exception if env['action_dispatch.show_exceptions'] == false From d42e43b3e50efdcd75112db2bb386d62cda1eb6a Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Sat, 23 Apr 2011 02:40:17 +0800 Subject: [PATCH 15/21] Fixed images path in plugin_new_generator --- .../rails/generators/rails/plugin_new/plugin_new_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 81563f81d3..12921f47b6 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -93,7 +93,7 @@ task :default => :test remove_file "doc" remove_file "Gemfile" remove_file "lib/tasks" - remove_file "public/images/rails.png" + remove_file "app/assets/images/rails.png" remove_file "public/index.html" remove_file "public/robots.txt" remove_file "README" From 3eae734012fadd641a4ec95715480b962861294c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 22 Apr 2011 14:37:53 -0500 Subject: [PATCH 16/21] set the backtrace to prevent AR exceptions from lying to us --- .../lib/active_record/connection_adapters/abstract_adapter.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index d24cce0a3c..468a2b106b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -223,7 +223,9 @@ module ActiveRecord rescue Exception => e message = "#{e.class.name}: #{e.message}: #{sql}" @logger.debug message if @logger - raise translate_exception(e, message) + exception = translate_exception(e, message) + exception.set_backtrace e.backtrace + raise exception end def translate_exception(e, message) From 3d19b356d7ccb37b23afcab0b0b698bfd3d668d7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 22 Apr 2011 15:31:03 -0500 Subject: [PATCH 17/21] fetch result row arrays from pg in C and return early if there are no money or binary columns. :heart: --- .../connection_adapters/postgresql_adapter.rb | 63 ++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 203ecd2f03..8763074121 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -1,6 +1,9 @@ require 'active_record/connection_adapters/abstract_adapter' require 'active_support/core_ext/kernel/requires' require 'active_support/core_ext/object/blank' + +# Make sure we're using pg high enough for PGResult#values +gem 'pg', '~> 0.11' require 'pg' module ActiveRecord @@ -460,42 +463,44 @@ module ActiveRecord # create a 2D array representing the result set def result_as_array(res) #:nodoc: # check if we have any binary column and if they need escaping - unescape_col = [] - res.nfields.times do |j| - unescape_col << res.ftype(j) + ftypes = Array.new(res.nfields) do |i| + [i, res.ftype(i)] end - ary = [] - res.ntuples.times do |i| - ary << [] - res.nfields.times do |j| - data = res.getvalue(i,j) - case unescape_col[j] + rows = res.values + return rows unless ftypes.any? { |_, x| + x == BYTEA_COLUMN_TYPE_OID || x == MONEY_COLUMN_TYPE_OID + } - # unescape string passed BYTEA field (OID == 17) - when BYTEA_COLUMN_TYPE_OID - data = unescape_bytea(data) if String === data + typehash = ftypes.group_by { |_, type| type } + binaries = (typehash[BYTEA_COLUMN_TYPE_OID] || []).map { |x| x.first } + monies = (typehash[MONEY_COLUMN_TYPE_OID] || []).map { |x| x.first } - # If this is a money type column and there are any currency symbols, - # then strip them off. Indeed it would be prettier to do this in - # PostgreSQLColumn.string_to_decimal but would break form input - # fields that call value_before_type_cast. - when MONEY_COLUMN_TYPE_OID - # Because money output is formatted according to the locale, there are two - # cases to consider (note the decimal separators): - # (1) $12,345,678.12 - # (2) $12.345.678,12 - case data - when /^-?\D+[\d,]+\.\d{2}$/ # (1) - data.gsub!(/[^-\d.]/, '') - when /^-?\D+[\d.]+,\d{2}$/ # (2) - data.gsub!(/[^-\d,]/, '').sub!(/,/, '.') - end + rows.each do |row| + # unescape string passed BYTEA field (OID == 17) + binaries.each do |index| + data = row[index] + row[index] = unescape_bytea(data) + end + + # If this is a money type column and there are any currency symbols, + # then strip them off. Indeed it would be prettier to do this in + # PostgreSQLColumn.string_to_decimal but would break form input + # fields that call value_before_type_cast. + monies.each do |index| + data = row[index] + # Because money output is formatted according to the locale, there are two + # cases to consider (note the decimal separators): + # (1) $12,345,678.12 + # (2) $12.345.678,12 + case data + when /^-?\D+[\d,]+\.\d{2}$/ # (1) + data.gsub!(/[^-\d.]/, '') + when /^-?\D+[\d.]+,\d{2}$/ # (2) + data.gsub!(/[^-\d,]/, '').sub!(/,/, '.') end - ary[i] << data end end - return ary end From 5bed6494d49506223dc3b6652858c21487776a02 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 22 Apr 2011 15:35:54 -0500 Subject: [PATCH 18/21] split indexes and column types on money / binary iteration --- .../connection_adapters/postgresql_adapter.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 8763074121..fbfccd4ec1 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -473,21 +473,20 @@ module ActiveRecord } typehash = ftypes.group_by { |_, type| type } - binaries = (typehash[BYTEA_COLUMN_TYPE_OID] || []).map { |x| x.first } - monies = (typehash[MONEY_COLUMN_TYPE_OID] || []).map { |x| x.first } + binaries = typehash[BYTEA_COLUMN_TYPE_OID] || [] + monies = typehash[MONEY_COLUMN_TYPE_OID] || [] rows.each do |row| # unescape string passed BYTEA field (OID == 17) - binaries.each do |index| - data = row[index] - row[index] = unescape_bytea(data) + binaries.each do |index, _| + row[index] = unescape_bytea(row[index]) end # If this is a money type column and there are any currency symbols, # then strip them off. Indeed it would be prettier to do this in # PostgreSQLColumn.string_to_decimal but would break form input # fields that call value_before_type_cast. - monies.each do |index| + monies.each do |index, _| data = row[index] # Because money output is formatted according to the locale, there are two # cases to consider (note the decimal separators): From 013d9016ca2a12f4429b2f0b058283fb75b73cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 22 Apr 2011 23:25:48 +0200 Subject: [PATCH 19/21] Use .erb in the test. --- railties/test/railties/shared_tests.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb index b2b18938ae..e975950b85 100644 --- a/railties/test/railties/shared_tests.rb +++ b/railties/test/railties/shared_tests.rb @@ -11,7 +11,7 @@ module RailtiesTest end def test_serving_sprockets_assets - @plugin.write "app/assets/javascripts/engine.js.coffee", "square = (x) -> x * x" + @plugin.write "app/assets/javascripts/engine.js.erb", "<%= :alert %>();" boot_rails require 'rack/test' @@ -19,7 +19,7 @@ module RailtiesTest extend Rack::Test::Methods get "/assets/engine.js" - assert_match "square = function(x) {", last_response.body + assert_match "alert();", last_response.body end def test_copying_migrations From 3f7a434d2e11e14a5ec1422b6096969c5a62a2bf Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 22 Apr 2011 23:38:03 +0200 Subject: [PATCH 20/21] The example uses erb --- .../generators/rails/app/templates/db/{seeds.rb => seeds.rb.tt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename railties/lib/rails/generators/rails/app/templates/db/{seeds.rb => seeds.rb.tt} (100%) diff --git a/railties/lib/rails/generators/rails/app/templates/db/seeds.rb b/railties/lib/rails/generators/rails/app/templates/db/seeds.rb.tt similarity index 100% rename from railties/lib/rails/generators/rails/app/templates/db/seeds.rb rename to railties/lib/rails/generators/rails/app/templates/db/seeds.rb.tt From f7538808d466b756df15ac3f27ca08370f7a189c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 22 Apr 2011 23:55:53 +0200 Subject: [PATCH 21/21] File watcher won't make the cut for 3.1. Maybe on 3.2. --- Gemfile | 1 - activesupport/lib/active_support.rb | 1 - activesupport/test/file_watcher_test.rb | 233 ------------------------ 3 files changed, 235 deletions(-) delete mode 100644 activesupport/test/file_watcher_test.rb diff --git a/Gemfile b/Gemfile index 5c65ebd2e6..c262b97819 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,6 @@ end # AS gem "memcache-client", ">= 1.8.5" -gem "fssm", "~> 0.2.5" platforms :mri_18 do gem "system_timer" diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 6b662ac660..6b87774978 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -42,7 +42,6 @@ module ActiveSupport autoload :DescendantsTracker autoload :FileUpdateChecker - autoload :FileWatcher autoload :LogSubscriber autoload :Notifications diff --git a/activesupport/test/file_watcher_test.rb b/activesupport/test/file_watcher_test.rb deleted file mode 100644 index 7b4d4be24f..0000000000 --- a/activesupport/test/file_watcher_test.rb +++ /dev/null @@ -1,233 +0,0 @@ -require 'abstract_unit' -require 'fssm' -require "fileutils" -require "timeout" - - -class FileWatcherTest < ActiveSupport::TestCase - class DumbBackend < ActiveSupport::FileWatcher::Backend - end - - def setup - @watcher = ActiveSupport::FileWatcher.new - - # In real life, the backend would take the path and use it to observe the file - # system. In our case, we will manually trigger the events for unit testing, - # so we can pass any path. - @backend = DumbBackend.new("RAILS_WOOT", @watcher) - - @payload = [] - @watcher.watch %r{^app/assets/.*\.scss$} do |pay| - pay.each do |status, files| - files.sort! - end - @payload << pay - end - end - - def test_use_triple_equals - fw = ActiveSupport::FileWatcher.new - called = [] - fw.watch("some_arbitrary_file.rb") do |file| - called << "omg" - end - fw.trigger(%w{ some_arbitrary_file.rb }) - assert_equal ['omg'], called - end - - def test_one_change - @backend.trigger("app/assets/main.scss" => :changed) - assert_equal({:changed => ["app/assets/main.scss"]}, @payload.first) - end - - def test_multiple_changes - @backend.trigger("app/assets/main.scss" => :changed, "app/assets/javascripts/foo.coffee" => :changed) - assert_equal([{:changed => ["app/assets/main.scss"]}], @payload) - end - - def test_multiple_changes_match - @backend.trigger("app/assets/main.scss" => :changed, "app/assets/print.scss" => :changed, "app/assets/javascripts/foo.coffee" => :changed) - assert_equal([{:changed => ["app/assets/main.scss", "app/assets/print.scss"]}], @payload) - end - - def test_multiple_state_changes - @backend.trigger("app/assets/main.scss" => :created, "app/assets/print.scss" => :changed) - assert_equal([{:changed => ["app/assets/print.scss"], :created => ["app/assets/main.scss"]}], @payload) - end - - def test_more_blocks - payload = [] - @watcher.watch %r{^config/routes\.rb$} do |pay| - payload << pay - end - - @backend.trigger "config/routes.rb" => :changed - assert_equal [:changed => ["config/routes.rb"]], payload - assert_equal [], @payload - end - - def test_overlapping_watchers - payload = [] - @watcher.watch %r{^app/assets/main\.scss$} do |pay| - payload << pay - end - - @backend.trigger "app/assets/print.scss" => :changed, "app/assets/main.scss" => :changed - assert_equal [:changed => ["app/assets/main.scss"]], payload - assert_equal [:changed => ["app/assets/main.scss", "app/assets/print.scss"]], @payload - end -end - -module FSSM::Backends - class Polling - def initialize_with_low_latency(options={}) - initialize_without_low_latency(options.merge(:latency => 0.1)) - end - alias_method_chain :initialize, :low_latency - end -end - -class FSSMFileWatcherTest < ActiveSupport::TestCase - class FSSMBackend < ActiveSupport::FileWatcher::Backend - def initialize(path, watcher) - super - - monitor = FSSM::Monitor.new - monitor.path(path, '**/*') do |p| - p.update { |base, relative| trigger relative => :changed } - p.delete { |base, relative| trigger relative => :deleted } - p.create { |base, relative| trigger relative => :created } - end - - @thread = Thread.new do - monitor.run - end - end - - def stop - @thread.kill - end - end - - def setup - Thread.abort_on_exception = true - - @payload = [] - @triggered = false - - @watcher = ActiveSupport::FileWatcher.new - - @path = path = File.expand_path("../tmp", __FILE__) - FileUtils.rm_rf path - - create "app/assets/main.scss", true - create "app/assets/javascripts/foo.coffee", true - create "app/assets/print.scss", true - create "app/assets/videos.scss", true - - @backend = FSSMBackend.new(path, @watcher) - - @watcher.watch %r{^app/assets/.*\.scss$} do |pay| - pay.each do |status, files| - files.sort! - end - @payload << pay - trigger - end - end - - def teardown - @backend.stop - Thread.abort_on_exception = false - end - - def create(path, past = false) - wait(past) do - path = File.join(@path, path) - FileUtils.mkdir_p(File.dirname(path)) - - FileUtils.touch(path) - File.utime(Time.now - 100, Time.now - 100, path) if past - end - end - - def change(path) - wait do - FileUtils.touch(File.join(@path, path)) - end - end - - def delete(path) - wait do - FileUtils.rm(File.join(@path, path)) - end - end - - def wait(past = false) - yield - return if past - - begin - Timeout.timeout(1) do - sleep 0.05 until @triggered - end - rescue Timeout::Error - end - - @triggered = false - end - - def trigger - @triggered = true - end - - def test_one_change - change "app/assets/main.scss" - assert_equal({:changed => ["app/assets/main.scss"]}, @payload.first) - end - - def test_multiple_changes - change "app/assets/main.scss" - change "app/assets/javascripts/foo.coffee" - assert_equal([{:changed => ["app/assets/main.scss"]}], @payload) - end - - def test_multiple_changes_match - change "app/assets/main.scss" - change "app/assets/print.scss" - change "app/assets/javascripts/foo.coffee" - assert_equal([{:changed => ["app/assets/main.scss"]}, {:changed => ["app/assets/print.scss"]}], @payload) - end - - def test_multiple_state_changes - create "app/assets/new.scss" - change "app/assets/print.scss" - delete "app/assets/videos.scss" - assert_equal([{:created => ["app/assets/new.scss"]}, {:changed => ["app/assets/print.scss"]}, {:deleted => ["app/assets/videos.scss"]}], @payload) - end - - def test_more_blocks - payload = [] - @watcher.watch %r{^config/routes\.rb$} do |pay| - payload << pay - trigger - end - - create "config/routes.rb" - assert_equal [{:created => ["config/routes.rb"]}], payload - assert_equal [], @payload - end - - def test_overlapping_watchers - payload = [] - @watcher.watch %r{^app/assets/main\.scss$} do |pay| - payload << pay - trigger - end - - change "app/assets/main.scss" - change "app/assets/print.scss" - assert_equal [{:changed => ["app/assets/main.scss"]}], payload - assert_equal [{:changed => ["app/assets/main.scss"]}, {:changed => ["app/assets/print.scss"]}], @payload - end -end