From a982443ae5bd12535405dbdb40f27df2d612256e Mon Sep 17 00:00:00 2001 From: Daniel Schierbeck Date: Sat, 9 Jul 2011 14:24:28 +0200 Subject: Make #extract_schema_and_table an instance method in Utils Also, move the utils test into its own test case. --- .../connection_adapters/postgresql_adapter.rb | 4 +++- .../test/cases/adapters/postgresql/schema_test.rb | 15 --------------- .../test/cases/adapters/postgresql/utils_test.rb | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 activerecord/test/cases/adapters/postgresql/utils_test.rb diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index a84f73c73f..df753d087c 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -948,6 +948,8 @@ module ActiveRecord end module Utils + extend self + # Returns an array of [schema_name, table_name] extracted from +name+. # +schema_name+ is nil if not specified in +name+. # +schema_name+ and +table_name+ exclude surrounding quotes (regardless of whether provided in +name+) @@ -958,7 +960,7 @@ module ActiveRecord # * schema_name.table_name # * schema_name."table.name" # * "schema.name"."table name" - def self.extract_schema_and_table(name) + def extract_schema_and_table(name) table, schema = name.scan(/[^".\s]+|"[^"]*"/)[0..1].collect{|m| m.gsub(/(^"|"$)/,'') }.reverse [schema, table] end diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index 3a7f1badf0..4c6d865d59 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -219,21 +219,6 @@ class SchemaTest < ActiveRecord::TestCase end end - def test_extract_schema_and_table - { - %(table_name) => [nil,'table_name'], - %("table.name") => [nil,'table.name'], - %(schema.table_name) => %w{schema table_name}, - %("schema".table_name) => %w{schema table_name}, - %(schema."table_name") => %w{schema table_name}, - %("schema"."table_name") => %w{schema table_name}, - %("even spaces".table) => ['even spaces','table'], - %(schema."table.name") => ['schema', 'table.name'] - }.each do |given, expect| - assert_equal expect, ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::Utils.extract_schema_and_table(given) - end - end - def test_current_schema { %('$user',public) => 'public', diff --git a/activerecord/test/cases/adapters/postgresql/utils_test.rb b/activerecord/test/cases/adapters/postgresql/utils_test.rb new file mode 100644 index 0000000000..5f08f79171 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/utils_test.rb @@ -0,0 +1,18 @@ +class PostgreSQLUtilsTest < ActiveSupport::TestCase + include ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::Utils + + def test_extract_schema_and_table + { + %(table_name) => [nil,'table_name'], + %("table.name") => [nil,'table.name'], + %(schema.table_name) => %w{schema table_name}, + %("schema".table_name) => %w{schema table_name}, + %(schema."table_name") => %w{schema table_name}, + %("schema"."table_name") => %w{schema table_name}, + %("even spaces".table) => ['even spaces','table'], + %(schema."table.name") => ['schema', 'table.name'] + }.each do |given, expect| + assert_equal expect, extract_schema_and_table(given) + end + end +end -- cgit v1.2.3 From 3c7b29da1b1fff83fb72a19426193332eaf63577 Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Mon, 1 Aug 2011 20:31:19 +0530 Subject: Test added to check mass_assignment_sanitizer is not present if --skip-active-record provided. --- railties/test/generators/app_generator_test.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index fb7ebaa1fa..0db9b99234 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -314,6 +314,15 @@ class AppGeneratorTest < Rails::Generators::TestCase end end + def test_generated_environments_file_for_sanitizer + run_generator [destination_root, "--skip-active-record"] + ["config/environments/development.rb", "config/environments/test.rb"].each do |env_file| + assert_file env_file do |file| + assert_no_match(/config.active_record.mass_assignment_sanitizer = :strict/, file) + end + end + end + protected def action(*args, &block) -- cgit v1.2.3 From d48dd18bb2a3d0c46708a9ee217909783b997cb2 Mon Sep 17 00:00:00 2001 From: Andrew Kaspick Date: Wed, 10 Aug 2011 12:55:29 -0500 Subject: fix exists? to return false if passed nil (which may come from a missing URL param) --- activerecord/lib/active_record/relation/finder_methods.rb | 4 +++- activerecord/test/cases/finder_test.rb | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 73368aed18..d0d138d2a6 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -180,7 +180,9 @@ module ActiveRecord # Person.exists?(:name => "David") # Person.exists?(['name LIKE ?', "%#{query}%"]) # Person.exists? - def exists?(id = nil) + def exists?(id = false) + return false if id.nil? + id = id.id if ActiveRecord::Base === id join_dependency = construct_join_dependency_for_association_find diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 5dc5f99582..4c6f8b9699 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -48,6 +48,15 @@ class FinderTest < ActiveRecord::TestCase assert Topic.exists? end + # exists? should handle nil for id's that come from URLs and always return false + # (example: Topic.exists?(params[:id])) where params[:id] is nil + def test_exists_with_nil_arg + assert !Topic.exists?(nil) + assert Topic.exists? + assert !Topic.first.replies.exists?(nil) + assert Topic.first.replies.exists? + end + def test_does_not_exist_with_empty_table_and_no_args_given Topic.delete_all assert !Topic.exists? -- cgit v1.2.3 From 895d64531d25a76c1de2d4fec9aba68c0ee8c104 Mon Sep 17 00:00:00 2001 From: Waynn Lue Date: Thu, 11 Aug 2011 00:30:45 -0700 Subject: fix destructive stringify_keys for label_tag --- actionpack/lib/action_view/helpers/form_tag_helper.rb | 4 ++-- actionpack/test/template/form_tag_helper_test.rb | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 2bbe0c175f..92349508e6 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -179,9 +179,9 @@ module ActionView def label_tag(name = nil, content_or_options = nil, options = nil, &block) options = content_or_options if block_given? && content_or_options.is_a?(Hash) options ||= {} - options.stringify_keys! + options = options.stringify_keys options["for"] = sanitize_to_id(name) unless name.blank? || options.has_key?("for") - content_tag :label, content_or_options || name.to_s.humanize, options, &block + content_tag :label, content_or_options.is_a?(Hash) ? options : (content_or_options || name.to_s.humanize), options, &block end # Creates a hidden form input field used to transmit data that would be lost due to HTTP's statelessness or diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index ad31812273..c8e47e4f71 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -530,6 +530,12 @@ class FormTagHelperTest < ActionView::TestCase assert_equal options, { :option => "random_option" } end + def test_image_label_tag_options_symbolize_keys_side_effects + options = { :option => "random_option" } + actual = label_tag "submit source", "title", options + assert_equal options, { :option => "random_option" } + end + def protect_against_forgery? false end -- cgit v1.2.3 From 60d358b23348a14447d176fa51624ad5434eb575 Mon Sep 17 00:00:00 2001 From: Andrew Kaspick Date: Thu, 11 Aug 2011 17:49:31 -0500 Subject: fix assert_select_email to work on non-multipart emails as well as converting the Mail::Body to a string to prevent errors. --- .../action_dispatch/testing/assertions/selector.rb | 4 ++-- actionpack/test/controller/assert_select_test.rb | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index 5fa91d1a76..b4555f4f59 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -415,9 +415,9 @@ module ActionDispatch assert !deliveries.empty?, "No e-mail in delivery list" for delivery in deliveries - for part in delivery.parts + for part in (delivery.parts.empty? ? [delivery] : delivery.parts) if part["Content-Type"].to_s =~ /^text\/html\W/ - root = HTML::Document.new(part.body).root + root = HTML::Document.new(part.body.to_s).root assert_select root, ":root", &block end end diff --git a/actionpack/test/controller/assert_select_test.rb b/actionpack/test/controller/assert_select_test.rb index 878484eb57..5eef8a32d7 100644 --- a/actionpack/test/controller/assert_select_test.rb +++ b/actionpack/test/controller/assert_select_test.rb @@ -20,6 +20,15 @@ class AssertSelectTest < ActionController::TestCase end end + class AssertMultipartSelectMailer < ActionMailer::Base + def test(options) + mail :subject => "Test e-mail", :from => "test@test.host", :to => "test " do |format| + format.text { render :text => options[:text] } + format.html { render :text => options[:html] } + end + end + end + class AssertSelectController < ActionController::Base def response_with=(content) @content = content @@ -313,6 +322,16 @@ EOF end end + def test_assert_select_email_multipart + AssertMultipartSelectMailer.test(:html => "

foo

bar

", :text => 'foo bar').deliver + assert_select_email do + assert_select "div:root" do + assert_select "p:first-child", "foo" + assert_select "p:last-child", "bar" + end + end + end + protected def render_html(html) @controller.response_with = html -- cgit v1.2.3 From 4bb7abcb7715c06ff816243c61d75b14afc117e0 Mon Sep 17 00:00:00 2001 From: "Jonathon M. Abbott" Date: Wed, 27 Jul 2011 17:35:35 +1000 Subject: Use mysql_creation_options inside rescue block Commit ecd37084b28a05f05251 did not take into account the use of creation_options inside the access denied exception handler. --- activerecord/lib/active_record/railties/databases.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index ec00f7faad..13c41350fb 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -94,7 +94,7 @@ db_namespace = namespace :db do "IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;" ActiveRecord::Base.establish_connection(config.merge( 'database' => nil, 'username' => 'root', 'password' => root_password)) - ActiveRecord::Base.connection.create_database(config['database'], creation_options) + ActiveRecord::Base.connection.create_database(config['database'], mysql_creation_options(config)) ActiveRecord::Base.connection.execute grant_statement ActiveRecord::Base.establish_connection(config) else -- cgit v1.2.3 From 8620bf90c5e486e1ec44b9aabb63f8c848668ed2 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev Date: Wed, 17 Aug 2011 17:26:00 +0300 Subject: Implemented strict validation concept In order to deliver debug information to dev team instead of display error message to end user Implemented strict validation concept that suppose to define validation that always raise exception when fails --- activemodel/lib/active_model/errors.rb | 8 +++++- .../lib/active_model/validations/acceptance.rb | 2 ++ .../lib/active_model/validations/confirmation.rb | 2 ++ .../lib/active_model/validations/exclusion.rb | 2 ++ activemodel/lib/active_model/validations/format.rb | 2 ++ .../lib/active_model/validations/inclusion.rb | 2 ++ activemodel/lib/active_model/validations/length.rb | 2 ++ .../lib/active_model/validations/numericality.rb | 2 ++ .../lib/active_model/validations/presence.rb | 2 ++ .../lib/active_model/validations/validates.rb | 18 ++++++++++-- activemodel/lib/active_model/validations/with.rb | 6 ++-- activemodel/test/cases/validations_test.rb | 33 ++++++++++++++++++++++ 12 files changed, 75 insertions(+), 6 deletions(-) diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 36819553ee..843c0c3cb5 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -63,7 +63,7 @@ module ActiveModel class Errors include Enumerable - CALLBACKS_OPTIONS = [:if, :unless, :on, :allow_nil, :allow_blank] + CALLBACKS_OPTIONS = [:if, :unless, :on, :allow_nil, :allow_blank, :strict] attr_reader :messages @@ -218,6 +218,9 @@ module ActiveModel elsif message.is_a?(Proc) message = message.call end + if options[:strict] + raise ActiveModel::StrictValidationFailed, message + end self[attribute] << message end @@ -319,4 +322,7 @@ module ActiveModel I18n.translate(key, options) end end + + class StrictValidationFailed < StandardError + end end diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index 01907ac9da..e628c6f306 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -58,6 +58,8 @@ module ActiveModel # :unless => Proc.new { |user| user.signup_step <= 2 }). # The method, proc or string should return or evaluate to a true or # false value. + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information def validates_acceptance_of(*attr_names) validates_with AcceptanceValidator, _merge_attributes(attr_names) end diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index a9dcb0b505..6573a7d264 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -58,6 +58,8 @@ module ActiveModel # :unless => :skip_validation, or # :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information def validates_confirmation_of(*attr_names) validates_with ConfirmationValidator, _merge_attributes(attr_names) end diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index d3b8d31502..644cc814a7 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -59,6 +59,8 @@ module ActiveModel # * :unless - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information def validates_exclusion_of(*attr_names) validates_with ExclusionValidator, _merge_attributes(attr_names) end diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index 090e8cfbae..d3faa8c6a6 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -84,6 +84,8 @@ module ActiveModel # * :unless - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information def validates_format_of(*attr_names) validates_with FormatValidator, _merge_attributes(attr_names) end diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 9a9270d615..147e2ecb69 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -59,6 +59,8 @@ module ActiveModel # * :unless - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information def validates_inclusion_of(*attr_names) validates_with InclusionValidator, _merge_attributes(attr_names) end diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index 144e73904e..eb7aac709d 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -96,6 +96,8 @@ module ActiveModel # * :tokenizer - Specifies how to split up the attribute string. (e.g. :tokenizer => lambda {|str| str.scan(/\w+/)} to # count words as in above example.) # Defaults to lambda{ |value| value.split(//) } which counts individual characters. + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information def validates_length_of(*attr_names) validates_with LengthValidator, _merge_attributes(attr_names) end diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 0d1903362c..34d447a0fa 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -107,6 +107,8 @@ module ActiveModel # * :unless - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information # # The following checks can also be supplied with a proc or a symbol which corresponds to a method: # * :greater_than diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index cfb4c33dcc..35af7152db 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -35,6 +35,8 @@ module ActiveModel # * unless - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). # The method, proc or string should return or evaluate to a true or false value. + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information # def validates_presence_of(*attr_names) validates_with PresenceValidator, _merge_attributes(attr_names) diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 7ff42de00b..43b095d11a 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -70,8 +70,8 @@ module ActiveModel # validator's initializer as +options[:in]+ while other types including # regular expressions and strings are passed as +options[:with]+ # - # Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+ and +:allow_nil+ can be given - # to one specific validator, as a hash: + # Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+ and +:strict+ + # can be given to one specific validator, as a hash: # # validates :password, :presence => { :if => :password_required? }, :confirmation => true # @@ -101,12 +101,24 @@ module ActiveModel end end + # This method is used to define validation that can not be correcterized by end user + # and is considered exceptional. + # So each validator defined with bang or :strict option set to true + # will always raise ActiveModel::InternalValidationFailed instead of adding error + # when validation fails + # See validates for more information about validation itself. + def validates!(*attributes) + options = attributes.extract_options! + options[:strict] = true + validates(*(attributes << options)) + end + protected # When creating custom validators, it might be useful to be able to specify # additional default keys. This can be done by overwriting this method. def _validates_default_keys - [ :if, :unless, :on, :allow_blank, :allow_nil ] + [ :if, :unless, :on, :allow_blank, :allow_nil , :strict] end def _parse_validates_options(options) #:nodoc: diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index a87b213fe4..83aae206a6 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -61,7 +61,9 @@ module ActiveModel # (e.g. :unless => :skip_validation, or # :unless => Proc.new { |user| user.signup_step <= 2 }). # The method, proc or string should return or evaluate to a true or false value. - # + # * :strict - Specifies whether validation should be strict. + # See ActiveModel::Validation#validates! for more information + # If you pass any additional configuration options, they will be passed # to the class and available as options: # @@ -140,4 +142,4 @@ module ActiveModel end end end -end \ No newline at end of file +end diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb index 0b50acf913..2f4376bd41 100644 --- a/activemodel/test/cases/validations_test.rb +++ b/activemodel/test/cases/validations_test.rb @@ -297,4 +297,37 @@ class ValidationsTest < ActiveModel::TestCase assert auto.valid? end + + def test_strict_validation_in_validates + Topic.validates :title, :strict => true, :presence => true + assert_raises ActiveModel::StrictValidationFailed do + Topic.new.valid? + end + end + + def test_strict_validation_not_fails + Topic.validates :title, :strict => true, :presence => true + assert Topic.new(:title => "hello").valid? + end + + def test_strict_validation_particular_validator + Topic.validates :title, :presence => {:strict => true} + assert_raises ActiveModel::StrictValidationFailed do + Topic.new.valid? + end + end + + def test_strict_validation_in_custom_validator_helper + Topic.validates_presence_of :title, :strict => true + assert_raises ActiveModel::StrictValidationFailed do + Topic.new.valid? + end + end + + def test_validates_with_bang + Topic.validates! :title, :presence => true + assert_raises ActiveModel::StrictValidationFailed do + Topic.new.valid? + end + end end -- cgit v1.2.3 From 03b96306176bfc328929cb422ae61d37ee071310 Mon Sep 17 00:00:00 2001 From: Marc G Gauthier Date: Fri, 19 Aug 2011 11:11:17 +0200 Subject: Do not try to use as a parameter elements that are not acceptable --- activeresource/lib/active_resource/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index 693bd0592e..f88772a7ff 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -955,7 +955,7 @@ module ActiveResource prefix_options, query_options = {}, {} (options || {}).each do |key, value| - next if key.blank? + next if key.blank? || [Fixnum, Date, Time, Float].include?(key.class) (prefix_parameters.include?(key.to_sym) ? prefix_options : query_options)[key.to_sym] = value end -- cgit v1.2.3 From 4fb4484cad22e3a3e3cbdcee6c8c5c1c309e4fbb Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Sat, 20 Aug 2011 15:57:24 -0500 Subject: Add .rbenv-version to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2d3c39d885..a5bedb78e1 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ railties/doc railties/guides/output railties/tmp .rvmrc +.rbenv-version RDOC_MAIN.rdoc -- cgit v1.2.3 From f6ceb944eaea525362db38aa990cac3e6f76ac5a Mon Sep 17 00:00:00 2001 From: Teng Siong Ong Date: Sun, 21 Aug 2011 15:14:45 -0500 Subject: fix escape_javascript for unicode character \u2028. --- actionpack/lib/action_view/helpers/javascript_helper.rb | 5 +++-- actionpack/test/template/javascript_helper_test.rb | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 4484390fde..f1b071caf7 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -10,7 +10,8 @@ module ActionView "\n" => '\n', "\r" => '\n', '"' => '\\"', - "'" => "\\'" } + "'" => "\\'", + "\342\200\250" => '
' } # Escape carrier returns and single and double quotes for JavaScript segments. # Also available through the alias j(). This is particularly helpful in JavaScript responses, like: @@ -18,7 +19,7 @@ module ActionView # $('some_element').replaceWith('<%=j render 'some/element_template' %>'); def escape_javascript(javascript) if javascript - result = javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) {|match| JS_ESCAPE_MAP[match] } + result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|[\n\r"'])/) {|match| JS_ESCAPE_MAP[match] } javascript.html_safe? ? result.html_safe : result else '' diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index dd8b7b7cd5..bab9d42472 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -27,6 +27,7 @@ class JavaScriptHelperTest < ActionView::TestCase assert_equal %(This \\"thing\\" is really\\n netos\\'), escape_javascript(%(This "thing" is really\n netos')) assert_equal %(backslash\\\\test), escape_javascript( %(backslash\\test) ) assert_equal %(dont <\\/close> tags), escape_javascript(%(dont tags)) + assert_equal %(unicode 
 newline), escape_javascript(%(unicode \342\200\250 newline)) assert_equal %(dont <\\/close> tags), j(%(dont tags)) end -- cgit v1.2.3 From 95bece9155c46a2273a3febc3a2e176b8c15df8f Mon Sep 17 00:00:00 2001 From: Joost Baaij Date: Mon, 22 Aug 2011 00:10:01 +0300 Subject: Removed my name from the changelog as the amount of blogspam became ridiculous. When will docrails be back? :-p --- railties/guides/source/getting_started.textile | 1 - 1 file changed, 1 deletion(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 092ca90a30..755f59f8f9 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1890,7 +1890,6 @@ h3. Changelog * April 26, 2011: Change migration code from +up+, +down+ pair to +change+ method by "Prem Sichanugrist":http://sikachu.com * April 11, 2011: Change scaffold_controller generator to create format block for JSON instead of XML by "Sebastian Martinez":http://www.wyeworks.com -* August 30, 2010: Minor editing after Rails 3 release by "Joost Baaij":http://www.spacebabies.nl * July 12, 2010: Fixes, editing and updating of code samples by "Jaime Iniesta":http://jaimeiniesta.com * May 16, 2010: Added a section on configuration gotchas to address common encoding problems that people might have by "Yehuda Katz":http://www.yehudakatz.com * April 30, 2010: Fixes, editing and updating of code samples by "Rohit Arondekar":http://rohitarondekar.com -- cgit v1.2.3 From 18b2223b3290c4b3daa310edfc06b4d51161c312 Mon Sep 17 00:00:00 2001 From: "Andrey A.I. Sitnik" Date: Mon, 22 Aug 2011 09:36:36 +1100 Subject: Allow to debug assets by config.assets.debug --- actionpack/lib/sprockets/helpers/rails_helper.rb | 10 ++++++---- actionpack/test/template/sprockets_helper_test.rb | 20 ++++++-------------- railties/guides/source/asset_pipeline.textile | 2 +- railties/lib/rails/application/configuration.rb | 1 + .../templates/config/environments/development.rb.tt | 3 +++ 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 69306ef631..38df9cbf6e 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -70,10 +70,12 @@ module Sprockets private def debug_assets? - Rails.env.development? || Rails.env.test? || - params[:debug_assets] == '1' || params[:debug_assets] == 'true' - rescue NoMethodError - false + begin + params[:debug_assets] == '1' || + params[:debug_assets] == 'true' + rescue NoMethodError + false + end || Rails.application.config.assets.debug end # Override to specify an alternative prefix for asset path generation. diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb index d303acad0f..cac277cf11 100644 --- a/actionpack/test/template/sprockets_helper_test.rb +++ b/actionpack/test/template/sprockets_helper_test.rb @@ -141,8 +141,6 @@ class SprocketsHelperTest < ActionView::TestCase end test "javascript include tag" do - Rails.env.stubs(:test?).returns(false) - assert_match %r{}, javascript_include_tag(:application) @@ -156,14 +154,12 @@ class SprocketsHelperTest < ActionView::TestCase assert_match %r{\n}, javascript_include_tag("xmlhr", "extra") - Rails.env.stubs(:test?).returns(true) + assert_match %r{\n}, + javascript_include_tag(:application, :debug => true) + @config.assets.debug = true assert_match %r{\n}, javascript_include_tag(:application) - - assert_match %r{}, - javascript_include_tag(:application, :debug => false) - end test "stylesheet path" do @@ -180,8 +176,6 @@ class SprocketsHelperTest < ActionView::TestCase end test "stylesheet link tag" do - Rails.env.stubs(:test?).returns(false) - assert_match %r{}, stylesheet_link_tag(:application) @@ -200,14 +194,12 @@ class SprocketsHelperTest < ActionView::TestCase assert_match %r{\n}, stylesheet_link_tag("style", "extra") - Rails.env.stubs(:test?).returns(true) + assert_match %r{\n}, + stylesheet_link_tag(:application, :debug => true) + @config.assets.debug = true assert_match %r{\n}, stylesheet_link_tag(:application) - - assert_match %r{}, - stylesheet_link_tag(:application, :debug => false) - end test "alternate asset prefix" do diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 34ab00e80d..012149c40e 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -224,7 +224,7 @@ If any of the files in the manifest have changed between requests, the server re h4. Debugging Assets -You can put +?debug_assets=true+ or +?debug_assets=1+ at the end of a URL and Sprockets expands the lines which load the assets. For example, if you had an +app/assets/javascripts/application.js+ file containing these lines: +You can put +?debug_assets=true+ or +?debug_assets=1+ at the end of a URL or set +config.assets.debug+ and Sprockets expands the lines which load the assets. For example, if you had an +app/assets/javascripts/application.js+ file containing these lines: //= require "projects" diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index cd850b6a75..f1add68890 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -38,6 +38,7 @@ module Rails @assets.precompile = [ /\w+\.(?!js|css).+/, /application.(css|js)$/ ] @assets.prefix = "/assets" @assets.version = '' + @assets.debug = false @assets.cache_store = [ :file_store, "#{root}/tmp/cache/assets/" ] @assets.js_compressor = nil diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index 3e0c29a587..47078e3af9 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -29,4 +29,7 @@ # Do not compress assets config.assets.compress = false + + # Expands the lines which load the assets + config.assets.debug = true end -- cgit v1.2.3 From 35c8a896fc75c222834e1324fe4710c1ba2645c4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 21 Aug 2011 15:55:15 -0700 Subject: Merge pull request #2620 from cesario/3-1-0 Fix CI and rename 1 misleading test case. --- 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 fb7ebaa1fa..2415195a17 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -189,7 +189,7 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "test/performance/browsing_test.rb" end - def test_generator_if_skip_active_record_is_given + def test_generator_if_skip_sprockets_is_given run_generator [destination_root, "--skip-sprockets"] assert_file "config/application.rb" do |content| assert_match(/#\s+require\s+["']sprockets\/railtie["']/, content) -- cgit v1.2.3 From 44f0d94469fb6c5d400776c3307b16fb8e4d1eb1 Mon Sep 17 00:00:00 2001 From: Andrey Ognevsky Date: Sun, 21 Aug 2011 01:25:11 +0300 Subject: Add Destroy Alias * Added destroy alias to rails generator * add alias info for destroy command * Updated command line guides --- railties/guides/source/command_line.textile | 2 ++ railties/lib/rails/commands.rb | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile index 6d5132a1bf..f6b33d283c 100644 --- a/railties/guides/source/command_line.textile +++ b/railties/guides/source/command_line.textile @@ -325,6 +325,8 @@ h4. +rails destroy+ Think of +destroy+ as the opposite of +generate+. It'll figure out what generate did, and undo it. +You can also use the alias "d" to invoke the destroy command: rails d. + $ rails generate model Oops exists app/models/ diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index a21484e5cb..ada150ceec 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -4,6 +4,7 @@ ARGV << '--help' if ARGV.empty? aliases = { "g" => "generate", + "d" => "destroy", "c" => "console", "s" => "server", "db" => "dbconsole", @@ -87,7 +88,7 @@ The most common rails commands are: In addition to those, there are: application Generate the Rails application code - destroy Undo code generated with "generate" + destroy Undo code generated with "generate" (short-cut alias: "d") benchmarker See how fast a piece of code runs profiler Get profile information from a piece of code plugin Install a plugin -- cgit v1.2.3 From db181bddb646ff22c85218072ba5c69ca680dabd Mon Sep 17 00:00:00 2001 From: Daniel Schierbeck Date: Mon, 22 Aug 2011 16:50:33 +0200 Subject: Refactor Sprockets::Helpers::RailsHelper#performing_caching? No need for them lines to get so long! Also, move that comment into the method body where it belongs! --- actionpack/lib/sprockets/helpers/rails_helper.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 69306ef631..cb01532449 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -139,9 +139,14 @@ module Sprockets end end - # When included in Sprockets::Context, we need to ask the top-level config as the controller is not available def performing_caching? - config.action_controller.present? ? config.action_controller.perform_caching : config.perform_caching + # When included in Sprockets::Context, we need to ask the + # top-level config as the controller is not available. + if config.action_controller.present? + config.action_controller.perform_caching + else + config.perform_caching + end end end end -- cgit v1.2.3 From e1f11ff37f79d72b3afd5b718529186f2bc1417f Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Mon, 22 Aug 2011 11:12:54 -0500 Subject: Fix Sprockets rewrite_asset_path --- actionpack/lib/sprockets/helpers/rails_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index cb01532449..c239af77bc 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -126,7 +126,7 @@ module Sprockets else source = digest_for(source) if performing_caching? source = File.join(dir, source) - source = "/#{url}" unless source =~ /^\// + source = "/#{source}" unless source =~ /^\// source end end -- cgit v1.2.3 From 71232f5d5d88d5390ff790b7b3336f5168e9f270 Mon Sep 17 00:00:00 2001 From: Anand Date: Mon, 22 Aug 2011 17:07:23 +0530 Subject: Travis status image added to GitHub README, excluding API pages. --- README.rdoc | 2 +- Rakefile | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index 1e78799e83..f0aa962272 100644 --- a/README.rdoc +++ b/README.rdoc @@ -62,7 +62,7 @@ can read more about Action Pack in its {README}[link:/rails/rails/blob/master/ac * The {API Documentation}[http://api.rubyonrails.org]. -== Contributing +== Contributing http://travis-ci.org/rails/rails.png We encourage you to contribute to Ruby on Rails! Please check out the {Contributing to Rails guide}[http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html] for guidelines about how diff --git a/Rakefile b/Rakefile index 36007f6e91..4cf01cf063 100755 --- a/Rakefile +++ b/Rakefile @@ -76,6 +76,9 @@ RDoc::Task.new do |rdoc| rdoc_main.gsub!(/^(?=\S).*?\b(?=Rails)\b/) { "#$&\\" } rdoc_main.gsub!(%r{link:/rails/rails/blob/master/(\w+)/README\.rdoc}, "link:files/\\1/README_rdoc.html") + # Remove Travis build status image from API pages. Only GitHub README page gets this image + rdoc_main.gsub!("http://travis-ci.org/rails/rails.png", "") + File.open(RDOC_MAIN, 'w') do |f| f.write(rdoc_main) end -- cgit v1.2.3 From d17954c7d826b64ae7d04aac4db6f919d5e22589 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Mon, 22 Aug 2011 23:39:17 -0500 Subject: Add destroy alias to engines --- railties/lib/rails/engine/commands.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/engine/commands.rb b/railties/lib/rails/engine/commands.rb index 3b0920e213..b71119af77 100644 --- a/railties/lib/rails/engine/commands.rb +++ b/railties/lib/rails/engine/commands.rb @@ -3,7 +3,8 @@ require 'active_support/core_ext/object/inclusion' ARGV << '--help' if ARGV.empty? aliases = { - "g" => "generate" + "g" => "generate", + "d" => "destroy" } command = ARGV.shift @@ -30,7 +31,7 @@ Usage: rails COMMAND [ARGS] The common rails commands available for engines are: generate Generate new code (short-cut alias: "g") - destroy Undo code generated with "generate" + destroy Undo code generated with "generate" (short-cut alias: "d") All commands can be run with -h for more information. EOT -- cgit v1.2.3 From 14cf4b2e353f923155aab1ae0eaafed3c2924b12 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Tue, 23 Aug 2011 11:07:37 +0100 Subject: Don't modify params in place - fixes #2624 --- actionpack/lib/action_controller/test_case.rb | 8 +++----- actionpack/test/controller/test_test.rb | 6 ++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index c8cf04bb69..a38e5a46da 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -401,9 +401,7 @@ module ActionController def paramify_values(hash_or_array_or_value) case hash_or_array_or_value when Hash - hash_or_array_or_value.each do |key, value| - hash_or_array_or_value[key] = paramify_values(value) - end + Hash[hash_or_array_or_value.map{|key, value| [key, paramify_values(value)] }] when Array hash_or_array_or_value.map {|i| paramify_values(i)} when Rack::Test::UploadedFile @@ -416,7 +414,7 @@ module ActionController def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') # Ensure that numbers and symbols passed as params are converted to # proper params, as is the case when engaging rack. - paramify_values(parameters) + parameters = paramify_values(parameters) # Sanity check for required instance variables so we can give an # understandable error message. @@ -450,7 +448,7 @@ module ActionController @controller.params.merge!(parameters) build_request_uri(action, parameters) @controller.class.class_eval { include Testing } - @controller.recycle! + @controller.recycle! @controller.process_with_new_base_test(@request, @response) @assigns = @controller.respond_to?(:view_assigns) ? @controller.view_assigns : {} @request.session.delete('flash') if @request.session['flash'].blank? diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index 043d44500a..eae5a3d472 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -515,6 +515,12 @@ XML ) end + def test_params_passing_doesnt_modify_in_place + page = {:name => "Page name", :month => 4, :year => 2004, :day => 6} + get :test_params, :page => page + assert_equal 2004, page[:year] + end + def test_id_converted_to_string get :test_params, :id => 20, :foo => Object.new assert_kind_of String, @request.path_parameters['id'] -- cgit v1.2.3 From 56e32ad40f8a1658c507ab0565767b82018369af Mon Sep 17 00:00:00 2001 From: Anand Date: Tue, 23 Aug 2011 16:03:58 +0530 Subject: added more tests for only-include and except-include options in serialization --- activemodel/test/cases/serialization_test.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/activemodel/test/cases/serialization_test.rb b/activemodel/test/cases/serialization_test.rb index 5122f08eec..071cb9ff4e 100644 --- a/activemodel/test/cases/serialization_test.rb +++ b/activemodel/test/cases/serialization_test.rb @@ -114,8 +114,21 @@ class SerializationTest < ActiveModel::TestCase @user.friends.first.friends = [@user] expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", :friends=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male', - :friends => ["email"=>"david@example.com", "gender"=>"male", "name"=>"David"]}, + :friends => [{"email"=>"david@example.com", "gender"=>"male", "name"=>"David"}]}, {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female', :friends => []}]} assert_equal expected , @user.serializable_hash(:include => {:friends => {:include => :friends}}) end + + def test_only_include + expected = {"name"=>"David", :friends => [{"name" => "Joe"}, {"name" => "Sue"}]} + assert_equal expected , @user.serializable_hash(:only => :name, :include => {:friends => {:only => :name}}) + end + + def test_except_include + expected = {"name"=>"David", "email"=>"david@example.com", + :friends => [{"name" => 'Joe', "email" => 'joe@example.com'}, + {"name" => "Sue", "email" => 'sue@example.com'}]} + assert_equal expected , @user.serializable_hash(:except => :gender, :include => {:friends => {:except => :gender}}) + end + end -- cgit v1.2.3 From cacdbb94374ebdc1c1fa5445467fca3d12ca31cd Mon Sep 17 00:00:00 2001 From: Daniel Schierbeck Date: Tue, 23 Aug 2011 12:39:07 +0200 Subject: Remove trailing whitespace --- activesupport/test/core_ext/array_ext_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb index f035505a01..52231aaeb0 100644 --- a/activesupport/test/core_ext/array_ext_test.rb +++ b/activesupport/test/core_ext/array_ext_test.rb @@ -470,8 +470,8 @@ class ArrayPrependAppendTest < Test::Unit::TestCase def test_append assert_equal [1, 2], [1].append(2) end - + def test_prepend assert_equal [2, 1], [1].prepend(2) end -end \ No newline at end of file +end -- cgit v1.2.3 From 1be3442a0a6df37525ff706fecfd65de7eae65cf Mon Sep 17 00:00:00 2001 From: Anand Date: Tue, 23 Aug 2011 16:30:02 +0530 Subject: added missing require array/wrap in serialization --- activemodel/lib/active_model/serialization.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index 9260c5082d..b9f6f6cbbf 100644 --- a/activemodel/lib/active_model/serialization.rb +++ b/activemodel/lib/active_model/serialization.rb @@ -1,5 +1,7 @@ require 'active_support/core_ext/hash/except' require 'active_support/core_ext/hash/slice' +require 'active_support/core_ext/array/wrap' + module ActiveModel # == Active Model Serialization -- cgit v1.2.3 From c46befbce300722650e324047a9342f628acc36d Mon Sep 17 00:00:00 2001 From: Joost Baaij Date: Tue, 23 Aug 2011 14:17:29 +0200 Subject: Revert "Removed my name from the changelog as the amount of blogspam became ridiculous. " This reverts commit 95bece9155c46a2273a3febc3a2e176b8c15df8f. --- railties/guides/source/getting_started.textile | 1 + 1 file changed, 1 insertion(+) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 755f59f8f9..092ca90a30 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1890,6 +1890,7 @@ h3. Changelog * April 26, 2011: Change migration code from +up+, +down+ pair to +change+ method by "Prem Sichanugrist":http://sikachu.com * April 11, 2011: Change scaffold_controller generator to create format block for JSON instead of XML by "Sebastian Martinez":http://www.wyeworks.com +* August 30, 2010: Minor editing after Rails 3 release by "Joost Baaij":http://www.spacebabies.nl * July 12, 2010: Fixes, editing and updating of code samples by "Jaime Iniesta":http://jaimeiniesta.com * May 16, 2010: Added a section on configuration gotchas to address common encoding problems that people might have by "Yehuda Katz":http://www.yehudakatz.com * April 30, 2010: Fixes, editing and updating of code samples by "Rohit Arondekar":http://rohitarondekar.com -- cgit v1.2.3 From 707378c4892a4666c8b7ed73bef577338bca3c38 Mon Sep 17 00:00:00 2001 From: Joost Baaij Date: Tue, 23 Aug 2011 14:18:06 +0200 Subject: removed the link to my blog to help stop endless comments --- railties/guides/source/getting_started.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 092ca90a30..d2bfcfdbb4 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1890,7 +1890,7 @@ h3. Changelog * April 26, 2011: Change migration code from +up+, +down+ pair to +change+ method by "Prem Sichanugrist":http://sikachu.com * April 11, 2011: Change scaffold_controller generator to create format block for JSON instead of XML by "Sebastian Martinez":http://www.wyeworks.com -* August 30, 2010: Minor editing after Rails 3 release by "Joost Baaij":http://www.spacebabies.nl +* August 30, 2010: Minor editing after Rails 3 release by Joost Baaij * July 12, 2010: Fixes, editing and updating of code samples by "Jaime Iniesta":http://jaimeiniesta.com * May 16, 2010: Added a section on configuration gotchas to address common encoding problems that people might have by "Yehuda Katz":http://www.yehudakatz.com * April 30, 2010: Fixes, editing and updating of code samples by "Rohit Arondekar":http://rohitarondekar.com -- cgit v1.2.3 From 13400ac289344dae002c77a3c2b820268f08745e Mon Sep 17 00:00:00 2001 From: Andrew White Date: Tue, 23 Aug 2011 14:55:31 +0100 Subject: Ensure regexp and hash key are UTF-8 --- actionpack/lib/action_view/helpers/javascript_helper.rb | 13 ++++++++++--- actionpack/test/template/javascript_helper_test.rb | 7 ++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index f1b071caf7..474ea53f91 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -1,4 +1,5 @@ require 'action_view/helpers/tag_helper' +require 'active_support/core_ext/string/encoding' module ActionView module Helpers @@ -10,8 +11,14 @@ module ActionView "\n" => '\n', "\r" => '\n', '"' => '\\"', - "'" => "\\'", - "\342\200\250" => '
' } + "'" => "\\'" + } + + if "ruby".encoding_aware? + JS_ESCAPE_MAP["\342\200\250".force_encoding('UTF-8').encode!] = '
' + else + JS_ESCAPE_MAP["\342\200\250"] = '
' + end # Escape carrier returns and single and double quotes for JavaScript segments. # Also available through the alias j(). This is particularly helpful in JavaScript responses, like: @@ -19,7 +26,7 @@ module ActionView # $('some_element').replaceWith('<%=j render 'some/element_template' %>'); def escape_javascript(javascript) if javascript - result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|[\n\r"'])/) {|match| JS_ESCAPE_MAP[match] } + result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] } javascript.html_safe? ? result.html_safe : result else '' diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index bab9d42472..4b9c3c97b1 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'active_support/core_ext/string/encoding' class JavaScriptHelperTest < ActionView::TestCase tests ActionView::Helpers::JavaScriptHelper @@ -27,7 +28,11 @@ class JavaScriptHelperTest < ActionView::TestCase assert_equal %(This \\"thing\\" is really\\n netos\\'), escape_javascript(%(This "thing" is really\n netos')) assert_equal %(backslash\\\\test), escape_javascript( %(backslash\\test) ) assert_equal %(dont <\\/close> tags), escape_javascript(%(dont tags)) - assert_equal %(unicode 
 newline), escape_javascript(%(unicode \342\200\250 newline)) + if "ruby".encoding_aware? + assert_equal %(unicode 
 newline), escape_javascript(%(unicode \342\200\250 newline).force_encoding('UTF-8').encode!) + else + assert_equal %(unicode 
 newline), escape_javascript(%(unicode \342\200\250 newline)) + end assert_equal %(dont <\\/close> tags), j(%(dont tags)) end -- cgit v1.2.3 From ebea387e4bb9f44d8c678ed9bad2ab2091d1f9c6 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Tue, 23 Aug 2011 15:33:59 +0100 Subject: Add failing test case for #2654 --- actionpack/test/controller/test_test.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index eae5a3d472..cba3aded2f 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -50,6 +50,10 @@ class TestTest < ActionController::TestCase render :text => request.query_string end + def test_protocol + render :text => request.protocol + end + def test_html_output render :text => < @@ -598,6 +602,19 @@ XML assert_nil @request.symbolized_path_parameters[:id] end + def test_request_protocol_is_reset_after_request + get :test_protocol + assert_equal "http://", @response.body + + @request.env["HTTPS"] = "on" + get :test_protocol + assert_equal "https://", @response.body + + @request.env.delete("HTTPS") + get :test_protocol + assert_equal "http://", @response.body + end + def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set cookies['foo'] = 'bar' get :no_op -- cgit v1.2.3 From 68a13eded347248fb9d4c8ef7f0ed2af52bba994 Mon Sep 17 00:00:00 2001 From: David Majda Date: Tue, 23 Aug 2011 14:12:41 +0200 Subject: Make ActionController::TestCase#recycle! set @protocol to nil This ensures that the protocol does not get carried over when there are two or more requests in functional tests. This was a problem when e.g. the first request was HTTP and the second request was HTTPS. Closes #2654. Signed-off-by: Andrew White --- actionpack/lib/action_controller/test_case.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index a38e5a46da..40332da321 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -180,7 +180,7 @@ module ActionController @env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ } @symbolized_path_params = nil @method = @request_method = nil - @fullpath = @ip = @remote_ip = nil + @fullpath = @ip = @remote_ip = @protocol = nil @env['action_dispatch.request.query_parameters'] = {} @set_cookies ||= {} @set_cookies.update(Hash[cookie_jar.instance_variable_get("@set_cookies").map{ |k,o| [k,o[:value]] }]) -- cgit v1.2.3 From a10606c490471d8e1483acb3b31d7f2d51e9ebbe Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Aug 2011 16:55:11 -0700 Subject: require needs to return true or false. thank you Ryan "zenspider" Davis --- activesupport/lib/active_support/dependencies.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 3f6c93e860..cc6e811224 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -233,7 +233,9 @@ module ActiveSupport #:nodoc: end def require(file, *) - load_dependency(file) { super } + result = false + load_dependency(file) { result = super } + result end # Mark the given constant as unloadable. Unloadable constants are removed each -- cgit v1.2.3 From 29004de1a2ded5e8705d421ffe60ff6f631110b1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Aug 2011 17:04:05 -0700 Subject: `load` should also return the value from `super` --- activesupport/lib/active_support/dependencies.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index cc6e811224..6252e7f7c3 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -229,7 +229,9 @@ module ActiveSupport #:nodoc: end def load(file, *) - load_dependency(file) { super } + result = false + load_dependency(file) { result = super } + result end def require(file, *) -- cgit v1.2.3 From d133fd6d290a4812a17cc58c0d7e5cd3895e23f6 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 23 Aug 2011 21:36:21 -0500 Subject: Debug assets shouldn't ignore media type for stylesheets. Closes #2625 --- actionpack/lib/sprockets/helpers/rails_helper.rb | 5 +++-- actionpack/test/template/sprockets_helper_test.rb | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 7200ab1ddd..051624d05e 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -43,17 +43,18 @@ module Sprockets options = sources.extract_options! debug = options.key?(:debug) ? options.delete(:debug) : debug_assets? body = options.key?(:body) ? options.delete(:body) : false + media = options.key?(:media) ? options.delete(:media) : "screen" sources.collect do |source| if debug && asset = asset_paths.asset_for(source, 'css') asset.to_a.map { |dep| - stylesheet_link_tag(dep, :debug => false, :body => true) + stylesheet_link_tag(dep, :media => media, :debug => false, :body => true) }.join("\n").html_safe else tag_options = { 'rel' => "stylesheet", 'type' => "text/css", - 'media' => "screen", + 'media' => media, 'href' => asset_path(source, 'css', body, :request) }.merge(options.stringify_keys) diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb index cac277cf11..b5a0e6cf04 100644 --- a/actionpack/test/template/sprockets_helper_test.rb +++ b/actionpack/test/template/sprockets_helper_test.rb @@ -200,6 +200,9 @@ class SprocketsHelperTest < ActionView::TestCase @config.assets.debug = true assert_match %r{\n}, stylesheet_link_tag(:application) + + assert_match %r{\n}, + stylesheet_link_tag(:application, :media => "print") end test "alternate asset prefix" do -- cgit v1.2.3 From 11146f1485ac83950c1079a458bd5fbae6ab405b Mon Sep 17 00:00:00 2001 From: Brian Morearty Date: Tue, 23 Aug 2011 21:34:43 -0700 Subject: Remove extra word from sentence in initialization guide. --- railties/guides/source/initialization.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index b93c4f35ac..9cc4dd5f04 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -1,6 +1,6 @@ h2. The Rails Initialization Process -This guide explains the internals of the initialization process in Rails works as of Rails 3.1. It is an extremely in-depth guide and recommended for advanced Rails developers. +This guide explains the internals of the initialization process in Rails as of Rails 3.1. It is an extremely in-depth guide and recommended for advanced Rails developers. * Using +rails server+ * Using Passenger -- cgit v1.2.3 From a5e925c1d35ff10a22a98841f6a02925d4263947 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev Date: Wed, 24 Aug 2011 10:25:29 +0300 Subject: Add strict validation example to guides --- railties/guides/source/active_model_basics.textile | 7 +++++-- railties/guides/source/active_record_validations_callbacks.textile | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/active_model_basics.textile b/railties/guides/source/active_model_basics.textile index f3a2b2edbc..7d435456bd 100644 --- a/railties/guides/source/active_model_basics.textile +++ b/railties/guides/source/active_model_basics.textile @@ -184,20 +184,23 @@ Validations module adds the ability to class objects to validate them in Active class Person include ActiveModel::Validations - attr_accessor :name, :email + attr_accessor :name, :email, :token validates :name, :presence => true validates_format_of :email, :with => /^([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})$/i + validates! :token, :presence => true end -person = Person.new +person = Person.new(:token => "2b1f325") person.valid? #=> false person.name = 'vishnu' person.email = 'me' person.valid? #=> false person.email = 'me@vishnuatrai.com' person.valid? #=> true +person.token = nil +person.valid? #=> raises ActiveModel::StrictValidationFailed h3. Changelog diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile index aba3224ba7..18fc77c660 100644 --- a/railties/guides/source/active_record_validations_callbacks.textile +++ b/railties/guides/source/active_record_validations_callbacks.textile @@ -1270,6 +1270,7 @@ The +after_commit+ and +after_rollback+ callbacks are guaranteed to be called fo h3. Changelog +* August 24, 2011: Add strict validation usage example. "Bogdan Gusiev":http://gusiev.com * February 17, 2011: Add description of transaction callbacks. * July 20, 2010: Fixed typos and rephrased some paragraphs for clarity. "Jaime Iniesta":http://jaimeiniesta.com * May 24, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -- cgit v1.2.3 From afe04da10b241434f7e1b4aed3d83b59971b379a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev Date: Wed, 24 Aug 2011 10:26:18 +0300 Subject: Add change log entry on strict validation --- activemodel/CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/activemodel/CHANGELOG b/activemodel/CHANGELOG index 9b7d2d026d..20e5816532 100644 --- a/activemodel/CHANGELOG +++ b/activemodel/CHANGELOG @@ -1,3 +1,5 @@ +* Add ability to define strict validation(with :strict => true option) that always raises exception when fails [Bogdan Gusiev] + * Deprecate "Model.model_name.partial_path" in favor of "model.to_partial_path" [Grant Hutchins, Peter Jaros] * Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior [Bogdan Gusiev] -- cgit v1.2.3 From 13dd7758cedf6152835c4c72b69b1fe631a60733 Mon Sep 17 00:00:00 2001 From: Damien Mathieu <42@dmathieu.com> Date: Tue, 23 Aug 2011 11:02:44 +0200 Subject: remove useless rescue params is a method, defined in every controller, which always returns a hash. If it raises a NoMethodError, it means there's a bug somewhere else, which we want to know about. --- actionpack/lib/sprockets/helpers/rails_helper.rb | 9 +++------ actionpack/test/abstract_unit.rb | 6 +++++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 7200ab1ddd..4fb8d0af37 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -70,12 +70,9 @@ module Sprockets private def debug_assets? - begin - params[:debug_assets] == '1' || - params[:debug_assets] == 'true' - rescue NoMethodError - false - end || Rails.application.config.assets.debug + params[:debug_assets] == '1' || + params[:debug_assets] == 'true' || + Rails.application.config.assets.debug end # Override to specify an alternative prefix for asset path generation. diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 24d071df39..aa7a01f6c9 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -142,7 +142,11 @@ class RoutedRackApp end class BasicController - attr_accessor :request + attr_accessor :request, :params + + def initialize + @params = {} + end def config @config ||= ActiveSupport::InheritableOptions.new(ActionController::Base.config).tap do |config| -- cgit v1.2.3 From eb0b71478ad4c37fdc4ec77bf2cf7c6b65dd36c4 Mon Sep 17 00:00:00 2001 From: Daniel Schierbeck Date: Tue, 23 Aug 2011 13:42:36 +0200 Subject: Simplify JavaScriptHelper#escape_javascript Use the Linus-style conditional. Also fix the documentation slightly. Signed-off-by: Andrew White --- actionpack/lib/action_view/helpers/javascript_helper.rb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 474ea53f91..d01e62378b 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -20,17 +20,16 @@ module ActionView JS_ESCAPE_MAP["\342\200\250"] = '
' end - # Escape carrier returns and single and double quotes for JavaScript segments. + # Escapes carriage returns and single and double quotes for JavaScript segments. + # # Also available through the alias j(). This is particularly helpful in JavaScript responses, like: # # $('some_element').replaceWith('<%=j render 'some/element_template' %>'); def escape_javascript(javascript) - if javascript - result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] } - javascript.html_safe? ? result.html_safe : result - else - '' - end + return "" if javascript.empty? + + result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] } + javascript.html_safe? ? result.html_safe : result end alias_method :j, :escape_javascript -- cgit v1.2.3 From 0a0da9d554490f01fe57d69fe8d98f29b02be3e5 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Wed, 24 Aug 2011 21:09:41 +0900 Subject: do not compute table names for abstract classes --- activerecord/lib/active_record/base.rb | 2 ++ activerecord/test/cases/base_test.rb | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index c76f98d6a0..03aea81d2c 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -624,6 +624,8 @@ module ActiveRecord #:nodoc: # Computes the table name, (re)sets it internally, and returns it. def reset_table_name #:nodoc: + return if abstract_class? + self.table_name = compute_table_name end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index fe46c00b47..bee183cc67 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1625,6 +1625,10 @@ class BasicsTest < ActiveRecord::TestCase assert !LooseDescendant.abstract_class? end + def test_abstract_class_table_name + assert_nil AbstractCompany.table_name + end + def test_base_class assert_equal LoosePerson, LoosePerson.base_class assert_equal LooseDescendant, LooseDescendant.base_class -- cgit v1.2.3 From 827cdae6fb5e21056b68ab8a89047ae82738871f Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Mon, 22 Aug 2011 23:19:25 -0500 Subject: Add config.allow_debugging option to determine if the debug_assets query param can be passed by user --- actionpack/lib/sprockets/helpers/rails_helper.rb | 7 ++-- actionpack/test/template/sprockets_helper_test.rb | 2 ++ railties/lib/rails/application/configuration.rb | 13 +++---- .../config/environments/development.rb.tt | 3 ++ .../app/templates/config/environments/test.rb.tt | 3 ++ railties/test/application/assets_test.rb | 42 ++++++++++++++++++++++ 6 files changed, 61 insertions(+), 9 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 4fb8d0af37..50a8db4000 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -70,9 +70,10 @@ module Sprockets private def debug_assets? - params[:debug_assets] == '1' || - params[:debug_assets] == 'true' || - Rails.application.config.assets.debug + Rails.application.config.assets.allow_debugging && + (Rails.application.config.assets.debug || + params[:debug_assets] == '1' || + params[:debug_assets] == 'true') end # Override to specify an alternative prefix for asset path generation. diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb index cac277cf11..5b4023809d 100644 --- a/actionpack/test/template/sprockets_helper_test.rb +++ b/actionpack/test/template/sprockets_helper_test.rb @@ -157,6 +157,7 @@ class SprocketsHelperTest < ActionView::TestCase assert_match %r{\n}, javascript_include_tag(:application, :debug => true) + @config.assets.allow_debugging = true @config.assets.debug = true assert_match %r{\n}, javascript_include_tag(:application) @@ -197,6 +198,7 @@ class SprocketsHelperTest < ActionView::TestCase assert_match %r{\n}, stylesheet_link_tag(:application, :debug => true) + @config.assets.allow_debugging = true @config.assets.debug = true assert_match %r{\n}, stylesheet_link_tag(:application) diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index f1add68890..c4a02ba5c0 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -33,12 +33,13 @@ module Rails @cache_store = [ :file_store, "#{root}/tmp/cache/" ] @assets = ActiveSupport::OrderedOptions.new - @assets.enabled = false - @assets.paths = [] - @assets.precompile = [ /\w+\.(?!js|css).+/, /application.(css|js)$/ ] - @assets.prefix = "/assets" - @assets.version = '' - @assets.debug = false + @assets.enabled = false + @assets.paths = [] + @assets.precompile = [ /\w+\.(?!js|css).+/, /application.(css|js)$/ ] + @assets.prefix = "/assets" + @assets.version = '' + @assets.debug = false + @assets.allow_debugging = false @assets.cache_store = [ :file_store, "#{root}/tmp/cache/assets/" ] @assets.js_compressor = nil diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index 47078e3af9..33f9939ffe 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -30,6 +30,9 @@ # Do not compress assets config.assets.compress = false + # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets + config.assets.allow_debugging = true + # Expands the lines which load the assets config.assets.debug = true end diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt index 80198cc21e..8e33a65b2d 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt @@ -41,4 +41,7 @@ # Print deprecation notices to the stderr config.active_support.deprecation = :stderr + + # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets + config.assets.allow_debugging = true end diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index a8d1382e94..1e6a93dbdf 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -135,5 +135,47 @@ module ApplicationTests assert_match "alert();", last_response.body assert_equal 200, last_response.status end + + test "assets are concatenated when debug is off and allow_debugging is off either if debug_assets param is provided" do + app_with_assets_in_view + + # config.assets.debug and config.assets.allow_debugging are false for production environment + ENV["RAILS_ENV"] = "production" + require "#{app_path}/config/environment" + + class ::PostsController < ActionController::Base ; end + + # the debug_assets params isn't used if allow_debugging is off + get '/posts?debug_assets=true' + assert_match /}, last_response.body + assert_not_match %r{}, last_response.body + end + + test "assets aren't concatened when allow_debugging is on and debug_assets params is true" do + app_file "config/initializers/allow_debugging.rb", "Rails.application.config.assets.allow_debugging = true" + + require "#{app_path}/config/environment" + + get '/posts?debug_assets=true' + assert_match %r{}, last_response.body + assert_match %r{}, last_response.body + end + end +end diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 1e6a93dbdf..a8d1382e94 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -135,47 +135,5 @@ module ApplicationTests assert_match "alert();", last_response.body assert_equal 200, last_response.status end - - test "assets are concatenated when debug is off and allow_debugging is off either if debug_assets param is provided" do - app_with_assets_in_view - - # config.assets.debug and config.assets.allow_debugging are false for production environment - ENV["RAILS_ENV"] = "production" - require "#{app_path}/config/environment" - - class ::PostsController < ActionController::Base ; end - - # the debug_assets params isn't used if allow_debugging is off - get '/posts?debug_assets=true' - assert_match /}, last_response.body - assert_not_match %r{}, last_response.body + assert_no_match %r{}, last_response.body end test "assets aren't concatened when allow_debugging is on and debug_assets params is true" do -- cgit v1.2.3 From 651ef614f1934578886ca792bb5e3eca8b5d1b48 Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Fri, 26 Aug 2011 11:29:05 +0530 Subject: Removed Unused Variable. --- actionpack/test/template/form_tag_helper_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 091f4e65b7..6eae9bf846 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -532,7 +532,7 @@ class FormTagHelperTest < ActionView::TestCase def test_image_label_tag_options_symbolize_keys_side_effects options = { :option => "random_option" } - actual = label_tag "submit source", "title", options + label_tag "submit source", "title", options assert_equal options, { :option => "random_option" } end -- cgit v1.2.3 From e8b525f16906458001fb1d10ed84d787760f19f3 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 26 Aug 2011 10:14:57 -0700 Subject: stop messing with the load path, load path should be adjusted in the test task --- activerecord/lib/active_record.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 511d402ee5..132dc12680 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -21,13 +21,6 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ - -activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) -$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) - -activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__) -$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path) - require 'active_support' require 'active_support/i18n' require 'active_model' -- cgit v1.2.3 From 6bdf4a3829acd089adddfb2b534ed66d974b902a Mon Sep 17 00:00:00 2001 From: Waynn Lue Date: Wed, 24 Aug 2011 23:00:43 -0700 Subject: incorporate feedback from vijaydev and dasch to rephrase this to sound more natural, and some grammar fixes. --- railties/README.rdoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/README.rdoc b/railties/README.rdoc index eb7ed961e3..501541eb06 100644 --- a/railties/README.rdoc +++ b/railties/README.rdoc @@ -1,12 +1,12 @@ = Railties -- Gluing the Engine to the Rails -Railties is responsible to glue all frameworks together. Overall, it: +Railties is responsible for gluing all frameworks together. Overall, it: -* handles all the bootstrapping process for a Rails application; +* handles the bootstrapping process for a Rails application; -* manages rails command line interface; +* manages the +rails+ command line interface; -* provides Rails generators core; +* and provides Rails generators core. == Download -- cgit v1.2.3 From 827a0fee07eff7ca35ecdf5ca650f2094ad4825a Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sat, 27 Aug 2011 03:55:01 -0700 Subject: use sdoc to generate the API --- Gemfile | 2 +- Rakefile | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index e11514d5e6..f0880926a3 100644 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,7 @@ gem "mocha", ">= 0.9.8" group :doc do gem "rdoc", "~> 3.4" - gem "horo", "= 1.0.3" + gem "sdoc", "~> 0.3" gem "RedCloth", "~> 4.2" if RUBY_VERSION < "1.9.3" gem "w3c_validators" end diff --git a/Rakefile b/Rakefile index 4cf01cf063..ae857036c5 100755 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,7 @@ #!/usr/bin/env rake require 'rdoc/task' +require 'sdoc' require 'net/http' $:.unshift File.expand_path('..', __FILE__) @@ -89,7 +90,8 @@ RDoc::Task.new do |rdoc| rdoc.rdoc_dir = 'doc/rdoc' rdoc.title = "Ruby on Rails Documentation" - rdoc.options << '-f' << 'horo' + rdoc.options << '-f' << 'sdoc' + rdoc.options << '-T' << 'rails' rdoc.options << '-c' << 'utf-8' rdoc.options << '-m' << RDOC_MAIN -- cgit v1.2.3 From 1606b6c7e4af5ebc0bc705f3c4e4ea63b038ef14 Mon Sep 17 00:00:00 2001 From: Jared Tame Date: Tue, 23 Aug 2011 02:26:55 -0700 Subject: fixed 500 error message which is misleading by suggesting all rails apps have exception notifications by default --- railties/lib/rails/generators/rails/app/templates/public/500.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/app/templates/public/500.html b/railties/lib/rails/generators/rails/app/templates/public/500.html index b80307fc16..b8e4d7c721 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/500.html +++ b/railties/lib/rails/generators/rails/app/templates/public/500.html @@ -20,7 +20,7 @@

We're sorry, but something went wrong.

-

We've been notified about this issue and we'll take a look at it shortly.

+

If you believe you've seen this page in error, please notify the site owner.

-- cgit v1.2.3 From 5acbc19f30b6d27ea9b131aa75bb23643d216088 Mon Sep 17 00:00:00 2001 From: Teng Siong Ong Date: Sat, 27 Aug 2011 14:31:24 -0500 Subject: remove misleading line on 500 error page. --- railties/lib/rails/generators/rails/app/templates/public/500.html | 1 - 1 file changed, 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/app/templates/public/500.html b/railties/lib/rails/generators/rails/app/templates/public/500.html index b8e4d7c721..f3648a0dbc 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/500.html +++ b/railties/lib/rails/generators/rails/app/templates/public/500.html @@ -20,7 +20,6 @@

We're sorry, but something went wrong.

-

If you believe you've seen this page in error, please notify the site owner.

-- cgit v1.2.3 From b5f68cc6fe70490367c5c144e933a87feb5df966 Mon Sep 17 00:00:00 2001 From: Dimitar Dimitrov Date: Fri, 26 Aug 2011 18:34:57 +0300 Subject: Fixed typos and made minor changes in the Plugins guide. --- railties/guides/source/plugins.textile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/railties/guides/source/plugins.textile b/railties/guides/source/plugins.textile index d3f9783fa6..e8bdfa7f1c 100644 --- a/railties/guides/source/plugins.textile +++ b/railties/guides/source/plugins.textile @@ -290,7 +290,7 @@ You can then return to the root directory (+cd ../..+) of your plugin and rerun
-Getting closer...now we will implement the code of the acts_as_yaffle method to make the tests pass. +Getting closer... Now we will implement the code of the acts_as_yaffle method to make the tests pass. # yaffle/lib/yaffle/acts_as_yaffle.rb @@ -322,7 +322,7 @@ When you run +rake+ you should see the tests all pass: h4. Add an Instance Method -This plugin will add a method named 'squawk' to any Active Record objects that call 'acts_as_yaffle'. The 'squawk' +This plugin will add a method named 'squawk' to any Active Record object that calls 'acts_as_yaffle'. The 'squawk' method will simply set the value of one of the fields in the database. To start out, write a failing test that shows the behavior you'd like: @@ -347,7 +347,7 @@ class ActsAsYaffleTest < Test::Unit::TestCase assert_equal "squawk! Hello World", hickwall.last_squawk end - def test_wickwalls_squawk_should_populate_last_tweeted_at + def test_wickwalls_squawk_should_populate_last_tweet wickwall = Wickwall.new wickwall.squawk("Hello World") assert_equal "squawk! Hello World", wickwall.last_tweet @@ -355,7 +355,7 @@ class ActsAsYaffleTest < Test::Unit::TestCase end -Run the test to make sure the last two tests fail the an error that contains "NoMethodError: undefined method `squawk'", +Run the test to make sure the last two tests fail with an error that contains "NoMethodError: undefined method `squawk'", then update 'acts_as_yaffle.rb' to look like this: @@ -400,11 +400,11 @@ the creation of generators can be found in the "Generators Guide":generators.htm h3. Publishing your Gem -Gem plugins in progress can be easily be shared from any Git repository. To share the Yaffle gem with others, simply -commit the code to a Git repository (like Github) and add a line to the Gemfile of the any application: +Gem plugins currently in development can easily be shared from any Git repository. To share the Yaffle gem with others, simply +commit the code to a Git repository (like Github) and add a line to the Gemfile of the application in question: -gem 'yaffle', :git => 'git://github.com/yaffle_watcher/yaffle.git' +gem 'yaffle', :git => 'git://github.com/yaffle_watcher/yaffle.git' After running +bundle install+, your gem functionality will be available to the application. @@ -426,12 +426,12 @@ require 'yaffle' You can test this by changing to the Rails application that you added the plugin to and starting a rails console. Once in the -console we can check to see if the String has an instance method of to_squawk. +console we can check to see if the String has an instance method to_squawk: $ cd my_app $ rails console -$ String.instance_methods.sort +$ "Rails plugins are easy!".to_squawk You can also remove the .gemspec, Gemfile and Gemfile.lock files as they will no longer be needed. @@ -445,9 +445,9 @@ The first step is to update the README file with detailed information about how * Your name * How to install * How to add the functionality to the app (several examples of common use cases) -* Warning, gotchas or tips that might help save users time +* Warnings, gotchas or tips that might help users and save them time -Once your README is solid, go through and add rdoc comments to all of the methods that developers will use. It's also customary to add '#:nodoc:' comments to those parts of the code that are not part of the public api. +Once your README is solid, go through and add rdoc comments to all of the methods that developers will use. It's also customary to add '#:nodoc:' comments to those parts of the code that are not included in the public api. Once your comments are good to go, navigate to your plugin directory and run: -- cgit v1.2.3 From 8526f727cfadb49e629e7ac3a0bbcbf9a89ec3cd Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Sun, 28 Aug 2011 02:25:54 +0530 Subject: doc fixes --- README.rdoc | 6 +++--- actionpack/lib/action_controller/metal/params_wrapper.rb | 16 ++++++++-------- actionpack/lib/action_dispatch/routing/url_for.rb | 12 ++++++++---- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/README.rdoc b/README.rdoc index f0aa962272..9f017cd05f 100644 --- a/README.rdoc +++ b/README.rdoc @@ -8,12 +8,12 @@ into three layers, each with a specific responsibility. The View layer is composed of "templates" that are responsible for providing appropriate representations of your application's resources. Templates -can come in a variety of formats, but most view templates are HTML with embedded Ruby +can come in a variety of formats, but most view templates are \HTML with embedded Ruby code (.erb files). The Model layer represents your domain model (such as Account, Product, Person, Post) and encapsulates the business logic that is specific to your application. In Rails, -database-backed model classes are derived from ActiveRecord::Base. ActiveRecord allows +database-backed model classes are derived from ActiveRecord::Base. Active Record allows you to present the data from database rows as objects and embellish these data objects with business logic methods. Although most Rails models are backed by a database, models can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as @@ -21,7 +21,7 @@ provided by the ActiveModel module. You can read more about Active Record in its {README}[link:/rails/rails/blob/master/activerecord/README.rdoc]. The Controller layer is responsible for handling incoming HTTP requests and providing a -suitable response. Usually this means returning HTML, but Rails controllers can also +suitable response. Usually this means returning \HTML, but Rails controllers can also generate XML, JSON, PDFs, mobile-specific views, and more. Controllers manipulate models and render view templates in order to generate the appropriate HTTP response. diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index f24203db3a..6acbb23907 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -6,30 +6,30 @@ require 'active_support/core_ext/module/anonymous' require 'action_dispatch/http/mime_types' module ActionController - # Wraps parameters hash into nested hash. This will allow client to submit - # POST request without having to specify a root element in it. + # Wraps the parameters hash into a nested hash. This will allow clients to submit + # POST requests without having to specify any root elements. # # This functionality is enabled in +config/initializers/wrap_parameters.rb+ - # and can be customized. If you are upgrading to Rails 3.1, this file will + # and can be customized. If you are upgrading to \Rails 3.1, this file will # need to be created for the functionality to be enabled. # # You could also turn it on per controller by setting the format array to - # non-empty array: + # a non-empty array: # # class UsersController < ApplicationController # wrap_parameters :format => [:json, :xml] # end # - # If you enable +ParamsWrapper+ for +:json+ format. Instead of having to + # If you enable +ParamsWrapper+ for +:json+ format, instead of having to # send JSON parameters like this: # # {"user": {"name": "Konata"}} # - # You can now just send a parameters like this: + # You can send parameters like this: # # {"name": "Konata"} # - # And it will be wrapped into a nested hash with the key name matching + # And it will be wrapped into a nested hash with the key name matching the # controller's name. For example, if you're posting to +UsersController+, # your new +params+ hash will look like this: # @@ -81,7 +81,7 @@ module ActionController # # ==== Examples # wrap_parameters :format => :xml - # # enables the parmeter wrapper for XML format + # # enables the parameter wrapper for XML format # # wrap_parameters :person # # wraps parameters into +params[:person]+ hash diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index de14113c51..30048cd48a 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -131,10 +131,14 @@ module ActionDispatch # # Examples: # - # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :port => '8080' # => 'http://somehost.org:8080/tasks/testing' - # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok' - # url_for :controller => 'tasks', :action => 'testing', :trailing_slash => true # => 'http://somehost.org/tasks/testing/' - # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33' + # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :port => '8080' + # # => 'http://somehost.org:8080/tasks/testing' + # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :anchor => 'ok', :only_path => true + # # => '/tasks/testing#ok' + # url_for :controller => 'tasks', :action => 'testing', :trailing_slash => true + # # => 'http://somehost.org/tasks/testing/' + # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :number => '33' + # # => 'http://somehost.org/tasks/testing?number=33' def url_for(options = nil) case options when String -- cgit v1.2.3 From bb4dedbc2cc7b96b95bf4519f56ed9624949a7ef Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sat, 27 Aug 2011 15:34:33 -0700 Subject: deletes spurious arrow --- actionpack/lib/action_controller/metal/url_for.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index 08132b1900..0b40b1fc4c 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -18,7 +18,7 @@ # @url = root_path # named route from the application. # end # end -# => +# module ActionController module UrlFor extend ActiveSupport::Concern -- cgit v1.2.3 From 24674b344864298135f4f1cecca1214c6b9ddf42 Mon Sep 17 00:00:00 2001 From: jbbarth Date: Sun, 28 Aug 2011 06:02:15 +0200 Subject: Fixed bad options order in ActiveRecord::Migration::CommandRecorder#invert_rename_index --- activerecord/lib/active_record/migration/command_recorder.rb | 2 +- activerecord/test/cases/migration/command_recorder_test.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb index 2eeff7e36f..ffee5a081a 100644 --- a/activerecord/lib/active_record/migration/command_recorder.rb +++ b/activerecord/lib/active_record/migration/command_recorder.rb @@ -71,7 +71,7 @@ module ActiveRecord end def invert_rename_index(args) - [:rename_index, args.reverse] + [:rename_index, [args.first] + args.last(2).reverse] end def invert_rename_column(args) diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb index 36007255fa..d108b456f0 100644 --- a/activerecord/test/cases/migration/command_recorder_test.rb +++ b/activerecord/test/cases/migration/command_recorder_test.rb @@ -104,9 +104,9 @@ module ActiveRecord end def test_invert_rename_index - @recorder.record :rename_index, [:old, :new] + @recorder.record :rename_index, [:table, :old, :new] rename = @recorder.inverse.first - assert_equal [:rename_index, [:new, :old]], rename + assert_equal [:rename_index, [:table, :new, :old]], rename end def test_invert_add_timestamps -- cgit v1.2.3 From 62a61add7e7555aae80660f3694e09624be192f3 Mon Sep 17 00:00:00 2001 From: Daniel Schierbeck Date: Sun, 28 Aug 2011 07:24:58 +0300 Subject: Refactor ActionDispatch::Http::UploadedFile --- actionpack/lib/action_dispatch/http/upload.rb | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index a15ad28f16..94fa747a79 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -11,24 +11,13 @@ module ActionDispatch raise(ArgumentError, ':tempfile is required') unless @tempfile end - def open - @tempfile.open - end - - def path - @tempfile.path - end - def read(*args) @tempfile.read(*args) end - def rewind - @tempfile.rewind - end - - def size - @tempfile.size + # Delegate these methods to the tempfile. + [:open, :path, :rewind, :size].each do |method| + class_eval "def #{method}; @tempfile.#{method}; end" end private -- cgit v1.2.3 From b4ff82a79177757509cefa2b103ae56d84b84f6d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 28 Aug 2011 14:15:51 -0700 Subject: clear and disable query cache when an exception is raised from called middleware --- activerecord/lib/active_record/query_cache.rb | 6 ++++++ activerecord/test/cases/query_cache_test.rb | 28 ++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb index e485901440..10c0dc6f2a 100644 --- a/activerecord/lib/active_record/query_cache.rb +++ b/activerecord/lib/active_record/query_cache.rb @@ -61,6 +61,12 @@ module ActiveRecord status, headers, body = @app.call(env) [status, headers, BodyProxy.new(old, body)] + rescue Exception => e + ActiveRecord::Base.connection.clear_query_cache + unless old + ActiveRecord::Base.connection.disable_query_cache! + end + raise e end end end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index ad17f6f83a..fd5e69935e 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -13,6 +13,32 @@ class QueryCacheTest < ActiveRecord::TestCase ActiveRecord::Base.connection.disable_query_cache! end + def test_exceptional_middleware_clears_and_disables_cache_on_error + assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache off' + + mw = ActiveRecord::QueryCache.new lambda { |env| + Task.find 1 + Task.find 1 + assert_equal 1, ActiveRecord::Base.connection.query_cache.length + raise "lol borked" + } + assert_raises(RuntimeError) { mw.call({}) } + + assert_equal 0, ActiveRecord::Base.connection.query_cache.length + assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache off' + end + + def test_exceptional_middleware_leaves_enabled_cache_alone + ActiveRecord::Base.connection.enable_query_cache! + + mw = ActiveRecord::QueryCache.new lambda { |env| + raise "lol borked" + } + assert_raises(RuntimeError) { mw.call({}) } + + assert ActiveRecord::Base.connection.query_cache_enabled, 'cache off' + end + def test_middleware_delegates called = false mw = ActiveRecord::QueryCache.new lambda { |env| @@ -213,4 +239,4 @@ class QueryCacheBodyProxyTest < ActiveRecord::TestCase assert_equal proxy.to_path, "/path" end -end \ No newline at end of file +end -- cgit v1.2.3 From 49af31eada829148bc7b4053fa56692fa8527928 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 28 Aug 2011 19:04:38 -0300 Subject: Bump rack-cache, rack-test, rack-mount and sprockets up --- actionpack/actionpack.gemspec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 02758148c0..59d5bbc5ed 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -18,13 +18,13 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', version) s.add_dependency('activemodel', version) - s.add_dependency('rack-cache', '~> 1.0.2') + s.add_dependency('rack-cache', '~> 1.0.3') s.add_dependency('builder', '~> 3.0.0') s.add_dependency('i18n', '~> 0.6') s.add_dependency('rack', '~> 1.3.2') - s.add_dependency('rack-test', '~> 0.6.0') - s.add_dependency('rack-mount', '~> 0.8.1') - s.add_dependency('sprockets', '~> 2.0.0.beta.14') + s.add_dependency('rack-test', '~> 0.6.1') + s.add_dependency('rack-mount', '~> 0.8.2') + s.add_dependency('sprockets', '~> 2.0.0.beta.15') s.add_dependency('erubis', '~> 2.7.0') s.add_development_dependency('tzinfo', '~> 0.3.29') -- cgit v1.2.3 From d63688d9e69d2440a35ab89c9b21866272a74fe3 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 28 Aug 2011 16:31:04 -0700 Subject: fixing typo --- activerecord/test/cases/query_cache_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index fd5e69935e..e3ad0cad90 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -36,7 +36,7 @@ class QueryCacheTest < ActiveRecord::TestCase } assert_raises(RuntimeError) { mw.call({}) } - assert ActiveRecord::Base.connection.query_cache_enabled, 'cache off' + assert ActiveRecord::Base.connection.query_cache_enabled, 'cache on' end def test_middleware_delegates -- cgit v1.2.3 From 871696a01af853f10a33c4ff53f6d6ed795144b7 Mon Sep 17 00:00:00 2001 From: Igor Zubkov Date: Sun, 28 Aug 2011 23:08:06 +0300 Subject: Documentation fixes --- railties/guides/source/asset_pipeline.textile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 4fbdda4c07..554246acb3 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -29,7 +29,7 @@ It is recommended that you use the defaults for all new apps. h4. Main Features -The first feature of the pipeline is to concatenate assets. This is important in a production environment, as it reduces the number of requests that a browser must make to render a web page. While Rails already has a feature to concatenate these types of assetsi -- by placing +:cache => true+ at the end of tags such as +javascript_include_tag+ and +stylesheet_link_tag+ -- many people do not use it. +The first feature of the pipeline is to concatenate assets. This is important in a production environment, as it reduces the number of requests that a browser must make to render a web page. While Rails already has a feature to concatenate these types of assets -- by placing +:cache => true+ at the end of tags such as +javascript_include_tag+ and +stylesheet_link_tag+ -- many people do not use it. The default behavior in Rails 3.1 and onward is to concatenate all files into one master file each for JS and CSS. However, you can separate files or groups of files if required (see below). In production, an MD5 fingerprint is inserted into each filename so that the file is cached by the web browser but can be invalidated if the fingerprint is altered. @@ -133,7 +133,7 @@ Otherwise, Sprockets looks through the available paths until it finds a file tha If you want to use a "css data URI":http://en.wikipedia.org/wiki/Data_URI_scheme -- a method of embedding the image data directly into the CSS file -- you can use the +asset_data_uri+ helper. -#logo { background: url(<%= asset_data_uri 'logo.png' %>) +#logo { background: url(<%= asset_data_uri 'logo.png' %>) } This inserts a correctly-formatted data URI into the CSS source. @@ -143,7 +143,7 @@ h5. CSS and ERB If you add an +erb+ extension to a CSS asset, making it something such as +application.css.erb+, then you can use the +asset_path+ helper in your CSS rules: -.class{background-image:<%= asset_path 'image.png' %>} +.class { background-image: <%= asset_path 'image.png' %> } This writes the path to the particular asset being referenced. In this example, it would make sense to have an image in one of the asset load paths, such as +app/assets/images/image.png+, which would be referenced here. If this image is already available in +public/assets+ as a fingerprinted file, then that path is referenced. @@ -282,7 +282,7 @@ Rails comes bundled with a rake task to compile the manifests to files on disc. The rake task is: -rake assets:precompile +bundle exec rake assets:precompile Capistrano (v2.8.0+) has a recipe to handle this in deployment. Add the following line to +Capfile+: -- cgit v1.2.3 From 734792aaaab07cd7b4340b76ae66be3533088b11 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 28 Aug 2011 16:41:15 -0700 Subject: Merge pull request #2723 from guilleiguaran/3-1-0-changelogs Update changelogs for Rails 3.1.0 --- actionpack/CHANGELOG | 2 ++ activesupport/CHANGELOG | 12 ++++++++++++ railties/CHANGELOG | 13 +++++++++++++ 3 files changed, 27 insertions(+) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index b1286d04cc..6b654e149e 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -30,6 +30,8 @@ *Rails 3.1.0 (unreleased)* +* Param values are `paramified` in controller tests. [David Chelimsky] + * x_sendfile_header now defaults to nil and config/environments/production.rb doesn't set a particular value for it. This allows servers to set it through X-Sendfile-Type. [Santiago Pastorino] * The submit form helper does not generate an id "object_name_id" anymore. [fbrusatti] diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 1697d346b5..3508ec0f34 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -20,6 +20,18 @@ Also, in 1.8 the ideographic space U+3000 is considered to be whitespace. [Akira *Rails 3.1.0 (unreleased)* +* ActiveSupport::Dependencies#load and ActiveSupport::Dependencies#require now +return the value from `super` [Aaron Patterson] + +* Fixed ActiveSupport::Gzip to work properly in Ruby 1.8 [Guillermo Iguaran] + +* Kernel.require_library_or_gem was deprecated and will be removed in Rails 3.2.0 [Josh Kalderimis] + +* ActiveSupport::Duration#duplicable? was fixed for Ruby 1.8 [thedarkone] + +* ActiveSupport::BufferedLogger set log encoding to BINARY, but still use text +mode to output portable newlines. [fxn] + * ActiveSupport::Dependencies now raises NameError if it finds an existing constant in load_missing_constant. This better reflects the nature of the error which is usually caused by calling constantize on a nested constant. [Andrew White] * Deprecated ActiveSupport::SecureRandom in favour of SecureRandom from the standard library [Jon Leighton] diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 76453f4e9a..6ed76974b4 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -12,6 +12,19 @@ *Rails 3.1.0 (unreleased)* +* The default database schema file is written as UTF-8. [Aaron Patterson] + +* Generated apps with --dev or --edge flags depend on git versions of +sass-rails and coffee-rails. [Santiago Pastorino] + +* Rack::Sendfile middleware is used only if x_sendfile_header is present. [Santiago Pastorino] + +* Add JavaScript Runtime name to the Rails Info properties. [DHH] + +* Make pp enabled by default in Rails console. [Akira Matsuda] + +* Add alias `r` for rails runner. [Jordi Romero] + * Make sprockets/railtie require explicit and add --skip-sprockets to app generator [José Valim] * Added Rails.groups that automatically handles Rails.env and ENV["RAILS_GROUPS"] [José Valim] -- cgit v1.2.3 From 381904d26b601c89e2a8496612a7c76db8ae9359 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Sun, 28 Aug 2011 19:00:58 -0500 Subject: Avoid extra recursive call in Sprockets helpers --- actionpack/lib/sprockets/helpers/rails_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 7ad4d30d9e..7a2bf8bef6 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -26,7 +26,7 @@ module Sprockets sources.collect do |source| if debug && asset = asset_paths.asset_for(source, 'js') asset.to_a.map { |dep| - javascript_include_tag(dep, options.merge({ :debug => false, :body => true })) + super(dep.to_s, { :src => asset_path(dep, 'js', true) }.merge!(options)) } else super(source.to_s, { :src => asset_path(source, 'js', body) }.merge!(options)) @@ -42,7 +42,7 @@ module Sprockets sources.collect do |source| if debug && asset = asset_paths.asset_for(source, 'css') asset.to_a.map { |dep| - stylesheet_link_tag(dep, options.merge({ :debug => false, :body => true })) + super(dep.to_s, { :href => asset_path(dep, 'css', true, :request) }.merge!(options)) } else super(source.to_s, { :href => asset_path(source, 'css', body, :request) }.merge!(options)) -- cgit v1.2.3 From a720243961ede01263f247842326d9d3e59b6200 Mon Sep 17 00:00:00 2001 From: Daniel Schierbeck Date: Mon, 29 Aug 2011 04:15:15 +0300 Subject: Split long string into multiple shorter ones This makes the code more readable. --- actionpack/lib/action_dispatch/middleware/session/abstract_store.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index a70d814749..6bcf099d2c 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -59,7 +59,10 @@ module ActionDispatch # Note that the regexp does not allow $1 to end with a ':' $1.constantize rescue LoadError, NameError => const_error - raise ActionDispatch::Session::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n" + raise ActionDispatch::Session::SessionRestoreError, + "Session contains objects whose class definition isn't available.\n" + + "Remember to require the classes for all objects kept in the session.\n" + + "(Original exception: #{const_error.message} [#{const_error.class}])\n" end retry else -- cgit v1.2.3 From 5766539342426e956980bf6f54ef99600cbfc33e Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 25 Aug 2011 22:28:46 +0100 Subject: Create an AbstractMysqlAdapter to abstract the common code between MysqlAdapter and Mysql2Adapter. --- .../connection_adapters/abstract_mysql_adapter.rb | 552 +++++++++++++++++ .../connection_adapters/mysql2_adapter.rb | 584 ++---------------- .../connection_adapters/mysql_adapter.rb | 667 +++------------------ .../cases/adapters/mysql/active_schema_test.rb | 8 +- activerecord/test/cases/column_definition_test.rb | 32 +- 5 files changed, 726 insertions(+), 1117 deletions(-) create mode 100644 activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb new file mode 100644 index 0000000000..72cf490d7e --- /dev/null +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -0,0 +1,552 @@ +require 'active_support/core_ext/object/blank' + +module ActiveRecord + module ConnectionAdapters + class AbstractMysqlAdapter < AbstractAdapter + class Column < ConnectionAdapters::Column + def extract_default(default) + if sql_type =~ /blob/i || type == :text + if default.blank? + return null ? nil : '' + else + raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}" + end + elsif missing_default_forged_as_empty_string?(default) + nil + else + super + end + end + + def has_default? + return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns + super + end + + private + + def extract_limit(sql_type) + case sql_type + when /blob|text/i + case sql_type + when /tiny/i + 255 + when /medium/i + 16777215 + when /long/i + 2147483647 # mysql only allows 2^31-1, not 2^32-1, somewhat inconsistently with the tiny/medium/normal cases + else + super # we could return 65535 here, but we leave it undecorated by default + end + when /^bigint/i; 8 + when /^int/i; 4 + when /^mediumint/i; 3 + when /^smallint/i; 2 + when /^tinyint/i; 1 + else + super + end + end + + # MySQL misreports NOT NULL column default when none is given. + # We can't detect this for columns which may have a legitimate '' + # default (string) but we can for others (integer, datetime, boolean, + # and the rest). + # + # Test whether the column has default '', is not null, and is not + # a type allowing default ''. + def missing_default_forged_as_empty_string?(default) + type != :string && !null && default == '' + end + end + + ## + # :singleton-method: + # By default, the MysqlAdapter will consider all columns of type tinyint(1) + # as boolean. If you wish to disable this emulation (which was the default + # behavior in versions 0.13.1 and earlier) you can add the following line + # to your application.rb file: + # + # ActiveRecord::ConnectionAdapters::Mysql[2]Adapter.emulate_booleans = false + class_attribute :emulate_booleans + self.emulate_booleans = true + + LOST_CONNECTION_ERROR_MESSAGES = [ + "Server shutdown in progress", + "Broken pipe", + "Lost connection to MySQL server during query", + "MySQL server has gone away" ] + + QUOTED_TRUE, QUOTED_FALSE = '1', '0' + + NATIVE_DATABASE_TYPES = { + :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY", + :string => { :name => "varchar", :limit => 255 }, + :text => { :name => "text" }, + :integer => { :name => "int", :limit => 4 }, + :float => { :name => "float" }, + :decimal => { :name => "decimal" }, + :datetime => { :name => "datetime" }, + :timestamp => { :name => "datetime" }, + :time => { :name => "time" }, + :date => { :name => "date" }, + :binary => { :name => "blob" }, + :boolean => { :name => "tinyint", :limit => 1 } + } + + # FIXME: Make the first parameter more similar for the two adapters + def initialize(connection, logger, connection_options, config) + super(connection, logger) + @connection_options, @config = connection_options, config + @quoted_column_names, @quoted_table_names = {}, {} + end + + def self.visitor_for(pool) # :nodoc: + Arel::Visitors::MySQL.new(pool) + end + + def adapter_name #:nodoc: + self.class::ADAPTER_NAME + end + + # Returns true, since this connection adapter supports migrations. + def supports_migrations? + true + end + + def supports_primary_key? + true + end + + # Returns true, since this connection adapter supports savepoints. + def supports_savepoints? + true + end + + def native_database_types + NATIVE_DATABASE_TYPES + end + + # HELPER METHODS =========================================== + + # The two drivers have slightly different ways of yielding hashes of results, so + # this method must be implemented to provide a uniform interface. + def each_hash(result) # :nodoc: + raise NotImplementedError + end + + # Overridden by the adapters to instantiate their specific Column type. + def new_column(field, default, type, null) # :nodoc: + Column.new(field, default, type, null) + end + + # Must return the Mysql error number from the exception, if the exception has an + # error number. + def error_number(exception) # :nodoc: + raise NotImplementedError + end + + # QUOTING ================================================== + + def quote(value, column = nil) + if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary) + s = column.class.string_to_binary(value).unpack("H*")[0] + "x'#{s}'" + elsif value.kind_of?(BigDecimal) + value.to_s("F") + else + super + end + end + + def quote_column_name(name) #:nodoc: + @quoted_column_names[name] ||= "`#{name.to_s.gsub('`', '``')}`" + end + + def quote_table_name(name) #:nodoc: + @quoted_table_names[name] ||= quote_column_name(name).gsub('.', '`.`') + end + + def quoted_true + QUOTED_TRUE + end + + def quoted_false + QUOTED_FALSE + end + + # REFERENTIAL INTEGRITY ==================================== + + def disable_referential_integrity(&block) #:nodoc: + old = select_value("SELECT @@FOREIGN_KEY_CHECKS") + + begin + update("SET FOREIGN_KEY_CHECKS = 0") + yield + ensure + update("SET FOREIGN_KEY_CHECKS = #{old}") + end + end + + # DATABASE STATEMENTS ====================================== + + # Executes the SQL statement in the context of this connection. + def execute(sql, name = nil) + if name == :skip_logging + @connection.query(sql) + else + log(sql, name) { @connection.query(sql) } + end + rescue ActiveRecord::StatementInvalid => exception + if exception.message.split(":").first =~ /Packets out of order/ + raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings." + else + raise + end + end + + # MysqlAdapter has to free a result after using it, so we use this method to write + # stuff in a abstract way without concerning ourselves about whether it needs to be + # explicitly freed or not. + def execute_and_free(sql, name = nil) #:nodoc: + yield execute(sql, name) + end + + def update_sql(sql, name = nil) #:nodoc: + super + @connection.affected_rows + end + + def begin_db_transaction + execute "BEGIN" + rescue Exception + # Transactions aren't supported + end + + def commit_db_transaction #:nodoc: + execute "COMMIT" + rescue Exception + # Transactions aren't supported + end + + def rollback_db_transaction #:nodoc: + execute "ROLLBACK" + rescue Exception + # Transactions aren't supported + end + + def create_savepoint + execute("SAVEPOINT #{current_savepoint_name}") + end + + def rollback_to_savepoint + execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}") + end + + def release_savepoint + execute("RELEASE SAVEPOINT #{current_savepoint_name}") + end + + # In the simple case, MySQL allows us to place JOINs directly into the UPDATE + # query. However, this does not allow for LIMIT, OFFSET and ORDER. To support + # these, we must use a subquery. However, MySQL is too stupid to create a + # temporary table for this automatically, so we have to give it some prompting + # in the form of a subsubquery. Ugh! + def join_to_update(update, select) #:nodoc: + if select.limit || select.offset || select.orders.any? + subsubselect = select.clone + subsubselect.projections = [update.key] + + subselect = Arel::SelectManager.new(select.engine) + subselect.project Arel.sql(update.key.name) + subselect.from subsubselect.as('__active_record_temp') + + update.where update.key.in(subselect) + else + update.table select.source + update.wheres = select.constraints + end + end + + # SCHEMA STATEMENTS ======================================== + + def structure_dump #:nodoc: + if supports_views? + sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'" + else + sql = "SHOW TABLES" + end + + select_all(sql).map do |table| + table.delete('Table_type') + sql = "SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}" + exec_without_stmt(sql).first['Create Table'] + ";\n\n" + end.join("") + end + + # Drops the database specified on the +name+ attribute + # and creates it again using the provided +options+. + def recreate_database(name, options = {}) + drop_database(name) + create_database(name, options) + end + + # Create a new MySQL database with optional :charset and :collation. + # Charset defaults to utf8. + # + # Example: + # create_database 'charset_test', :charset => 'latin1', :collation => 'latin1_bin' + # create_database 'matt_development' + # create_database 'matt_development', :charset => :big5 + def create_database(name, options = {}) + if options[:collation] + execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}` COLLATE `#{options[:collation]}`" + else + execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}`" + end + end + + # Drops a MySQL database. + # + # Example: + # drop_database('sebastian_development') + def drop_database(name) #:nodoc: + execute "DROP DATABASE IF EXISTS `#{name}`" + end + + def current_database + select_value 'SELECT DATABASE() as db' + end + + # Returns the database character set. + def charset + show_variable 'character_set_database' + end + + # Returns the database collation strategy. + def collation + show_variable 'collation_database' + end + + def tables(name = nil, database = nil) #:nodoc: + sql = ["SHOW TABLES", database].compact.join(' IN ') + + execute_and_free(sql, 'SCHEMA') do |result| + result.collect { |field| field.first } + end + end + + def table_exists?(name) + return true if super + + name = name.to_s + schema, table = name.split('.', 2) + + unless table # A table was provided without a schema + table = schema + schema = nil + end + + tables(nil, schema).include? table + end + + # Returns an array of indexes for the given table. + def indexes(table_name, name = nil) #:nodoc: + indexes = [] + current_index = nil + execute_and_free("SHOW KEYS FROM #{quote_table_name(table_name)}", 'SCHEMA') do |result| + each_hash(result) do |row| + if current_index != row[:Key_name] + next if row[:Key_name] == 'PRIMARY' # skip the primary key + current_index = row[:Key_name] + indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], []) + end + + indexes.last.columns << row[:Column_name] + indexes.last.lengths << row[:Sub_part] + end + end + + indexes + end + + # Returns an array of +Column+ objects for the table specified by +table_name+. + def columns(table_name, name = nil)#:nodoc: + sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}" + execute_and_free(sql, 'SCHEMA') do |result| + each_hash(result).map do |field| + new_column(field[:Field], field[:Default], field[:Type], field[:Null] == "YES") + end + end + end + + def create_table(table_name, options = {}) #:nodoc: + super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB")) + end + + # Renames a table. + # + # Example: + # rename_table('octopuses', 'octopi') + def rename_table(table_name, new_name) + execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}" + end + + def add_column(table_name, column_name, type, options = {}) + execute("ALTER TABLE #{quote_table_name(table_name)} #{add_column_sql(table_name, column_name, type, options)}") + end + + def change_column_default(table_name, column_name, default) + column = column_for(table_name, column_name) + change_column table_name, column_name, column.sql_type, :default => default + end + + def change_column_null(table_name, column_name, null, default = nil) + column = column_for(table_name, column_name) + + unless null || default.nil? + execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") + end + + change_column table_name, column_name, column.sql_type, :null => null + end + + def change_column(table_name, column_name, type, options = {}) #:nodoc: + execute("ALTER TABLE #{quote_table_name(table_name)} #{change_column_sql(table_name, column_name, type, options)}") + end + + def rename_column(table_name, column_name, new_column_name) #:nodoc: + execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_sql(table_name, column_name, new_column_name)}") + end + + # Maps logical Rails types to MySQL-specific data types. + def type_to_sql(type, limit = nil, precision = nil, scale = nil) + return super unless type.to_s == 'integer' + + case limit + when 1; 'tinyint' + when 2; 'smallint' + when 3; 'mediumint' + when nil, 4, 11; 'int(11)' # compatibility with MySQL default + when 5..8; 'bigint' + else raise(ActiveRecordError, "No integer type has byte size #{limit}") + end + end + + def add_column_position!(sql, options) + if options[:first] + sql << " FIRST" + elsif options[:after] + sql << " AFTER #{quote_column_name(options[:after])}" + end + end + + # SHOW VARIABLES LIKE 'name' + def show_variable(name) + variables = select_all("SHOW VARIABLES LIKE '#{name}'") + variables.first['Value'] unless variables.empty? + end + + # Returns a table's primary key and belonging sequence. + def pk_and_sequence_for(table) + execute_and_free("DESCRIBE #{quote_table_name(table)}", 'SCHEMA') do |result| + keys = each_hash(result).select { |row| row[:Key] == 'PRI' }.map { |row| row[:Field] } + keys.length == 1 ? [keys.first, nil] : nil + end + end + + # Returns just a table's primary key + def primary_key(table) + pk_and_sequence = pk_and_sequence_for(table) + pk_and_sequence && pk_and_sequence.first + end + + def case_sensitive_modifier(node) + Arel::Nodes::Bin.new(node) + end + + def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) + where_sql + end + + protected + + def quoted_columns_for_index(column_names, options = {}) + length = options[:length] if options.is_a?(Hash) + + case length + when Hash + column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) } + when Fixnum + column_names.map {|name| "#{quote_column_name(name)}(#{length})"} + else + column_names.map {|name| quote_column_name(name) } + end + end + + def translate_exception(exception, message) + case error_number(exception) + when 1062 + RecordNotUnique.new(message, exception) + when 1452 + InvalidForeignKey.new(message, exception) + else + super + end + end + + def add_column_sql(table_name, column_name, type, options = {}) + add_column_sql = "ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" + add_column_options!(add_column_sql, options) + add_column_position!(add_column_sql, options) + add_column_sql + end + + def change_column_sql(table_name, column_name, type, options = {}) + column = column_for(table_name, column_name) + + unless options_include_default?(options) + options[:default] = column.default + end + + unless options.has_key?(:null) + options[:null] = column.null + end + + change_column_sql = "CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" + add_column_options!(change_column_sql, options) + add_column_position!(change_column_sql, options) + change_column_sql + end + + def rename_column_sql(table_name, column_name, new_column_name) + options = {} + + if column = columns(table_name).find { |c| c.name == column_name.to_s } + options[:default] = column.default + options[:null] = column.null + else + raise ActiveRecordError, "No such column: #{table_name}.#{column_name}" + end + + current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"] + rename_column_sql = "CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}" + add_column_options!(rename_column_sql, options) + rename_column_sql + end + + private + + def supports_views? + version[0] >= 5 + end + + def column_for(table_name, column_name) + unless column = columns(table_name).find { |c| c.name == column_name.to_s } + raise "No such column: #{table_name}.#{column_name}" + end + column + end + end + end +end diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index ef51f5ebca..00d9caa8ee 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -1,4 +1,4 @@ -# encoding: utf-8 +require 'active_record/connection_adapters/abstract_mysql_adapter' gem 'mysql2', '~> 0.3.6' require 'mysql2' @@ -20,31 +20,13 @@ module ActiveRecord end module ConnectionAdapters - class Mysql2IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths) #:nodoc: - end - - class Mysql2Column < Column - BOOL = "tinyint(1)" - def extract_default(default) - if sql_type =~ /blob/i || type == :text - if default.blank? - return null ? nil : '' - else - raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}" - end - elsif missing_default_forged_as_empty_string?(default) - nil - else - super - end - end + class Mysql2Adapter < AbstractMysqlAdapter + class Column < AbstractMysqlAdapter::Column # :nodoc: + BOOL = "tinyint(1)" - def has_default? - return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns - super - end + private - private + # FIXME: Combine with the mysql version and move to abstract adapter def simplified_type(field_type) return :boolean if Mysql2Adapter.emulate_booleans && field_type.downcase.index(BOOL) @@ -56,155 +38,45 @@ module ActiveRecord super end end - - def extract_limit(sql_type) - case sql_type - when /blob|text/i - case sql_type - when /tiny/i - 255 - when /medium/i - 16777215 - when /long/i - 2147483647 # mysql only allows 2^31-1, not 2^32-1, somewhat inconsistently with the tiny/medium/normal cases - else - super # we could return 65535 here, but we leave it undecorated by default - end - when /^bigint/i; 8 - when /^int/i; 4 - when /^mediumint/i; 3 - when /^smallint/i; 2 - when /^tinyint/i; 1 - else - super - end - end - - # MySQL misreports NOT NULL column default when none is given. - # We can't detect this for columns which may have a legitimate '' - # default (string) but we can for others (integer, datetime, boolean, - # and the rest). - # - # Test whether the column has default '', is not null, and is not - # a type allowing default ''. - def missing_default_forged_as_empty_string?(default) - type != :string && !null && default == '' - end - end - - class Mysql2Adapter < AbstractAdapter - cattr_accessor :emulate_booleans - self.emulate_booleans = true + end ADAPTER_NAME = 'Mysql2' - PRIMARY = "PRIMARY" - - LOST_CONNECTION_ERROR_MESSAGES = [ - "Server shutdown in progress", - "Broken pipe", - "Lost connection to MySQL server during query", - "MySQL server has gone away" ] - - QUOTED_TRUE, QUOTED_FALSE = '1', '0' - - NATIVE_DATABASE_TYPES = { - :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY", - :string => { :name => "varchar", :limit => 255 }, - :text => { :name => "text" }, - :integer => { :name => "int", :limit => 4 }, - :float => { :name => "float" }, - :decimal => { :name => "decimal" }, - :datetime => { :name => "datetime" }, - :timestamp => { :name => "datetime" }, - :time => { :name => "time" }, - :date => { :name => "date" }, - :binary => { :name => "blob" }, - :boolean => { :name => "tinyint", :limit => 1 } - } def initialize(connection, logger, connection_options, config) - super(connection, logger) - @connection_options, @config = connection_options, config - @quoted_column_names, @quoted_table_names = {}, {} + super configure_connection end - def self.visitor_for(pool) # :nodoc: - Arel::Visitors::MySQL.new(pool) - end - - def adapter_name - ADAPTER_NAME - end - - # Returns true, since this connection adapter supports migrations. - def supports_migrations? - true - end - - def supports_primary_key? - true - end - - # Returns true, since this connection adapter supports savepoints. - def supports_savepoints? - true - end - - def native_database_types - NATIVE_DATABASE_TYPES - end + # HELPER METHODS =========================================== - # QUOTING ================================================== - - def quote(value, column = nil) - if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary) - s = column.class.string_to_binary(value).unpack("H*")[0] - "x'#{s}'" - elsif value.kind_of?(BigDecimal) - value.to_s("F") + def each_hash(result) # :nodoc: + if block_given? + result.each(:as => :hash, :symbolize_keys => true) do |row| + yield row + end else - super + to_enum(:each_hash, result) end end - def quote_column_name(name) #:nodoc: - @quoted_column_names[name] ||= "`#{name.to_s.gsub('`', '``')}`" + def new_column(field, default, type, null) # :nodoc: + Column.new(field, default, type, null) end - def quote_table_name(name) #:nodoc: - @quoted_table_names[name] ||= quote_column_name(name).gsub('.', '`.`') + def error_number(exception) + exception.error_number if exception.respond_to?(:error_number) end + # QUOTING ================================================== + def quote_string(string) @connection.escape(string) end - def quoted_true - QUOTED_TRUE - end - - def quoted_false - QUOTED_FALSE - end - def substitute_at(column, index) Arel.sql "\0" end - # REFERENTIAL INTEGRITY ==================================== - - def disable_referential_integrity(&block) #:nodoc: - old = select_value("SELECT @@FOREIGN_KEY_CHECKS") - - begin - update("SET FOREIGN_KEY_CHECKS = 0") - yield - ensure - update("SET FOREIGN_KEY_CHECKS = #{old}") - end - end - # CONNECTION MANAGEMENT ==================================== def active? @@ -217,11 +89,6 @@ module ActiveRecord connect end - # this is set to true in 2.3, but we don't want it to be - def requires_reloading? - false - end - # Disconnects from the database if already connected. # Otherwise, this method does nothing. def disconnect! @@ -277,17 +144,22 @@ module ActiveRecord # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been # made since we established the connection @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone - if name == :skip_logging - @connection.query(sql) - else - log(sql, name) { @connection.query(sql) } - end - rescue ActiveRecord::StatementInvalid => exception - if exception.message.split(":").first =~ /Packets out of order/ - raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings." - else - raise - end + + super + end + + def exec_query(sql, name = 'SQL', binds = []) + result = execute(sql, name) + ActiveRecord::Result.new(result.fields, result.to_a) + end + + alias exec_without_stmt exec_query + + # Returns an array of record hashes with the column names as keys and + # column values as values. + def select(sql, name = nil, binds = []) + binds = binds.dup + exec_query(sql.gsub("\0") { quote(*binds.shift.reverse) }, name).to_a end def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) @@ -316,379 +188,35 @@ module ActiveRecord @connection.last_id end - def update_sql(sql, name = nil) - super - @connection.affected_rows - end - - def begin_db_transaction - execute "BEGIN" - rescue Exception - # Transactions aren't supported - end - - def commit_db_transaction - execute "COMMIT" - rescue Exception - # Transactions aren't supported - end - - def rollback_db_transaction - execute "ROLLBACK" - rescue Exception - # Transactions aren't supported - end - - def create_savepoint - execute("SAVEPOINT #{current_savepoint_name}") - end - - def rollback_to_savepoint - execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}") - end - - def release_savepoint - execute("RELEASE SAVEPOINT #{current_savepoint_name}") - end - - # SCHEMA STATEMENTS ======================================== - - def structure_dump - if supports_views? - sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'" - else - sql = "SHOW TABLES" - end - - select_all(sql).inject("") do |structure, table| - table.delete('Table_type') - structure += select_one("SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}")["Create Table"] + ";\n\n" - end - end - - # Drops the database specified on the +name+ attribute - # and creates it again using the provided +options+. - def recreate_database(name, options = {}) - drop_database(name) - create_database(name, options) - end - - # Create a new MySQL database with optional :charset and :collation. - # Charset defaults to utf8. - # - # Example: - # create_database 'charset_test', :charset => 'latin1', :collation => 'latin1_bin' - # create_database 'matt_development' - # create_database 'matt_development', :charset => :big5 - def create_database(name, options = {}) - if options[:collation] - execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}` COLLATE `#{options[:collation]}`" - else - execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}`" - end - end - - # Drops a MySQL database. - # - # Example: - # drop_database('sebastian_development') - def drop_database(name) #:nodoc: - execute "DROP DATABASE IF EXISTS `#{name}`" - end - - def current_database - select_value 'SELECT DATABASE() as db' - end - - # Returns the database character set. - def charset - show_variable 'character_set_database' - end - - # Returns the database collation strategy. - def collation - show_variable 'collation_database' - end - - def tables(name = nil, database = nil) #:nodoc: - sql = ["SHOW TABLES", database].compact.join(' IN ') - execute(sql, 'SCHEMA').collect do |field| - field.first - end - end - - def table_exists?(name) - return true if super - - name = name.to_s - schema, table = name.split('.', 2) - - unless table # A table was provided without a schema - table = schema - schema = nil - end - - tables(nil, schema).include? table - end - - # Returns an array of indexes for the given table. - def indexes(table_name, name = nil) - indexes = [] - current_index = nil - result = execute("SHOW KEYS FROM #{quote_table_name(table_name)}", 'SCHEMA') - result.each(:symbolize_keys => true, :as => :hash) do |row| - if current_index != row[:Key_name] - next if row[:Key_name] == PRIMARY # skip the primary key - current_index = row[:Key_name] - indexes << Mysql2IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique] == 0, [], []) - end - - indexes.last.columns << row[:Column_name] - indexes.last.lengths << row[:Sub_part] - end - indexes - end - - # Returns an array of +Mysql2Column+ objects for the table specified by +table_name+. - def columns(table_name, name = nil) - sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}" - columns = [] - result = execute(sql, 'SCHEMA') - result.each(:symbolize_keys => true, :as => :hash) { |field| - columns << Mysql2Column.new(field[:Field], field[:Default], field[:Type], field[:Null] == "YES") - } - columns - end - - def create_table(table_name, options = {}) - super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB")) - end - - # Renames a table. - # - # Example: - # rename_table('octopuses', 'octopi') - def rename_table(table_name, new_name) - execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}" - end - - def add_column(table_name, column_name, type, options = {}) - add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" - add_column_options!(add_column_sql, options) - add_column_position!(add_column_sql, options) - execute(add_column_sql) - end - - def change_column_default(table_name, column_name, default) - column = column_for(table_name, column_name) - change_column table_name, column_name, column.sql_type, :default => default - end - - def change_column_null(table_name, column_name, null, default = nil) - column = column_for(table_name, column_name) - - unless null || default.nil? - execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") - end - - change_column table_name, column_name, column.sql_type, :null => null - end - - def change_column(table_name, column_name, type, options = {}) - column = column_for(table_name, column_name) - - unless options_include_default?(options) - options[:default] = column.default - end - - unless options.has_key?(:null) - options[:null] = column.null - end - - change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" - add_column_options!(change_column_sql, options) - add_column_position!(change_column_sql, options) - execute(change_column_sql) - end - - def rename_column(table_name, column_name, new_column_name) - options = {} - if column = columns(table_name).find { |c| c.name == column_name.to_s } - options[:default] = column.default - options[:null] = column.null - else - raise ActiveRecordError, "No such column: #{table_name}.#{column_name}" - end - current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"] - rename_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}" - add_column_options!(rename_column_sql, options) - execute(rename_column_sql) - end - - # Maps logical Rails types to MySQL-specific data types. - def type_to_sql(type, limit = nil, precision = nil, scale = nil) - return super unless type.to_s == 'integer' - - case limit - when 1; 'tinyint' - when 2; 'smallint' - when 3; 'mediumint' - when nil, 4, 11; 'int(11)' # compatibility with MySQL default - when 5..8; 'bigint' - else raise(ActiveRecordError, "No integer type has byte size #{limit}") - end - end + private - def add_column_position!(sql, options) - if options[:first] - sql << " FIRST" - elsif options[:after] - sql << " AFTER #{quote_column_name(options[:after])}" - end + def connect + @connection = Mysql2::Client.new(@config) + configure_connection end - # SHOW VARIABLES LIKE 'name'. - def show_variable(name) - variables = select_all("SHOW VARIABLES LIKE '#{name}'") - variables.first['Value'] unless variables.empty? - end + def configure_connection + @connection.query_options.merge!(:as => :array) - # Returns a table's primary key and belonging sequence. - def pk_and_sequence_for(table) - keys = [] - result = execute("DESCRIBE #{quote_table_name(table)}", 'SCHEMA') - result.each(:symbolize_keys => true, :as => :hash) do |row| - keys << row[:Field] if row[:Key] == "PRI" - end - keys.length == 1 ? [keys.first, nil] : nil - end + # By default, MySQL 'where id is null' selects the last inserted id. + # Turn this off. http://dev.rubyonrails.org/ticket/6778 + variable_assignments = ['SQL_AUTO_IS_NULL=0'] + encoding = @config[:encoding] - # Returns just a table's primary key - def primary_key(table) - pk_and_sequence = pk_and_sequence_for(table) - pk_and_sequence && pk_and_sequence.first - end + # make sure we set the encoding + variable_assignments << "NAMES '#{encoding}'" if encoding - def case_sensitive_modifier(node) - Arel::Nodes::Bin.new(node) - end + # increase timeout so mysql server doesn't disconnect us + wait_timeout = @config[:wait_timeout] + wait_timeout = 2592000 unless wait_timeout.is_a?(Fixnum) + variable_assignments << "@@wait_timeout = #{wait_timeout}" - def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) - where_sql + execute("SET #{variable_assignments.join(', ')}", :skip_logging) end - # In the simple case, MySQL allows us to place JOINs directly into the UPDATE - # query. However, this does not allow for LIMIT, OFFSET and ORDER. To support - # these, we must use a subquery. However, MySQL is too stupid to create a - # temporary table for this automatically, so we have to give it some prompting - # in the form of a subsubquery. Ugh! - def join_to_update(update, select) #:nodoc: - if select.limit || select.offset || select.orders.any? - subsubselect = select.clone - subsubselect.projections = [update.key] - - subselect = Arel::SelectManager.new(select.engine) - subselect.project Arel.sql(update.key.name) - subselect.from subsubselect.as('__active_record_temp') - - update.where update.key.in(subselect) - else - update.table select.source - update.wheres = select.constraints - end + def version + @version ||= @connection.info[:version].scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } end - - protected - def quoted_columns_for_index(column_names, options = {}) - length = options[:length] if options.is_a?(Hash) - - case length - when Hash - column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) } - when Fixnum - column_names.map {|name| "#{quote_column_name(name)}(#{length})"} - else - column_names.map {|name| quote_column_name(name) } - end - end - - def translate_exception(exception, message) - return super unless exception.respond_to?(:error_number) - - case exception.error_number - when 1062 - RecordNotUnique.new(message, exception) - when 1452 - InvalidForeignKey.new(message, exception) - else - super - end - end - - private - def connect - @connection = Mysql2::Client.new(@config) - configure_connection - end - - def configure_connection - @connection.query_options.merge!(:as => :array) - - # By default, MySQL 'where id is null' selects the last inserted id. - # Turn this off. http://dev.rubyonrails.org/ticket/6778 - variable_assignments = ['SQL_AUTO_IS_NULL=0'] - encoding = @config[:encoding] - - # make sure we set the encoding - variable_assignments << "NAMES '#{encoding}'" if encoding - - # increase timeout so mysql server doesn't disconnect us - wait_timeout = @config[:wait_timeout] - wait_timeout = 2592000 unless wait_timeout.is_a?(Fixnum) - variable_assignments << "@@wait_timeout = #{wait_timeout}" - - execute("SET #{variable_assignments.join(', ')}", :skip_logging) - end - - # Returns an array of record hashes with the column names as keys and - # column values as values. - def select(sql, name = nil, binds = []) - binds = binds.dup - exec_query(sql.gsub("\0") { quote(*binds.shift.reverse) }, name).to_a - end - - def exec_query(sql, name = 'SQL', binds = []) - @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone - - log(sql, name, binds) do - begin - result = @connection.query(sql) - rescue ActiveRecord::StatementInvalid => exception - if exception.message.split(":").first =~ /Packets out of order/ - raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings." - else - raise - end - end - - ActiveRecord::Result.new(result.fields, result.to_a) - end - end - - def supports_views? - version[0] >= 5 - end - - def version - @version ||= @connection.info[:version].scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } - end - - def column_for(table_name, column_name) - unless column = columns(table_name).find { |c| c.name == column_name.to_s } - raise "No such column: #{table_name}.#{column_name}" - end - column - end end end end diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index b844e5ab10..d61875195a 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -1,6 +1,5 @@ -require 'active_record/connection_adapters/abstract_adapter' -require 'active_support/core_ext/object/blank' -require 'set' +require 'active_record/connection_adapters/abstract_mysql_adapter' +require 'active_support/core_ext/hash/keys' gem 'mysql', '~> 2.8.1' require 'mysql' @@ -40,9 +39,28 @@ module ActiveRecord end module ConnectionAdapters - class MysqlColumn < Column #:nodoc: - class << self - def string_to_time(value) + # The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with + # the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/). + # + # Options: + # + # * :host - Defaults to "localhost". + # * :port - Defaults to 3306. + # * :socket - Defaults to "/tmp/mysql.sock". + # * :username - Defaults to "root" + # * :password - Defaults to nothing. + # * :database - The name of the database. No default, must be provided. + # * :encoding - (Optional) Sets the client encoding by executing "SET NAMES " after connection. + # * :reconnect - Defaults to false (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html). + # * :sslca - Necessary to use MySQL with an SSL connection. + # * :sslkey - Necessary to use MySQL with an SSL connection. + # * :sslcert - Necessary to use MySQL with an SSL connection. + # * :sslcapath - Necessary to use MySQL with an SSL connection. + # * :sslcipher - Necessary to use MySQL with an SSL connection. + # + class MysqlAdapter < AbstractMysqlAdapter + class Column < AbstractMysqlAdapter::Column #:nodoc: + def self.string_to_time(value) return super unless Mysql::Time === value new_time( value.year, @@ -54,152 +72,36 @@ module ActiveRecord value.second_part) end - def string_to_dummy_time(v) + def self.string_to_dummy_time(v) return super unless Mysql::Time === v new_time(2000, 01, 01, v.hour, v.minute, v.second, v.second_part) end - def string_to_date(v) + def self.string_to_date(v) return super unless Mysql::Time === v new_date(v.year, v.month, v.day) end - end - def extract_default(default) - if sql_type =~ /blob/i || type == :text - if default.blank? - return null ? nil : '' - else - raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}" - end - elsif missing_default_forged_as_empty_string?(default) - nil - else - super - end - end + private - def has_default? - return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns - super - end - - private + # FIXME: Combine with the mysql2 version and move to abstract adapter def simplified_type(field_type) return :boolean if MysqlAdapter.emulate_booleans && field_type.downcase.index("tinyint(1)") return :string if field_type =~ /enum/i super end - - def extract_limit(sql_type) - case sql_type - when /blob|text/i - case sql_type - when /tiny/i - 255 - when /medium/i - 16777215 - when /long/i - 2147483647 # mysql only allows 2^31-1, not 2^32-1, somewhat inconsistently with the tiny/medium/normal cases - else - super # we could return 65535 here, but we leave it undecorated by default - end - when /^bigint/i; 8 - when /^int/i; 4 - when /^mediumint/i; 3 - when /^smallint/i; 2 - when /^tinyint/i; 1 - else - super - end - end - - # MySQL misreports NOT NULL column default when none is given. - # We can't detect this for columns which may have a legitimate '' - # default (string) but we can for others (integer, datetime, boolean, - # and the rest). - # - # Test whether the column has default '', is not null, and is not - # a type allowing default ''. - def missing_default_forged_as_empty_string?(default) - type != :string && !null && default == '' - end - end - - # The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with - # the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/). - # - # Options: - # - # * :host - Defaults to "localhost". - # * :port - Defaults to 3306. - # * :socket - Defaults to "/tmp/mysql.sock". - # * :username - Defaults to "root" - # * :password - Defaults to nothing. - # * :database - The name of the database. No default, must be provided. - # * :encoding - (Optional) Sets the client encoding by executing "SET NAMES " after connection. - # * :reconnect - Defaults to false (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html). - # * :sslca - Necessary to use MySQL with an SSL connection. - # * :sslkey - Necessary to use MySQL with an SSL connection. - # * :sslcert - Necessary to use MySQL with an SSL connection. - # * :sslcapath - Necessary to use MySQL with an SSL connection. - # * :sslcipher - Necessary to use MySQL with an SSL connection. - # - class MysqlAdapter < AbstractAdapter - - ## - # :singleton-method: - # By default, the MysqlAdapter will consider all columns of type tinyint(1) - # as boolean. If you wish to disable this emulation (which was the default - # behavior in versions 0.13.1 and earlier) you can add the following line - # to your application.rb file: - # - # ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false - cattr_accessor :emulate_booleans - self.emulate_booleans = true + end ADAPTER_NAME = 'MySQL' - LOST_CONNECTION_ERROR_MESSAGES = [ - "Server shutdown in progress", - "Broken pipe", - "Lost connection to MySQL server during query", - "MySQL server has gone away" ] - - QUOTED_TRUE, QUOTED_FALSE = '1', '0' - - NATIVE_DATABASE_TYPES = { - :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY", - :string => { :name => "varchar", :limit => 255 }, - :text => { :name => "text" }, - :integer => { :name => "int", :limit => 4 }, - :float => { :name => "float" }, - :decimal => { :name => "decimal" }, - :datetime => { :name => "datetime" }, - :timestamp => { :name => "datetime" }, - :time => { :name => "time" }, - :date => { :name => "date" }, - :binary => { :name => "blob" }, - :boolean => { :name => "tinyint", :limit => 1 } - } - def initialize(connection, logger, connection_options, config) - super(connection, logger) - @connection_options, @config = connection_options, config - @quoted_column_names, @quoted_table_names = {}, {} + super @statements = {} @client_encoding = nil connect end - def self.visitor_for(pool) # :nodoc: - Arel::Visitors::MySQL.new(pool) - end - - def adapter_name #:nodoc: - ADAPTER_NAME - end - + # FIXME: Move to abstract adapter def supports_bulk_alter? #:nodoc: true end @@ -210,78 +112,39 @@ module ActiveRecord true end - # Returns true, since this connection adapter supports migrations. - def supports_migrations? #:nodoc: - true - end + # HELPER METHODS =========================================== - # Returns true. - def supports_primary_key? #:nodoc: - true + def each_hash(result) # :nodoc: + if block_given? + result.each_hash do |row| + row.symbolize_keys! + yield row + end + else + to_enum(:each_hash, result) + end end - # Returns true, since this connection adapter supports savepoints. - def supports_savepoints? #:nodoc: - true + def new_column(field, default, type, null) # :nodoc: + Column.new(field, default, type, null) end - def native_database_types #:nodoc: - NATIVE_DATABASE_TYPES + def error_number(exception) # :nodoc: + exception.errno if exception.respond_to?(:errno) end - # QUOTING ================================================== - def quote(value, column = nil) - if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary) - s = column.class.string_to_binary(value).unpack("H*")[0] - "x'#{s}'" - elsif value.kind_of?(BigDecimal) - value.to_s("F") - else - super - end - end - def type_cast(value, column) return super unless value == true || value == false value ? 1 : 0 end - def quote_column_name(name) #:nodoc: - @quoted_column_names[name] ||= "`#{name.to_s.gsub('`', '``')}`" - end - - def quote_table_name(name) #:nodoc: - @quoted_table_names[name] ||= quote_column_name(name).gsub('.', '`.`') - end - def quote_string(string) #:nodoc: @connection.quote(string) end - def quoted_true - QUOTED_TRUE - end - - def quoted_false - QUOTED_FALSE - end - - # REFERENTIAL INTEGRITY ==================================== - - def disable_referential_integrity #:nodoc: - old = select_value("SELECT @@FOREIGN_KEY_CHECKS") - - begin - update("SET FOREIGN_KEY_CHECKS = 0") - yield - ensure - update("SET FOREIGN_KEY_CHECKS = #{old}") - end - end - # CONNECTION MANAGEMENT ==================================== def active? @@ -425,20 +288,11 @@ module ActiveRecord end end - # Executes an SQL query and returns a MySQL::Result object. Note that you have to free - # the Result object after you're done using it. - def execute(sql, name = nil) #:nodoc: - if name == :skip_logging - @connection.query(sql) - else - log(sql, name) { @connection.query(sql) } - end - rescue ActiveRecord::StatementInvalid => exception - if exception.message.split(":").first =~ /Packets out of order/ - raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings." - else - raise - end + def execute_and_free(sql, name = nil) + result = execute(sql, name) + ret = yield result + result.free + ret end def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc: @@ -447,11 +301,6 @@ module ActiveRecord end alias :create :insert_sql - def update_sql(sql, name = nil) #:nodoc: - super - @connection.affected_rows - end - def exec_delete(sql, name, binds) log(sql, name, binds) do exec_stmt(sql, name, binds) do |cols, stmt| @@ -467,172 +316,8 @@ module ActiveRecord # Transactions aren't supported end - def commit_db_transaction #:nodoc: - execute "COMMIT" - rescue Exception - # Transactions aren't supported - end - - def rollback_db_transaction #:nodoc: - execute "ROLLBACK" - rescue Exception - # Transactions aren't supported - end - - def create_savepoint - execute("SAVEPOINT #{current_savepoint_name}") - end - - def rollback_to_savepoint - execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}") - end - - def release_savepoint - execute("RELEASE SAVEPOINT #{current_savepoint_name}") - end - - # In the simple case, MySQL allows us to place JOINs directly into the UPDATE - # query. However, this does not allow for LIMIT, OFFSET and ORDER. To support - # these, we must use a subquery. However, MySQL is too stupid to create a - # temporary table for this automatically, so we have to give it some prompting - # in the form of a subsubquery. Ugh! - def join_to_update(update, select) #:nodoc: - if select.limit || select.offset || select.orders.any? - subsubselect = select.clone - subsubselect.projections = [update.key] - - subselect = Arel::SelectManager.new(select.engine) - subselect.project Arel.sql(update.key.name) - subselect.from subsubselect.as('__active_record_temp') - - update.where update.key.in(subselect) - else - update.table select.source - update.wheres = select.constraints - end - end - # SCHEMA STATEMENTS ======================================== - def structure_dump #:nodoc: - if supports_views? - sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'" - else - sql = "SHOW TABLES" - end - - select_all(sql).map do |table| - table.delete('Table_type') - sql = "SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}" - exec_without_stmt(sql).first['Create Table'] + ";\n\n" - end.join("") - end - - # Drops the database specified on the +name+ attribute - # and creates it again using the provided +options+. - def recreate_database(name, options = {}) #:nodoc: - drop_database(name) - create_database(name, options) - end - - # Create a new MySQL database with optional :charset and :collation. - # Charset defaults to utf8. - # - # Example: - # create_database 'charset_test', :charset => 'latin1', :collation => 'latin1_bin' - # create_database 'matt_development' - # create_database 'matt_development', :charset => :big5 - def create_database(name, options = {}) - if options[:collation] - execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}` COLLATE `#{options[:collation]}`" - else - execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}`" - end - end - - # Drops a MySQL database. - # - # Example: - # drop_database 'sebastian_development' - def drop_database(name) #:nodoc: - execute "DROP DATABASE IF EXISTS `#{name}`" - end - - def current_database - select_value 'SELECT DATABASE() as db' - end - - # Returns the database character set. - def charset - show_variable 'character_set_database' - end - - # Returns the database collation strategy. - def collation - show_variable 'collation_database' - end - - def tables(name = nil, database = nil) #:nodoc: - result = execute(["SHOW TABLES", database].compact.join(' IN '), 'SCHEMA') - tables = result.collect { |field| field[0] } - result.free - tables - end - - def table_exists?(name) - return true if super - - name = name.to_s - schema, table = name.split('.', 2) - - unless table # A table was provided without a schema - table = schema - schema = nil - end - - tables(nil, schema).include? table - end - - # Returns an array of indexes for the given table. - def indexes(table_name, name = nil)#:nodoc: - indexes = [] - current_index = nil - result = execute("SHOW KEYS FROM #{quote_table_name(table_name)}", name) - result.each do |row| - if current_index != row[2] - next if row[2] == "PRIMARY" # skip the primary key - current_index = row[2] - indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", [], []) - end - - indexes.last.columns << row[4] - indexes.last.lengths << row[7] - end - result.free - indexes - end - - # Returns an array of +MysqlColumn+ objects for the table specified by +table_name+. - def columns(table_name, name = nil)#:nodoc: - sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}" - result = execute(sql, 'SCHEMA') - columns = result.collect { |field| MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") } - result.free - columns - end - - def create_table(table_name, options = {}) #:nodoc: - super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB")) - end - - # Renames a table. - # - # Example: - # rename_table('octopuses', 'octopi') - def rename_table(table_name, new_name) - execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}" - end - def bulk_change_table(table_name, operations) #:nodoc: sqls = operations.map do |command, args| table, arguments = args.shift, args @@ -648,177 +333,33 @@ module ActiveRecord execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}") end - def add_column(table_name, column_name, type, options = {}) - execute("ALTER TABLE #{quote_table_name(table_name)} #{add_column_sql(table_name, column_name, type, options)}") - end - - def change_column_default(table_name, column_name, default) #:nodoc: - column = column_for(table_name, column_name) - change_column table_name, column_name, column.sql_type, :default => default - end - - def change_column_null(table_name, column_name, null, default = nil) - column = column_for(table_name, column_name) - - unless null || default.nil? - execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") - end - - change_column table_name, column_name, column.sql_type, :null => null - end - - def change_column(table_name, column_name, type, options = {}) #:nodoc: - execute("ALTER TABLE #{quote_table_name(table_name)} #{change_column_sql(table_name, column_name, type, options)}") - end - - def rename_column(table_name, column_name, new_column_name) #:nodoc: - execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_sql(table_name, column_name, new_column_name)}") - end - - # Maps logical Rails types to MySQL-specific data types. - def type_to_sql(type, limit = nil, precision = nil, scale = nil) - return super unless type.to_s == 'integer' - - case limit - when 1; 'tinyint' - when 2; 'smallint' - when 3; 'mediumint' - when nil, 4, 11; 'int(11)' # compatibility with MySQL default - when 5..8; 'bigint' - else raise(ActiveRecordError, "No integer type has byte size #{limit}") - end - end - - def add_column_position!(sql, options) - if options[:first] - sql << " FIRST" - elsif options[:after] - sql << " AFTER #{quote_column_name(options[:after])}" - end - end + protected - # SHOW VARIABLES LIKE 'name' - def show_variable(name) - variables = select_all("SHOW VARIABLES LIKE '#{name}'") - variables.first['Value'] unless variables.empty? + def remove_column_sql(table_name, *column_names) + columns_for_remove(table_name, *column_names).map {|column_name| "DROP #{column_name}" } end + alias :remove_columns_sql :remove_column - # Returns a table's primary key and belonging sequence. - def pk_and_sequence_for(table) #:nodoc: - keys = [] - result = execute("describe #{quote_table_name(table)}", 'SCHEMA') - result.each_hash do |h| - keys << h["Field"]if h["Key"] == "PRI" - end - result.free - keys.length == 1 ? [keys.first, nil] : nil + def add_index_sql(table_name, column_name, options = {}) + index_name, index_type, index_columns = add_index_options(table_name, column_name, options) + "ADD #{index_type} INDEX #{index_name} (#{index_columns})" end - # Returns just a table's primary key - def primary_key(table) - pk_and_sequence = pk_and_sequence_for(table) - pk_and_sequence && pk_and_sequence.first + def remove_index_sql(table_name, options = {}) + index_name = index_name_for_remove(table_name, options) + "DROP INDEX #{index_name}" end - def case_sensitive_modifier(node) - Arel::Nodes::Bin.new(node) + def add_timestamps_sql(table_name) + [add_column_sql(table_name, :created_at, :datetime), add_column_sql(table_name, :updated_at, :datetime)] end - def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) - where_sql + def remove_timestamps_sql(table_name) + [remove_column_sql(table_name, :updated_at), remove_column_sql(table_name, :created_at)] end - protected - def quoted_columns_for_index(column_names, options = {}) - length = options[:length] if options.is_a?(Hash) - - case length - when Hash - column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) } - when Fixnum - column_names.map {|name| "#{quote_column_name(name)}(#{length})"} - else - column_names.map {|name| quote_column_name(name) } - end - end - - def translate_exception(exception, message) - return super unless exception.respond_to?(:errno) - - case exception.errno - when 1062 - RecordNotUnique.new(message, exception) - when 1452 - InvalidForeignKey.new(message, exception) - else - super - end - end - - def add_column_sql(table_name, column_name, type, options = {}) - add_column_sql = "ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" - add_column_options!(add_column_sql, options) - add_column_position!(add_column_sql, options) - add_column_sql - end - - def remove_column_sql(table_name, *column_names) - columns_for_remove(table_name, *column_names).map {|column_name| "DROP #{column_name}" } - end - alias :remove_columns_sql :remove_column - - def change_column_sql(table_name, column_name, type, options = {}) - column = column_for(table_name, column_name) - - unless options_include_default?(options) - options[:default] = column.default - end - - unless options.has_key?(:null) - options[:null] = column.null - end - - change_column_sql = "CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" - add_column_options!(change_column_sql, options) - add_column_position!(change_column_sql, options) - change_column_sql - end - - def rename_column_sql(table_name, column_name, new_column_name) - options = {} - - if column = columns(table_name).find { |c| c.name == column_name.to_s } - options[:default] = column.default - options[:null] = column.null - else - raise ActiveRecordError, "No such column: #{table_name}.#{column_name}" - end - - current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"] - rename_column_sql = "CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}" - add_column_options!(rename_column_sql, options) - rename_column_sql - end - - def add_index_sql(table_name, column_name, options = {}) - index_name, index_type, index_columns = add_index_options(table_name, column_name, options) - "ADD #{index_type} INDEX #{index_name} (#{index_columns})" - end - - def remove_index_sql(table_name, options = {}) - index_name = index_name_for_remove(table_name, options) - "DROP INDEX #{index_name}" - end - - def add_timestamps_sql(table_name) - [add_column_sql(table_name, :created_at, :datetime), add_column_sql(table_name, :updated_at, :datetime)] - end - - def remove_timestamps_sql(table_name) - [remove_column_sql(table_name, :updated_at), remove_column_sql(table_name, :created_at)] - end - private + def exec_stmt(sql, name, binds) cache = {} if binds.empty? @@ -830,7 +371,6 @@ module ActiveRecord stmt = cache[:stmt] end - begin stmt.execute(*binds.map { |col, val| type_cast(val, col) }) rescue Mysql::Error => e @@ -859,59 +399,48 @@ module ActiveRecord result end - def connect - encoding = @config[:encoding] - if encoding - @connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil - end - - if @config[:sslca] || @config[:sslkey] - @connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher]) - end + def connect + encoding = @config[:encoding] + if encoding + @connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil + end - @connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout] - @connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout] - @connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout] + if @config[:sslca] || @config[:sslkey] + @connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher]) + end - @connection.real_connect(*@connection_options) + @connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout] + @connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout] + @connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout] - # reconnect must be set after real_connect is called, because real_connect sets it to false internally - @connection.reconnect = !!@config[:reconnect] if @connection.respond_to?(:reconnect=) + @connection.real_connect(*@connection_options) - configure_connection - end + # reconnect must be set after real_connect is called, because real_connect sets it to false internally + @connection.reconnect = !!@config[:reconnect] if @connection.respond_to?(:reconnect=) - def configure_connection - encoding = @config[:encoding] - execute("SET NAMES '#{encoding}'", :skip_logging) if encoding - - # By default, MySQL 'where id is null' selects the last inserted id. - # Turn this off. http://dev.rubyonrails.org/ticket/6778 - execute("SET SQL_AUTO_IS_NULL=0", :skip_logging) - end + configure_connection + end - def select(sql, name = nil, binds = []) - @connection.query_with_result = true - rows = exec_query(sql, name, binds).to_a - @connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped - rows - end + def configure_connection + encoding = @config[:encoding] + execute("SET NAMES '#{encoding}'", :skip_logging) if encoding - def supports_views? - version[0] >= 5 - end + # By default, MySQL 'where id is null' selects the last inserted id. + # Turn this off. http://dev.rubyonrails.org/ticket/6778 + execute("SET SQL_AUTO_IS_NULL=0", :skip_logging) + end - # Returns the version of the connected MySQL server. - def version - @version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } - end + def select(sql, name = nil, binds = []) + @connection.query_with_result = true + rows = exec_query(sql, name, binds).to_a + @connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped + rows + end - def column_for(table_name, column_name) - unless column = columns(table_name).find { |c| c.name == column_name.to_s } - raise "No such column: #{table_name}.#{column_name}" - end - column - end + # Returns the version of the connected MySQL server. + def version + @version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } + end end end end diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb index 509baacaef..94fc3564df 100644 --- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb +++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb @@ -2,7 +2,7 @@ require "cases/helper" class ActiveSchemaTest < ActiveRecord::TestCase def setup - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.class_eval do alias_method :execute_without_stub, :execute remove_method :execute def execute(sql, name = nil) return sql end @@ -10,7 +10,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase end def teardown - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.class_eval do remove_method :execute alias_method :execute, :execute_without_stub end @@ -99,7 +99,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase private def with_real_execute #we need to actually modify some data, so we make execute point to the original method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.class_eval do alias_method :execute_with_stub, :execute remove_method :execute alias_method :execute, :execute_without_stub @@ -107,7 +107,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase yield ensure #before finishing, we restore the alias to the mock-up method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.class_eval do remove_method :execute alias_method :execute, :execute_with_stub end diff --git a/activerecord/test/cases/column_definition_test.rb b/activerecord/test/cases/column_definition_test.rb index d1dddd4c2c..14884e42af 100644 --- a/activerecord/test/cases/column_definition_test.rb +++ b/activerecord/test/cases/column_definition_test.rb @@ -58,68 +58,68 @@ module ActiveRecord if current_adapter?(:MysqlAdapter) def test_should_set_default_for_mysql_binary_data_types - binary_column = MysqlColumn.new("title", "a", "binary(1)") + binary_column = MysqlAdapter::Column.new("title", "a", "binary(1)") assert_equal "a", binary_column.default - varbinary_column = MysqlColumn.new("title", "a", "varbinary(1)") + varbinary_column = MysqlAdapter::Column.new("title", "a", "varbinary(1)") assert_equal "a", varbinary_column.default end def test_should_not_set_default_for_blob_and_text_data_types assert_raise ArgumentError do - MysqlColumn.new("title", "a", "blob") + MysqlAdapter::Column.new("title", "a", "blob") end assert_raise ArgumentError do - MysqlColumn.new("title", "Hello", "text") + MysqlAdapter::Column.new("title", "Hello", "text") end - text_column = MysqlColumn.new("title", nil, "text") + text_column = MysqlAdapter::Column.new("title", nil, "text") assert_equal nil, text_column.default - not_null_text_column = MysqlColumn.new("title", nil, "text", false) + not_null_text_column = MysqlAdapter::Column.new("title", nil, "text", false) assert_equal "", not_null_text_column.default end def test_has_default_should_return_false_for_blog_and_test_data_types - blob_column = MysqlColumn.new("title", nil, "blob") + blob_column = MysqlAdapter::Column.new("title", nil, "blob") assert !blob_column.has_default? - text_column = MysqlColumn.new("title", nil, "text") + text_column = MysqlAdapter::Column.new("title", nil, "text") assert !text_column.has_default? end end if current_adapter?(:Mysql2Adapter) def test_should_set_default_for_mysql_binary_data_types - binary_column = Mysql2Column.new("title", "a", "binary(1)") + binary_column = Mysql2Adapter::Column.new("title", "a", "binary(1)") assert_equal "a", binary_column.default - varbinary_column = Mysql2Column.new("title", "a", "varbinary(1)") + varbinary_column = Mysql2Adapter::Column.new("title", "a", "varbinary(1)") assert_equal "a", varbinary_column.default end def test_should_not_set_default_for_blob_and_text_data_types assert_raise ArgumentError do - Mysql2Column.new("title", "a", "blob") + Mysql2Adapter::Column.new("title", "a", "blob") end assert_raise ArgumentError do - Mysql2Column.new("title", "Hello", "text") + Mysql2Adapter::Column.new("title", "Hello", "text") end - text_column = Mysql2Column.new("title", nil, "text") + text_column = Mysql2Adapter::Column.new("title", nil, "text") assert_equal nil, text_column.default - not_null_text_column = Mysql2Column.new("title", nil, "text", false) + not_null_text_column = Mysql2Adapter::Column.new("title", nil, "text", false) assert_equal "", not_null_text_column.default end def test_has_default_should_return_false_for_blog_and_test_data_types - blob_column = Mysql2Column.new("title", nil, "blob") + blob_column = Mysql2Adapter::Column.new("title", nil, "blob") assert !blob_column.has_default? - text_column = Mysql2Column.new("title", nil, "text") + text_column = Mysql2Adapter::Column.new("title", nil, "text") assert !text_column.has_default? end end -- cgit v1.2.3 From 4fcd847c8d9fb2b22e1c2e3c840c8d1c590b56b4 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 29 Aug 2011 12:25:15 +0100 Subject: Extract simplified_type into the abstract class --- .../connection_adapters/abstract_mysql_adapter.rb | 19 ++++++++++++++++++- .../connection_adapters/mysql2_adapter.rb | 18 +++--------------- .../connection_adapters/mysql_adapter.rb | 10 +++------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 72cf490d7e..548ca83353 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/object/blank' module ActiveRecord module ConnectionAdapters class AbstractMysqlAdapter < AbstractAdapter - class Column < ConnectionAdapters::Column + class Column < ConnectionAdapters::Column # :nodoc: def extract_default(default) if sql_type =~ /blob/i || type == :text if default.blank? @@ -23,8 +23,25 @@ module ActiveRecord super end + # Must return the relevant concrete adapter + def adapter + raise NotImplementedError + end + private + def simplified_type(field_type) + return :boolean if adapter.emulate_booleans && field_type.downcase.index("tinyint(1)") + + case field_type + when /enum/i, /set/i then :string + when /year/i then :integer + when /bit/i then :binary + else + super + end + end + def extract_limit(sql_type) case sql_type when /blob|text/i diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index 00d9caa8ee..8b574518e5 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -21,22 +21,10 @@ module ActiveRecord module ConnectionAdapters class Mysql2Adapter < AbstractMysqlAdapter - class Column < AbstractMysqlAdapter::Column # :nodoc: - BOOL = "tinyint(1)" - - private - - # FIXME: Combine with the mysql version and move to abstract adapter - def simplified_type(field_type) - return :boolean if Mysql2Adapter.emulate_booleans && field_type.downcase.index(BOOL) - case field_type - when /enum/i, /set/i then :string - when /year/i then :integer - when /bit/i then :binary - else - super - end + class Column < AbstractMysqlAdapter::Column # :nodoc: + def adapter + Mysql2Adapter end end diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index d61875195a..182db65165 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -59,6 +59,7 @@ module ActiveRecord # * :sslcipher - Necessary to use MySQL with an SSL connection. # class MysqlAdapter < AbstractMysqlAdapter + class Column < AbstractMysqlAdapter::Column #:nodoc: def self.string_to_time(value) return super unless Mysql::Time === value @@ -82,13 +83,8 @@ module ActiveRecord new_date(v.year, v.month, v.day) end - private - - # FIXME: Combine with the mysql2 version and move to abstract adapter - def simplified_type(field_type) - return :boolean if MysqlAdapter.emulate_booleans && field_type.downcase.index("tinyint(1)") - return :string if field_type =~ /enum/i - super + def adapter + MysqlAdapter end end -- cgit v1.2.3 From fd22d040fef48778a519825dd2f0cf2fd73a8965 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 29 Aug 2011 12:43:17 +0100 Subject: Move the bulk alter table code into the abstract mysql adapter, hence it is supported for mysql2 as well now. --- activerecord/CHANGELOG | 2 + .../connection_adapters/abstract_mysql_adapter.rb | 42 +++++++++++++++++++ .../connection_adapters/mysql_adapter.rb | 47 ---------------------- 3 files changed, 44 insertions(+), 47 deletions(-) diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index e8d4b9c04e..700e11ff94 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.2.0 (unreleased)* +* Support bulk change_table in mysql2 adapter, as well as the mysql one. [Jon Leighton] + * If multiple parameters are sent representing a date, and some are blank, the resulting object is nil. In previous releases those values defaulted to 1. This only affects existing but blank parameters, missing ones still raise an error. diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 548ca83353..4b7c74e0b8 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -140,6 +140,10 @@ module ActiveRecord true end + def supports_bulk_alter? #:nodoc: + true + end + def native_database_types NATIVE_DATABASE_TYPES end @@ -401,6 +405,21 @@ module ActiveRecord super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB")) end + def bulk_change_table(table_name, operations) #:nodoc: + sqls = operations.map do |command, args| + table, arguments = args.shift, args + method = :"#{command}_sql" + + if respond_to?(method) + send(method, table, *arguments) + else + raise "Unknown method called : #{method}(#{arguments.inspect})" + end + end.flatten.join(", ") + + execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}") + end + # Renames a table. # # Example: @@ -552,6 +571,29 @@ module ActiveRecord rename_column_sql end + def remove_column_sql(table_name, *column_names) + columns_for_remove(table_name, *column_names).map {|column_name| "DROP #{column_name}" } + end + alias :remove_columns_sql :remove_column + + def add_index_sql(table_name, column_name, options = {}) + index_name, index_type, index_columns = add_index_options(table_name, column_name, options) + "ADD #{index_type} INDEX #{index_name} (#{index_columns})" + end + + def remove_index_sql(table_name, options = {}) + index_name = index_name_for_remove(table_name, options) + "DROP INDEX #{index_name}" + end + + def add_timestamps_sql(table_name) + [add_column_sql(table_name, :created_at, :datetime), add_column_sql(table_name, :updated_at, :datetime)] + end + + def remove_timestamps_sql(table_name) + [remove_column_sql(table_name, :updated_at), remove_column_sql(table_name, :created_at)] + end + private def supports_views? diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 182db65165..e9bdcc2104 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -97,11 +97,6 @@ module ActiveRecord connect end - # FIXME: Move to abstract adapter - def supports_bulk_alter? #:nodoc: - true - end - # Returns true, since this connection adapter supports prepared statement # caching. def supports_statement_cache? @@ -312,48 +307,6 @@ module ActiveRecord # Transactions aren't supported end - # SCHEMA STATEMENTS ======================================== - - def bulk_change_table(table_name, operations) #:nodoc: - sqls = operations.map do |command, args| - table, arguments = args.shift, args - method = :"#{command}_sql" - - if respond_to?(method) - send(method, table, *arguments) - else - raise "Unknown method called : #{method}(#{arguments.inspect})" - end - end.flatten.join(", ") - - execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}") - end - - protected - - def remove_column_sql(table_name, *column_names) - columns_for_remove(table_name, *column_names).map {|column_name| "DROP #{column_name}" } - end - alias :remove_columns_sql :remove_column - - def add_index_sql(table_name, column_name, options = {}) - index_name, index_type, index_columns = add_index_options(table_name, column_name, options) - "ADD #{index_type} INDEX #{index_name} (#{index_columns})" - end - - def remove_index_sql(table_name, options = {}) - index_name = index_name_for_remove(table_name, options) - "DROP INDEX #{index_name}" - end - - def add_timestamps_sql(table_name) - [add_column_sql(table_name, :created_at, :datetime), add_column_sql(table_name, :updated_at, :datetime)] - end - - def remove_timestamps_sql(table_name) - [remove_column_sql(table_name, :updated_at), remove_column_sql(table_name, :created_at)] - end - private def exec_stmt(sql, name, binds) -- cgit v1.2.3 From 735d985b0162976e7e900cf36d4cbb0d657fb5e9 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 29 Aug 2011 15:01:17 +0100 Subject: The join_nodes must be passed to the JoinDependency initializer and therefore counted by the alias tracker. This is because the association_joins are aliased on initialization and then the tables are cached, so it is no use to alias the join_nodes later. Fixes #2556. --- .../lib/active_record/associations/alias_tracker.rb | 18 ++++++++++++------ .../lib/active_record/relation/query_methods.rb | 9 ++------- .../associations/has_many_through_associations_test.rb | 4 ++++ activerecord/test/models/toy.rb | 2 ++ 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/activerecord/lib/active_record/associations/alias_tracker.rb b/activerecord/lib/active_record/associations/alias_tracker.rb index 92ed844a2e..0248c7483c 100644 --- a/activerecord/lib/active_record/associations/alias_tracker.rb +++ b/activerecord/lib/active_record/associations/alias_tracker.rb @@ -53,12 +53,18 @@ module ActiveRecord # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase quoted_name = connection.quote_table_name(name).downcase - table_joins.map { |join| - # Table names + table aliases - join.left.downcase.scan( - /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/ - ).size - }.sum + counts = table_joins.map do |join| + if join.is_a?(Arel::Nodes::StringJoin) + # Table names + table aliases + join.left.downcase.scan( + /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/ + ).size + else + join.left.table_name == name ? 1 : 0 + end + end + + counts.sum end def truncate(name) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 1654ae1eac..7eda9ad8e8 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -254,12 +254,12 @@ module ActiveRecord association_joins = buckets['association_join'] || [] stashed_association_joins = buckets['stashed_join'] || [] - join_nodes = buckets['join_node'] || [] + join_nodes = (buckets['join_node'] || []).uniq string_joins = (buckets['string_join'] || []).map { |x| x.strip }.uniq - join_list = custom_join_ast(manager, string_joins) + join_list = join_nodes + custom_join_ast(manager, string_joins) join_dependency = ActiveRecord::Associations::JoinDependency.new( @klass, @@ -267,10 +267,6 @@ module ActiveRecord join_list ) - join_nodes.each do |join| - join_dependency.alias_tracker.aliased_name_for(join.left.name.downcase) - end - join_dependency.graft(*stashed_association_joins) @implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty? @@ -280,7 +276,6 @@ module ActiveRecord association.join_to(manager) end - manager.join_sources.concat join_nodes.uniq manager.join_sources.concat join_list manager diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 5f2328ff95..b703c96ec1 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -821,4 +821,8 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert person.posts.loaded?, 'person.posts should be loaded' assert_equal [], person.posts end + + def test_explicitly_joining_join_table + assert_equal owners(:blackbeard).toys, owners(:blackbeard).toys.with_pet + end end diff --git a/activerecord/test/models/toy.rb b/activerecord/test/models/toy.rb index 79a88db0da..6c45e99671 100644 --- a/activerecord/test/models/toy.rb +++ b/activerecord/test/models/toy.rb @@ -1,4 +1,6 @@ class Toy < ActiveRecord::Base set_primary_key :toy_id belongs_to :pet + + scope :with_pet, joins(:pet) end -- cgit v1.2.3 From c59c9bb8bc275a2be8695d4d431a0512d29353f1 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 29 Aug 2011 17:39:09 +0100 Subject: Move clear_timestamp_attributes into Timestamp module --- activerecord/lib/active_record/base.rb | 10 +--------- activerecord/lib/active_record/timestamp.rb | 14 +++++++++++++- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 03aea81d2c..374791deb1 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1849,7 +1849,7 @@ MSG ensure_proper_type populate_with_current_scope_attributes - clear_timestamp_attributes + super end # Returns +true+ if the record is read only. Records loaded through joins with piggy-back @@ -2113,14 +2113,6 @@ MSG send("#{att}=", value) if respond_to?("#{att}=") end end - - # Clear attributes and changed_attributes - def clear_timestamp_attributes - all_timestamp_attributes_in_model.each do |attribute_name| - self[attribute_name] = nil - changed_attributes.delete(attribute_name) - end - end end Base.class_eval do diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 1511c71ffc..6b8c52861e 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -37,6 +37,11 @@ module ActiveRecord self.record_timestamps = true end + def initialize_dup(other) + clear_timestamp_attributes + super + end + private def create #:nodoc: @@ -95,6 +100,13 @@ module ActiveRecord def current_time_from_proper_timezone #:nodoc: self.class.default_timezone == :utc ? Time.now.utc : Time.now end + + # Clear attributes and changed_attributes + def clear_timestamp_attributes + all_timestamp_attributes_in_model.each do |attribute_name| + self[attribute_name] = nil + changed_attributes.delete(attribute_name) + end + end end end - -- cgit v1.2.3 From 92619e4f78e9417dbfa3e22acce25ff343f45f0b Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 29 Aug 2011 23:04:50 +0100 Subject: Fix test failures on 1.8.7, since Object#initialize_dup is not defined there (and this call to super is no essential, so easiest to simply remove) --- activerecord/lib/active_record/timestamp.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 6b8c52861e..cccac6ffd7 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -39,7 +39,6 @@ module ActiveRecord def initialize_dup(other) clear_timestamp_attributes - super end private -- cgit v1.2.3 From 5aa86f793f4df75f8a5780626269abc3511c61a0 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Mon, 29 Aug 2011 15:47:56 -0700 Subject: let SDoc add a link to the source code in GitHub for each method --- Rakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Rakefile b/Rakefile index ae857036c5..f171949961 100755 --- a/Rakefile +++ b/Rakefile @@ -93,6 +93,7 @@ RDoc::Task.new do |rdoc| rdoc.options << '-f' << 'sdoc' rdoc.options << '-T' << 'rails' rdoc.options << '-c' << 'utf-8' + rdoc.options << '-g' # SDoc flag, link methods to GitHub rdoc.options << '-m' << RDOC_MAIN rdoc.rdoc_files.include('railties/CHANGELOG') -- cgit v1.2.3 From 725617a6475703270a9afd59f1cf91ac3297720a Mon Sep 17 00:00:00 2001 From: Daniel Schierbeck Date: Mon, 22 Aug 2011 19:21:35 +0200 Subject: Document the Sprockets compressors Add documentation to Sprockets::NullCompressor and Sprockets::LazyCompressor. Also, make LazyCompressor#compressor private, as it isn't part of the public API. --- actionpack/lib/sprockets/compressors.rb | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/sprockets/compressors.rb b/actionpack/lib/sprockets/compressors.rb index 6544953df4..351eff1085 100644 --- a/actionpack/lib/sprockets/compressors.rb +++ b/actionpack/lib/sprockets/compressors.rb @@ -1,21 +1,37 @@ module Sprockets - class NullCompressor + # An asset compressor which does nothing. + # + # This compressor simply returns the asset as-is, without any compression + # whatsoever. It is useful in development mode, when compression isn't + # needed but using the same asset pipeline as production is desired. + class NullCompressor #:nodoc: def compress(content) content end end - class LazyCompressor + # An asset compressor which only initializes the underlying compression + # engine when needed. + # + # This postpones the initialization of the compressor until + # #compress is called the first time. + class LazyCompressor #:nodoc: + # Initializes a new LazyCompressor. + # + # The block should return a compressor when called, i.e. an object + # which responds to #compress. def initialize(&block) @block = block end - def compressor - @compressor ||= @block.call || NullCompressor.new - end - def compress(content) compressor.compress(content) end + + private + + def compressor + @compressor ||= (@block.call || NullCompressor.new) + end end -end \ No newline at end of file +end -- cgit v1.2.3 From bd4bd3f50a7e3a8efd8f24612765a7f16e520748 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 30 Aug 2011 09:56:42 -0700 Subject: Merge pull request #2750 from rsim/fix_test_column_names_are_escaped_for_oracle Fix test column names are escaped for oracle --- activerecord/test/cases/base_test.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index bee183cc67..1e647b5970 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -81,7 +81,13 @@ class BasicsTest < ActiveRecord::TestCase } quoted = conn.quote_column_name "foo#{badchar}bar" - assert_equal("#{badchar}foo#{badchar * 2}bar#{badchar}", quoted) + if current_adapter?(:OracleAdapter) + # Oracle does not allow double quotes in table and column names at all + # therefore quoting removes them + assert_equal("#{badchar}foobar#{badchar}", quoted) + else + assert_equal("#{badchar}foo#{badchar * 2}bar#{badchar}", quoted) + end end def test_columns_should_obey_set_primary_key -- cgit v1.2.3 From 2350fecd2251584d770afc4bd1764b3fe526ff70 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 30 Aug 2011 13:48:16 -0700 Subject: adds the asset pipeline guide to the index --- railties/guides/source/asset_pipeline.textile | 2 +- railties/guides/source/index.html.erb | 4 ++++ railties/guides/source/layout.html.erb | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 554246acb3..2695ba9ec1 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -1,6 +1,6 @@ h2. Asset Pipeline -This guide covers the ideology of the asset pipeline introduced in Rails 3.1. +This guide covers the asset pipeline introduced in Rails 3.1. By referring to this guide you will be able to: * Understand what the asset pipeline is and what it does diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb index 684251962c..b7813086d7 100644 --- a/railties/guides/source/index.html.erb +++ b/railties/guides/source/index.html.erb @@ -131,6 +131,10 @@ Ruby on Rails Guides <%= guide("Caching with Rails", 'caching_with_rails.html', :work_in_progress => true) do %>

Various caching techniques provided by Rails.

<% end %> + +<%= guide('Asset Pipeline', 'asset_pipeline.html') do %> +

This guide documents the asset pipeline.

+<% end %>

Extending Rails

diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb index 5dcac8e74c..5f8ee57517 100644 --- a/railties/guides/source/layout.html.erb +++ b/railties/guides/source/layout.html.erb @@ -5,7 +5,7 @@ -<%= yield(:page_title) || 'Ruby on Rails guides' %> +<%= yield(:page_title) || 'Ruby on Rails Guides' %> @@ -71,6 +71,7 @@
Configuring Rails Applications
Rails Command Line Tools and Rake Tasks
Caching with Rails
+
Asset Pipeline
Extending Rails
The Basics of Creating Rails Plugins
-- cgit v1.2.3 From 84dad446c6a23a15f67b9d558e8039891a008bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mej=C3=ADa?= Date: Sat, 27 Aug 2011 23:10:25 -0500 Subject: Adding first_or_create, first_or_create!, first_or_new and first_or_build to Active Record. This let's you write things like: User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson", :hot => true) Related to #2420. --- activerecord/CHANGELOG | 6 + activerecord/lib/active_record/base.rb | 1 + activerecord/lib/active_record/relation.rb | 43 +++++++ activerecord/test/cases/base_test.rb | 31 +++++ activerecord/test/cases/relations_test.rb | 128 +++++++++++++++++++++ .../guides/source/active_record_querying.textile | 75 ++++++++++-- 6 files changed, 277 insertions(+), 7 deletions(-) diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 700e11ff94..57e4fcf9cf 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,11 @@ *Rails 3.2.0 (unreleased)* +* Add first_or_create, first_or_create!, first_or_build and first_or_new methods to Active Record. This is a better approach over the old find_or_create_by dynamic methods because it's clearer which arguments are used to find the record and which are used to create it: + + User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson", :hot => true) + + [Andrés Mejía] + * Support bulk change_table in mysql2 adapter, as well as the mysql one. [Jon Leighton] * If multiple parameters are sent representing a date, and some are blank, the diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 374791deb1..2979ad1cb3 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -442,6 +442,7 @@ module ActiveRecord #:nodoc: class << self # Class methods delegate :find, :first, :first!, :last, :last!, :all, :exists?, :any?, :many?, :to => :scoped + delegate :first_or_create, :first_or_create!, :first_or_new, :first_or_build, :to => :scoped delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, :to => :scoped delegate :find_each, :find_in_batches, :to => :scoped delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 15fd1a58c8..461237c7ad 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -94,6 +94,49 @@ module ActiveRecord scoping { @klass.create!(*args, &block) } end + # Tries to load the first record; if it fails, then create is called with the same arguments as this method. + # + # Expects arguments in the same format as Base.create. + # + # ==== Examples + # # Find the first user named Scarlett or create a new one. + # User.where(:first_name => 'Scarlett').first_or_create(:last_name => 'Johansson') + # # => + # + # # Find the first user named Scarlett or create one with a different last name. + # # We already have one Scarlett, so she'll be returned. + # User.where(:first_name => 'Scarlett').first_or_create do |user| + # user.last_name = "O'Hara" + # end + # # => + # + # # Find the first user named Andy or create several at a time. + # User.where(:first_name => 'Andy').first_or_create([{:last_name => 'García'}, {:last_name => 'Mejía'}]) + # # => [#, + # #] + # + # # Find the first user with last name García or create several at a time. + # User.where(:last_name => 'García').first_or_create([{:first_name => 'Jorge'}, {:first_name => 'Andy'}]) + # # => + def first_or_create(*args, &block) + first || create(*args, &block) + end + + # Like first_or_create but calls create! so an exception is raised if the created record is invalid. + # + # Expects arguments in the same format as Base.create. + def first_or_create!(*args, &block) + first || create!(*args, &block) + end + + # Like first_or_create but calls new instead of create. + # + # Expects arguments in the same format as Base.new. + def first_or_new(*args, &block) + first || new(*args, &block) + end + alias :first_or_build :first_or_new + def respond_to?(method, include_private = false) arel.respond_to?(method, include_private) || Array.method_defined?(method) || diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 1e647b5970..02a4644cd2 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -277,6 +277,37 @@ class BasicsTest < ActiveRecord::TestCase assert_equal(true, cb.frickinawesome) end + def test_first_or_create + parrot = Bird.first_or_create(:color => 'green', :name => 'parrot') + assert parrot.persisted? + the_same_parrot = Bird.first_or_create(:color => 'yellow', :name => 'macaw') + assert_equal parrot, the_same_parrot + end + + def test_first_or_create_bang + assert_raises(ActiveRecord::RecordInvalid) { Bird.first_or_create! } + parrot = Bird.first_or_create!(:color => 'green', :name => 'parrot') + assert parrot.persisted? + the_same_parrot = Bird.first_or_create!(:color => 'yellow', :name => 'macaw') + assert_equal parrot, the_same_parrot + end + + def test_first_or_new + parrot = Bird.first_or_new(:color => 'green', :name => 'parrot') + assert_kind_of Bird, parrot + assert !parrot.persisted? + assert parrot.new_record? + assert parrot.valid? + end + + def test_first_or_build + parrot = Bird.first_or_build(:color => 'green', :name => 'parrot') + assert_kind_of Bird, parrot + assert !parrot.persisted? + assert parrot.new_record? + assert parrot.valid? + end + def test_load topics = Topic.find(:all, :order => 'id') assert_equal(4, topics.size) diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 615551a279..9f129cf9fc 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -863,6 +863,134 @@ class RelationTest < ActiveRecord::TestCase assert_equal 'hen', hen.name end + def test_first_or_create + parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot') + assert_kind_of Bird, parrot + assert parrot.persisted? + assert_equal 'parrot', parrot.name + assert_equal 'green', parrot.color + + same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet') + assert_kind_of Bird, same_parrot + assert same_parrot.persisted? + assert_equal parrot, same_parrot + end + + def test_first_or_create_with_no_parameters + parrot = Bird.where(:color => 'green').first_or_create + assert_kind_of Bird, parrot + assert !parrot.persisted? + assert_equal 'green', parrot.color + end + + def test_first_or_create_with_block + parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parrot' } + assert_kind_of Bird, parrot + assert parrot.persisted? + assert_equal 'green', parrot.color + assert_equal 'parrot', parrot.name + + same_parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parakeet' } + assert_equal parrot, same_parrot + end + + def test_first_or_create_with_array + several_green_birds = Bird.where(:color => 'green').first_or_create([{:name => 'parrot'}, {:name => 'parakeet'}]) + assert_kind_of Array, several_green_birds + several_green_birds.each { |bird| assert bird.persisted? } + + same_parrot = Bird.where(:color => 'green').first_or_create([{:name => 'hummingbird'}, {:name => 'macaw'}]) + assert_kind_of Bird, same_parrot + assert_equal several_green_birds.first, same_parrot + end + + def test_first_or_create_bang_with_valid_options + parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot') + assert_kind_of Bird, parrot + assert parrot.persisted? + assert_equal 'parrot', parrot.name + assert_equal 'green', parrot.color + + same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet') + assert_kind_of Bird, same_parrot + assert same_parrot.persisted? + assert_equal parrot, same_parrot + end + + def test_first_or_create_bang_with_invalid_options + assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) } + end + + def test_first_or_create_bang_with_no_parameters + assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create! } + end + + def test_first_or_create_bang_with_valid_block + parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parrot' } + assert_kind_of Bird, parrot + assert parrot.persisted? + assert_equal 'green', parrot.color + assert_equal 'parrot', parrot.name + + same_parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parakeet' } + assert_equal parrot, same_parrot + end + + def test_first_or_create_bang_with_invalid_block + assert_raise(ActiveRecord::RecordInvalid) do + parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.pirate_id = 1 } + end + end + + def test_first_or_create_with_valid_array + several_green_birds = Bird.where(:color => 'green').first_or_create!([{:name => 'parrot'}, {:name => 'parakeet'}]) + assert_kind_of Array, several_green_birds + several_green_birds.each { |bird| assert bird.persisted? } + + same_parrot = Bird.where(:color => 'green').first_or_create!([{:name => 'hummingbird'}, {:name => 'macaw'}]) + assert_kind_of Bird, same_parrot + assert_equal several_green_birds.first, same_parrot + end + + def test_first_or_create_with_invalid_array + assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!([ {:name => 'parrot'}, {:pirate_id => 1} ]) } + end + + def test_first_or_new + parrot = Bird.where(:color => 'green').first_or_new(:name => 'parrot') + assert_kind_of Bird, parrot + assert !parrot.persisted? + assert parrot.valid? + assert parrot.new_record? + assert_equal 'parrot', parrot.name + assert_equal 'green', parrot.color + end + + def test_first_or_new_with_no_parameters + parrot = Bird.where(:color => 'green').first_or_new + assert_kind_of Bird, parrot + assert !parrot.persisted? + assert !parrot.valid? + assert parrot.new_record? + assert_equal 'green', parrot.color + end + + def test_first_or_new_with_block + parrot = Bird.where(:color => 'green').first_or_new { |bird| bird.name = 'parrot' } + assert_kind_of Bird, parrot + assert !parrot.persisted? + assert parrot.valid? + assert parrot.new_record? + assert_equal 'green', parrot.color + assert_equal 'parrot', parrot.name + end + + def test_first_or_build_is_alias_for_first_or_new + birds = Bird.scoped + assert birds.respond_to?(:first_or_build) + assert_equal birds.method(:first_or_new), birds.method(:first_or_build) + end + def test_explicit_create_scope hens = Bird.where(:name => 'hen') assert_equal 'hen', hens.new.name diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 4e77a6e803..37874c2ea1 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -1018,23 +1018,84 @@ If you want to find both by name and locked, you can chain these finders togethe WARNING: Up to and including Rails 3.1, when the number of arguments passed to a dynamic finder method is lesser than the number of fields, say Client.find_by_name_and_locked("Ryan"), the behavior is to pass +nil+ as the missing argument. This is *unintentional* and this behavior will be changed in Rails 3.2 to throw an +ArgumentError+. -There's another set of dynamic finders that let you find or create/initialize objects if they aren't found. These work in a similar fashion to the other finders and can be used like +find_or_create_by_first_name(params[:first_name])+. Using this will first perform a find and then create if the find returns +nil+. The SQL looks like this for +Client.find_or_create_by_first_name("Ryan")+: +h3. Find or build a new object + +It's common that you need to find a record or create it if it doesn't exist. You can do that with the +first_or_create+ and +first_or_create!+ methods. + +h4. +first_or_create+ + +The +first_or_create+ method checks whether +first+ returns +nil+ or not. If it does return +nil+, then +create+ is called. This is very powerful when coupled with the +where+ method. Let's see an example. + +Suppose you want to find a client named 'Andy', and if there's none, create one and additionally set his +locked+ attribute to false. You can do so by running: + + +Client.where(:first_name => 'Andy').first_or_create(:locked => false) +# => + + +The SQL generated by this method looks like this: -SELECT * FROM clients WHERE (clients.first_name = 'Ryan') LIMIT 1 +SELECT * FROM clients WHERE (clients.first_name = 'Andy') LIMIT 1 BEGIN -INSERT INTO clients (first_name, updated_at, created_at, orders_count, locked) - VALUES('Ryan', '2008-09-28 15:39:12', '2008-09-28 15:39:12', 0, '0') +INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) VALUES ('2011-08-30 05:22:57', 'Andy', 0, NULL, '2011-08-30 05:22:57') COMMIT -+find_or_create+'s sibling, +find_or_initialize+, will find an object and if it does not exist will act similarly to calling +new+ with the arguments you passed in. For example: ++first_or_create+ returns either the record that already existed or the new record. In our case, we didn't already have a client named Andy so the record was created an returned. + +The new record might not be saved to the database; that depends on whether validations passed or not (just like +create+). + +It's also worth noting that +first_or_create+ takes into account the arguments of the +where+ method. In the example above we didn't explicitly pass a +:first_name => 'Andy'+ argument to +first_or_create+. However, that was used when creating the new record because it was already passed before to the +where+ method. + +NOTE: On previous versions of Rails you could do a similar thing with the +find_or_create_by+ method. Following our example, you could also run something like +Client.find_or_create_by_first_name(:first_name => "Andy", :locked => false)+. This method still works, but it's encouraged to use +first_or_create+ because it's more explicit on what arguments are used to _find_ the record and what arguments are used to _create_ it, resulting in less confusion overall. + +h4. +first_or_create!+ + +You can also use +first_or_create!+ to raise an exception if the new record is invalid. Validations are not covered on this guide, but let's assume for a moment that you temporarily add + + + validates :orders_count, :presence => true + + +to your +Client+ model. If you try to create a new +Client+ without passing an +orders_count+, the record will be invalid and an exception will be raised: + + +Client.where(:first_name => 'Andy').first_or_create!(:locked => false) +# => ActiveRecord::RecordInvalid: Validation failed: Orders count can't be blank + + +NOTE: Be sure to check the extensive *Active Record Validations and Callbacks Guide* for more information about validations. + +h4. +first_or_new+ + +The +first_or_new+ method will work just like +first_or_create+ but it will not call +create+ but the +new+. This means that a new model instance will be created in memory but won't be saved to the database. Continuing with the +first_or_create+ example, we now want the client named 'Nick': + + +nick = Client.where(:first_name => 'Nick').first_or_new(:locked => false) +# => + +nick.persisted? +# => false + +nick.new_record? +# => true + + +Because the object is not yet stored in the database, the SQL generated looks like this: + + +SELECT * FROM clients WHERE (clients.first_name = 'Nick') LIMIT 1 + + +When you want to save it to the database, just call +save+: -client = Client.find_or_initialize_by_first_name('Ryan') +nick.save +# => true -will either assign an existing client object with the name "Ryan" to the client local variable, or initialize a new object similar to calling +Client.new(:first_name => 'Ryan')+. From here, you can modify other fields in client by calling the attribute setters on it: +client.locked = true+ and when you want to write it to the database just call +save+ on it. +Just like you can use *+build+* instead of *+new+*, you can use *+first_or_build+* instead of *+first_or_new+*. h3. Finding by SQL -- cgit v1.2.3 From 60d8e4ac28726d04d029b25cff82181a9b0ab5c3 Mon Sep 17 00:00:00 2001 From: Raimonds Simanovskis Date: Tue, 30 Aug 2011 20:37:16 +0300 Subject: Ensure correct ordering of results in test_update_all_with_joins_and_offset_and_order Last two asserts in this test assume that all_comments are ordered by posts.id and then by comments.id therefore additional ordering is added. Without it test was failing on Oracle which returned results in different order. --- activerecord/test/cases/relations_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 615551a279..da96afd718 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -1018,7 +1018,7 @@ class RelationTest < ActiveRecord::TestCase end def test_update_all_with_joins_and_offset_and_order - all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('posts.id') + all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('posts.id', 'comments.id') count = all_comments.count comments = all_comments.offset(1) -- cgit v1.2.3 From ee822f257e2f3f3b571772f30ae3a8edd69538c3 Mon Sep 17 00:00:00 2001 From: Nicolas Hock Isaza Date: Tue, 30 Aug 2011 15:40:09 -0500 Subject: Adding `first_or_new` documentation to the AR Querying guide. --- railties/guides/source/active_record_querying.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 37874c2ea1..54ce7a25ab 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -1069,7 +1069,7 @@ NOTE: Be sure to check the extensive *Active Record Validations and Callbacks Gu h4. +first_or_new+ -The +first_or_new+ method will work just like +first_or_create+ but it will not call +create+ but the +new+. This means that a new model instance will be created in memory but won't be saved to the database. Continuing with the +first_or_create+ example, we now want the client named 'Nick': +The +first_or_new+ method will work just like +first_or_create+ but it will not call +create+ but +new+. This means that a new model instance will be created in memory but won't be saved to the database. Continuing with the +first_or_create+ example, we now want the client named 'Nick': nick = Client.where(:first_name => 'Nick').first_or_new(:locked => false) -- cgit v1.2.3 From e5f2b0d75f29cd7d9e11e8008d410caf48ab1078 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 30 Aug 2011 20:47:01 -0300 Subject: Revert "Merge pull request #2647 from dmathieu/no_rescue" This reverts commit 125b1b0b9180ec8f0135da185e77250d2b8a4bea. --- actionpack/lib/sprockets/helpers/rails_helper.rb | 8 ++++++-- actionpack/test/abstract_unit.rb | 6 +----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 7a2bf8bef6..062aa4dae5 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -58,8 +58,12 @@ module Sprockets private def debug_assets? - config = Rails.application.config.assets - config.allow_debugging && (config.debug || params[:debug_assets]) + begin + config = Rails.application.config.assets + config.allow_debugging && (config.debug || params[:debug_assets]) + rescue NoMethodError + false + end end # Override to specify an alternative prefix for asset path generation. diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index aa7a01f6c9..24d071df39 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -142,11 +142,7 @@ class RoutedRackApp end class BasicController - attr_accessor :request, :params - - def initialize - @params = {} - end + attr_accessor :request def config @config ||= ActiveSupport::InheritableOptions.new(ActionController::Base.config).tap do |config| -- cgit v1.2.3 From f4492b8656f7a1937a574d9a8ea1f065e10df36d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 30 Aug 2011 22:49:03 -0300 Subject: Bump sprockets up --- actionpack/actionpack.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 59d5bbc5ed..65b364f872 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -24,7 +24,7 @@ Gem::Specification.new do |s| s.add_dependency('rack', '~> 1.3.2') s.add_dependency('rack-test', '~> 0.6.1') s.add_dependency('rack-mount', '~> 0.8.2') - s.add_dependency('sprockets', '~> 2.0.0.beta.15') + s.add_dependency('sprockets', '~> 2.0.0') s.add_dependency('erubis', '~> 2.7.0') s.add_development_dependency('tzinfo', '~> 0.3.29') -- cgit v1.2.3 From 331dad14bc0623a8b1f24be88f2933c20c346c74 Mon Sep 17 00:00:00 2001 From: Ray Baxter Date: Tue, 30 Aug 2011 22:32:09 -0700 Subject: don't need edgeapi now that we are on 3.1 --- railties/guides/source/3_1_release_notes.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/3_1_release_notes.textile b/railties/guides/source/3_1_release_notes.textile index 087926f98d..156987efc4 100644 --- a/railties/guides/source/3_1_release_notes.textile +++ b/railties/guides/source/3_1_release_notes.textile @@ -170,7 +170,7 @@ class PostsController < ActionController::Base end -You can restrict it to some actions by using +:only+ or +:except+. Please read the docs at "ActionController::Streaming":http://edgeapi.rubyonrails.org/classes/ActionController/Streaming.html for more information. +You can restrict it to some actions by using +:only+ or +:except+. Please read the docs at "ActionController::Streaming":http://api.rubyonrails.org/classes/ActionController/Streaming.html for more information. * The redirect route method now also accepts a hash of options which will only change the parts of the url in question, or an object which responds to call, allowing for redirects to be reused. -- cgit v1.2.3 From 73263f6c81936b199f7410991a23ea380a58e005 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Wed, 31 Aug 2011 01:44:59 -0700 Subject: adds the release notes of 3.1 to the index --- railties/guides/source/index.html.erb | 4 ++++ railties/guides/source/layout.html.erb | 1 + 2 files changed, 5 insertions(+) diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb index b7813086d7..214155c088 100644 --- a/railties/guides/source/index.html.erb +++ b/railties/guides/source/index.html.erb @@ -174,6 +174,10 @@ Ruby on Rails Guides

Release Notes

+<%= guide("Ruby on Rails 3.1 Release Notes", '3_1_release_notes.html') do %> +

Release notes for Rails 3.1.

+<% end %> + <%= guide("Ruby on Rails 3.0 Release Notes", '3_0_release_notes.html') do %>

Release notes for Rails 3.0.

<% end %> diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb index 5f8ee57517..3ccbc3a477 100644 --- a/railties/guides/source/layout.html.erb +++ b/railties/guides/source/layout.html.erb @@ -84,6 +84,7 @@
Ruby on Rails Guides Guidelines
Release Notes
+
Ruby on Rails 3.1 Release Notes
Ruby on Rails 3.0 Release Notes
Ruby on Rails 2.3 Release Notes
Ruby on Rails 2.2 Release Notes
-- cgit v1.2.3 From d7be97ec31f5d972e01fb11b05ca4b36f581c779 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Wed, 31 Aug 2011 01:52:43 -0700 Subject: release notes: adds a couple of blank lines to get the markup right --- railties/guides/source/3_1_release_notes.textile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/railties/guides/source/3_1_release_notes.textile b/railties/guides/source/3_1_release_notes.textile index 087926f98d..9ca77d0657 100644 --- a/railties/guides/source/3_1_release_notes.textile +++ b/railties/guides/source/3_1_release_notes.textile @@ -346,6 +346,7 @@ has_many :things, :conditions => proc { "foo = #{bar}" } # after Inside the proc, +self+ is the object which is the owner of the association, unless you are eager loading the association, in which case +self+ is the class which the association is within. You can have any "normal" conditions inside the proc, so the following will work too: + has_many :things, :conditions => proc { ["foo = ?", bar] } @@ -353,6 +354,7 @@ has_many :things, :conditions => proc { ["foo = ?", bar] } * Previously +:insert_sql+ and +:delete_sql+ on +has_and_belongs_to_many+ association allowed you to call 'record' to get the record being inserted or deleted. This is now passed as an argument to the proc. * Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePassword) to encapsulate dead-simple password usage with BCrypt encryption and salting. + # Schema: User(name:string, password_digest:string, password_salt:string) class User < ActiveRecord::Base -- cgit v1.2.3 From e746c4047cd34accd7f63aa5d09cbb35011c24e2 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Wed, 31 Aug 2011 02:04:36 -0700 Subject: syncs assets guide with what's in 3-1-stable --- railties/guides/source/asset_pipeline.textile | 38 +++++++++++++++++++-------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 2695ba9ec1..96b11dbf63 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -15,7 +15,7 @@ h3. What is the Asset Pipeline? The asset pipeline provides a framework to concatenate and minify or compress JavaScript and CSS assets. It also adds the ability to write these assets in other languages such as CoffeeScript, SCSS and ERB. -Prior to Rails 3.1 these features were added through third-party Ruby libraries such as Jammit and Sprockets. Rails 3.1 includes the +sprockets-rails+ gem, which depends on the +sprockets+ gem, by default. +Prior to Rails 3.1 these features were added through third-party Ruby libraries such as Jammit and Sprockets. Rails 3.1 is integrated with Sprockets throught ActionPack which depends on the +sprockets+ gem, by default. By having this as a core feature of Rails, all developers can benefit from the power of having their assets pre-processed, compressed and minified by one central library, Sprockets. This is part of Rails' "Fast by default" strategy as outlined by DHH in his 2011 keynote at Railsconf. @@ -27,6 +27,7 @@ config.assets.enabled = false It is recommended that you use the defaults for all new apps. + h4. Main Features The first feature of the pipeline is to concatenate assets. This is important in a production environment, as it reduces the number of requests that a browser must make to render a web page. While Rails already has a feature to concatenate these types of assets -- by placing +:cache => true+ at the end of tags such as +javascript_include_tag+ and +stylesheet_link_tag+ -- many people do not use it. @@ -74,11 +75,14 @@ The other problem is that when static assets are deployed with each new release Fingerprinting avoids all these problems by ensuring filenames are consistent based on their content. +Fingerprinting is enabled by default for production and disabled for all the others environments. You can enable or disable it in your configuration through the +config.assets.digest+ option. + More reading: * "Optimize caching":http://code.google.com/speed/page-speed/docs/caching.html * "Revving Filenames: don’t use querystring":http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/ + h3. How to Use the Asset Pipeline In previous versions of Rails, all assets were located in subdirectories of +public+ such as +images+, +javascripts+ and +stylesheets+. With the asset pipeline, the preferred location for these assets is now the +app/assets+ directory. Files in this directory are served by the Sprockets middleware included in the sprockets gem. @@ -247,14 +251,7 @@ When the +debug_assets+ parameter is set, this line is expanded out into three s This allows the individual parts of an asset to be rendered and debugged separately. -Additionally if the +config.assets.debug+ is set to true you can debug your assets passing the +:debug+ option to the assets tags: - - -<%= javascript_include_tag :application, :debug => true %> - - - -NOTE. Assets debugging is turned on by default in development and test environments. You can set +config.assets.allow_debugging+ to false to turn it off. +NOTE. Assets debugging is turned on by default in development and test environments. h3. In Production @@ -271,7 +268,7 @@ The MD5 is generated from the contents of the compiled files, and is included in Sprockets also sets the +Cache-Control+ HTTP header to +max-age=31536000+. This signals all caches between your server and the client browser that this content (the file served) can be cached for 1 year. The effect of this is to reduce the number of requests for this asset from your server; the asset has a good chance of being in the local browser cache or some intermediate cache. -This behavior is controlled by the setting of +config.action_controller.perform_caching+ setting in Rails (which is +true+ for production, +false+ for everything else). This value is propagated to Sprockets during initialization for use when action_controller is not available. +This behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). h4. Precompiling Assets @@ -307,6 +304,20 @@ If you have other manifests or individual stylesheets and JavaScript files to in config.assets.precompile += ['admin.js', 'admin.css', 'swfObject.js'] +The rake task also generates a +manifest.yml+ that contains a list with all your assets and their fingerprints, using this manifest file the assets helpers avoid hitting to Sprockets to recalculate MD5 hashes for files. Manifest file typically look like this: + + +--- +rails.png: rails-bd9ad5a560b5a3a7be0808c5cd76a798.png +jquery-ui.min.js: jquery-ui-7e33882a28fc84ad0e0e47e46cbf901c.min.js +jquery.min.js: jquery-8a50feed8d29566738ad005e19fe1c2d.min.js +application.js: application-3fdab497b8fb70d20cfc5495239dfc29.js +application.css: application-8af74128f904600e41a6e39241464e03.css + + +The manifest file is generated by default in same folder of your precompiled assets, you can change the location of the file setting the +config.assets.manifest+ option with the full path of the folder where you want save it. + + Precompiled assets exist on the filesystem and are served directly by your webserver. They do not have far-future headers by default, so to get the benefit of fingerprinting you'll have to update your server configuration to add them. For Apache: @@ -325,12 +336,16 @@ For Apache: -TODO: NGINX instructions +TODO: nginx instructions When files are precompiled, Sprockets also creates a "Gzip":http://en.wikipedia.org/wiki/Gzip (.gz) version of your assets. This avoids the server having to do this for any requests; it can simply read the compressed files from disc. You must configure your server to use gzip compression and serve the compressed assets that will be stored in the public/assets folder. The following configuration options can be used: TODO: Apache instructions +TODO: nginx instructions + +By default Rails assumes that you have your files precompiled in the production environment, if you want use live compiling (compile your assets during runtime) in production you must set the +config.assets.compile+ to true. You can use this option to fallback to Sprockets when you are using precompiled assets but there are any missing precompiled files. If +config.assets.compile+ option is set to false and there are missing precompiled files you will get an "AssetNoPrecompiledError" indicating the name of the missing file. + h3. Customizing the Pipeline @@ -378,6 +393,7 @@ To enable this, pass a +new+ Object to the config option in +application.rb+: config.assets.css_compressor = Transformer.new + h4. Changing the _assets_ Path The public path that Sprockets uses by default is +/assets+. -- cgit v1.2.3 From 6d772c0953b418da774b2c3bf5cc297508669da7 Mon Sep 17 00:00:00 2001 From: Semyon Perepelitsa Date: Wed, 31 Aug 2011 14:40:45 +0400 Subject: Fix typo: => instead of = --- railties/guides/source/3_1_release_notes.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/3_1_release_notes.textile b/railties/guides/source/3_1_release_notes.textile index ba36735a0b..b9850daf15 100644 --- a/railties/guides/source/3_1_release_notes.textile +++ b/railties/guides/source/3_1_release_notes.textile @@ -245,7 +245,7 @@ class User < ActiveRecord::Base has_one :account end -user.build_account{ |a| a.credit_limit => 100.0 } +user.build_account{ |a| a.credit_limit = 100.0 } * Added ActiveRecord::Base.attribute_names to return a list of attribute names. This will return an empty array if the model is abstract or the table does not exist. -- cgit v1.2.3 From 30d65da17e5fb1cdd3f10a6d14f4295b57e26286 Mon Sep 17 00:00:00 2001 From: Rodrigo Rosenfeld Rosas Date: Wed, 31 Aug 2011 10:50:08 -0300 Subject: Fix logic in 3.1 release notes sentence --- railties/guides/source/3_1_release_notes.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/3_1_release_notes.textile b/railties/guides/source/3_1_release_notes.textile index 4412d32cce..7de8866ff6 100644 --- a/railties/guides/source/3_1_release_notes.textile +++ b/railties/guides/source/3_1_release_notes.textile @@ -271,7 +271,7 @@ Post.new(params[:post], :as => :admin) * +ConnectionManagement+ middleware is changed to clean up the connection pool after the rack body has been flushed. -* Added an +update_column+ method on Active Record. This new method updates a given attribute on an object, skipping validations and callbacks. It is recommended to use +update_attribute+ unless you are sure you do not want to execute any callback, including the modification of the +updated_at+ column. It should not be called on new records. +* Added an +update_column+ method on Active Record. This new method updates a given attribute on an object, skipping validations and callbacks. It is not recommended to use +update_attribute+ unless you are sure you do not want to execute any callback, including the modification of the +updated_at+ column. It should not be called on new records. * Associations with a +:through+ option can now use any association as the through or source association, including other associations which have a +:through+ option and +has_and_belongs_to_many+ associations. -- cgit v1.2.3 From 73d34feb4c6b658d28c83ac6c69413b737565b23 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Wed, 31 Aug 2011 09:42:43 -0500 Subject: Always enable digest and compile in the Rake task --- actionpack/lib/sprockets/assets.rake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 7594ee4296..5698f22080 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -13,8 +13,9 @@ namespace :assets do # Ensure that action view is loaded and the appropriate sprockets hooks get executed ActionView::Base - # Always perform caching so that asset_path appends the timestamps to file references. - Rails.application.config.action_controller.perform_caching = true + # Always calculate digests and compile files + Rails.application.config.assets.digest = true + Rails.application.config.assets.compile = true config = Rails.application.config env = Rails.application.assets -- cgit v1.2.3 From 508f33f35c9ce7a8973c1cf3466223313dfcfb24 Mon Sep 17 00:00:00 2001 From: Chris Griego Date: Tue, 30 Aug 2011 21:22:14 -0500 Subject: Revert "Ruby 1.8.7+ provides to_date/to_datetime, AS just makes them public." to support date implementations without private to_date/to_datetime on Time (home_run). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 080345baca1076a9788dff4803153600aec31f86. Signed-off-by: José Valim --- .../active_support/core_ext/time/conversions.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb index d9d5e02778..49ac18d245 100644 --- a/activesupport/lib/active_support/core_ext/time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/time/conversions.rb @@ -55,9 +55,31 @@ class Time utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon) end + # Converts a Time object to a Date, dropping hour, minute, and second precision. + # + # my_time = Time.now # => Mon Nov 12 22:59:51 -0500 2007 + # my_time.to_date # => Mon, 12 Nov 2007 + # + # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009 + # your_time.to_date # => Tue, 13 Jan 2009 + def to_date + ::Date.new(year, month, day) + end unless method_defined?(:to_date) + # A method to keep Time, Date and DateTime instances interchangeable on conversions. # In this case, it simply returns +self+. def to_time self end unless method_defined?(:to_time) + + # Converts a Time instance to a Ruby DateTime instance, preserving UTC offset. + # + # my_time = Time.now # => Mon Nov 12 23:04:21 -0500 2007 + # my_time.to_datetime # => Mon, 12 Nov 2007 23:04:21 -0500 + # + # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009 + # your_time.to_datetime # => Tue, 13 Jan 2009 13:13:03 -0500 + def to_datetime + ::DateTime.civil(year, month, day, hour, min, sec, Rational(utc_offset, 86400)) + end unless method_defined?(:to_datetime) end -- cgit v1.2.3 From dffdd829930e664cef522f34730d5987be348596 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Mon, 29 Aug 2011 16:28:11 -0500 Subject: Read digests of assets from manifest.yml if config.assets.manifest is on --- actionpack/lib/sprockets/assets.rake | 10 +++- actionpack/lib/sprockets/helpers/rails_helper.rb | 17 +++++- actionpack/lib/sprockets/railtie.rb | 6 ++ railties/lib/rails/application/configuration.rb | 9 +-- .../rails/app/templates/config/application.rb | 4 ++ railties/test/application/assets_test.rb | 65 ++++++++++++++++++++++ 6 files changed, 105 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 5698f22080..7ee82ee530 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -19,7 +19,8 @@ namespace :assets do config = Rails.application.config env = Rails.application.assets - target = Rails.root.join("public#{config.assets.prefix}") + target = Pathname.new(File.join(Rails.public_path, config.assets.prefix)) + manifest = {} if env.respond_to?(:each_logical_path) config.assets.precompile.each do |path| @@ -31,6 +32,7 @@ namespace :assets do end if asset = env.find_asset(logical_path) + manifest[logical_path] = asset.digest_path filename = target.join(asset.digest_path) mkdir_p filename.dirname asset.write_to(filename) @@ -44,6 +46,12 @@ namespace :assets do assets << {:to => target} env.precompile(*assets) end + + if config.assets.manifest + File.open("#{target}/manifest.yml", 'w') do |f| + YAML.dump(manifest, f) + end + end end end diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 062aa4dae5..8e7eb182fd 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -14,6 +14,7 @@ module Sprockets paths = RailsHelper::AssetPaths.new(config, controller) paths.asset_environment = asset_environment paths.asset_prefix = asset_prefix + paths.asset_digests = asset_digests paths end end @@ -76,6 +77,10 @@ module Sprockets Rails.application.config.assets.prefix end + def asset_digests + Rails.application.config.assets.digests + end + # Override to specify an alternative asset environment for asset # path generation. The environment should already have been mounted # at the prefix returned by +asset_prefix+. @@ -84,7 +89,9 @@ module Sprockets end class AssetPaths < ::ActionView::AssetPaths #:nodoc: - attr_accessor :asset_environment, :asset_prefix + attr_accessor :asset_environment, :asset_prefix, :asset_digests + + class AssetNotPrecompiledError < StandardError; end def compute_public_path(source, dir, ext=nil, include_host=true, protocol=nil) super(source, asset_prefix, ext, include_host, protocol) @@ -103,6 +110,14 @@ module Sprockets end def digest_for(logical_path) + if asset_digests && (digest = asset_digests[logical_path]) + return digest + end + + if digest.nil? && Rails.application.config.assets.precompile_only + raise AssetNotPrecompiledError + end + if asset = asset_environment[logical_path] return asset.digest_path end diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb index c21bf57935..680cb980ff 100644 --- a/actionpack/lib/sprockets/railtie.rb +++ b/actionpack/lib/sprockets/railtie.rb @@ -26,6 +26,12 @@ module Sprockets end end + if config.assets.manifest + if File.exist?(path = File.join(Rails.public_path, config.assets.prefix, "manifest.yml")) + config.assets.digests = YAML.load_file(path) + end + end + ActiveSupport.on_load(:action_view) do include ::Sprockets::Helpers::RailsHelper diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 5d7bd3282d..7f4db0a19f 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -42,10 +42,11 @@ module Rails @assets.version = '' @assets.debug = false @assets.allow_debugging = false - - @assets.cache_store = [ :file_store, "#{root}/tmp/cache/assets/" ] - @assets.js_compressor = nil - @assets.css_compressor = nil + @assets.manifest = true + @assets.precompile_only = false + @assets.cache_store = [ :file_store, "#{root}/tmp/cache/assets/" ] + @assets.js_compressor = nil + @assets.css_compressor = nil end def compiled_asset_path diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 3891829150..30a75200cb 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -52,6 +52,10 @@ module <%= app_const_base %> <% unless options.skip_sprockets? -%> # Enable the asset pipeline config.assets.enabled = true + + # Create a manifest with the hashes of your assets when you run "rake assets:precompile". + # Use this if you don't have a JavaScript engine in your production servers + config.assets.manifest = true <% end -%> end end diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index a8d1382e94..9df10e84d8 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -62,6 +62,71 @@ module ApplicationTests end end + test "precompile don't create a manifest file when manifest option is off" do + app_file "app/assets/javascripts/application.js", "alert();" + app_file "config/initializers/manifest.rb", "Rails.application.config.assets.manifest = false" + + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + + assert !File.exist?("#{app_path}/public/assets/manifest.yml") + end + + test "precompile creates a manifest file with all the assets listed when manifest option is on" do + app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" + app_file "app/assets/javascripts/application.js", "alert();" + + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + + manifest = "#{app_path}/public/assets/manifest.yml" + + assets = YAML.load_file(manifest) + assert_match /application-([0-z]+)\.js/, assets["application.js"] + assert_match /application-([0-z]+)\.css/, assets["application.css"] + end + + test "assets do not require any assets group gem when manifest option is on and manifest file is present" do + app_file "app/assets/javascripts/application.js", "alert();" + + ENV["RAILS_ENV"] = "production" + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + manifest = "#{app_path}/public/assets/manifest.yml" + assets = YAML.load_file(manifest) + asset_path = assets["application.js"] + + require "#{app_path}/config/environment" + + # Checking if Uglifier is defined we can know if Sprockets was reached or not + assert !defined?(Uglifier) + get "/assets/#{asset_path}" + assert_match "alert()", last_response.body + assert !defined?(Uglifier) + end + + test "assets raise AssetNotPrecompiledError if config.assets.precompile_only is on and file isn't precompiled" do + app_file "app/assets/javascripts/app.js", "alert();" + app_file "app/views/posts/index.html.erb", "<%= javascript_include_tag 'app' %>" + app_file "config/initializers/precompile_only.rb", "Rails.application.config.assets.precompile_only = true" + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + match '/posts', :to => "posts#index" + end + RUBY + + ENV["RAILS_ENV"] = "production" + require "#{app_path}/config/environment" + class ::PostsController < ActionController::Base ; end + + get '/posts' + assert_match /AssetNotPrecompiledError/, last_response.body + end + test "precompile appends the md5 hash to files referenced with asset_path and run in the provided RAILS_ENV" do app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" -- cgit v1.2.3 From fa04c37f45ca9299a5efb426913488b678c178ce Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Wed, 31 Aug 2011 12:42:54 -0500 Subject: Backport b0f30631662 to master --- .../lib/rails/generators/rails/app/templates/config/application.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 30a75200cb..13fbe9e526 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -53,9 +53,8 @@ module <%= app_const_base %> # Enable the asset pipeline config.assets.enabled = true - # Create a manifest with the hashes of your assets when you run "rake assets:precompile". - # Use this if you don't have a JavaScript engine in your production servers - config.assets.manifest = true + # Version of your assets, change this if you want to expire all your assets + config.assets.version = '1.0' <% end -%> end end -- cgit v1.2.3 From f236e00189b5a6cf0cebac5c275f64d41d73428d Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Wed, 31 Aug 2011 12:47:33 -0500 Subject: Backport f443f9cb0c64 to master --- actionpack/lib/sprockets/assets.rake | 6 ++-- actionpack/lib/sprockets/helpers/rails_helper.rb | 29 ++++++-------------- actionpack/lib/sprockets/railtie.rb | 6 ++-- actionpack/test/template/sprockets_helper_test.rb | 6 ++-- railties/lib/rails/application/configuration.rb | 5 ++-- .../config/environments/development.rb.tt | 3 -- .../templates/config/environments/production.rb.tt | 6 ++++ railties/test/application/assets_test.rb | 32 +++++++++++----------- 8 files changed, 41 insertions(+), 52 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 7ee82ee530..54907abb39 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -47,10 +47,8 @@ namespace :assets do env.precompile(*assets) end - if config.assets.manifest - File.open("#{target}/manifest.yml", 'w') do |f| - YAML.dump(manifest, f) - end + File.open("#{target}/manifest.yml", 'w') do |f| + YAML.dump(manifest, f) end end end diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 8e7eb182fd..975dc9e80c 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -61,7 +61,7 @@ module Sprockets def debug_assets? begin config = Rails.application.config.assets - config.allow_debugging && (config.debug || params[:debug_assets]) + config.compile && (config.debug || params[:debug_assets]) rescue NoMethodError false end @@ -114,22 +114,21 @@ module Sprockets return digest end - if digest.nil? && Rails.application.config.assets.precompile_only - raise AssetNotPrecompiledError - end - - if asset = asset_environment[logical_path] - return asset.digest_path + if Rails.application.config.assets.compile + if asset = asset_environment[logical_path] + return asset.digest_path + end + return logical_path + else + raise AssetNotPrecompiledError.new("#{logical_path} isn't precompiled") end - - logical_path end def rewrite_asset_path(source, dir) if source[0] == ?/ source else - source = digest_for(source) if performing_caching? + source = digest_for(source) if Rails.application.config.assets.digest source = File.join(dir, source) source = "/#{source}" unless source =~ /^\// source @@ -143,16 +142,6 @@ module Sprockets source end end - - def performing_caching? - # When included in Sprockets::Context, we need to ask the - # top-level config as the controller is not available. - if config.action_controller.present? - config.action_controller.perform_caching - else - config.perform_caching - end - end end end end diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb index 680cb980ff..4adfd000f8 100644 --- a/actionpack/lib/sprockets/railtie.rb +++ b/actionpack/lib/sprockets/railtie.rb @@ -26,10 +26,8 @@ module Sprockets end end - if config.assets.manifest - if File.exist?(path = File.join(Rails.public_path, config.assets.prefix, "manifest.yml")) - config.assets.digests = YAML.load_file(path) - end + if File.exist?(path = File.join(Rails.public_path, config.assets.prefix, "manifest.yml")) + config.assets.digests = YAML.load_file(path) end ActiveSupport.on_load(:action_view) do diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb index 6c1f97a44a..ae4cb1f0aa 100644 --- a/actionpack/test/template/sprockets_helper_test.rb +++ b/actionpack/test/template/sprockets_helper_test.rb @@ -30,6 +30,8 @@ class SprocketsHelperTest < ActionView::TestCase @config = config @config.action_controller ||= ActiveSupport::InheritableOptions.new @config.perform_caching = true + @config.assets.digest = true + @config.assets.compile = true end def url_for(*args) @@ -157,7 +159,7 @@ class SprocketsHelperTest < ActionView::TestCase assert_match %r{\n}, javascript_include_tag(:application, :debug => true) - @config.assets.allow_debugging = true + @config.assets.compile = true @config.assets.debug = true assert_match %r{\n}, javascript_include_tag(:application) @@ -198,7 +200,7 @@ class SprocketsHelperTest < ActionView::TestCase assert_match %r{\n}, stylesheet_link_tag(:application, :debug => true) - @config.assets.allow_debugging = true + @config.assets.compile = true @config.assets.debug = true assert_match %r{\n}, stylesheet_link_tag(:application) diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 7f4db0a19f..85e0cd5061 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -41,9 +41,8 @@ module Rails @assets.prefix = "/assets" @assets.version = '' @assets.debug = false - @assets.allow_debugging = false - @assets.manifest = true - @assets.precompile_only = false + @assets.compile = true + @assets.digest = false @assets.cache_store = [ :file_store, "#{root}/tmp/cache/assets/" ] @assets.js_compressor = nil @assets.css_compressor = nil diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index 33f9939ffe..47078e3af9 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -30,9 +30,6 @@ # Do not compress assets config.assets.compress = false - # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets - config.assets.allow_debugging = true - # Expands the lines which load the assets config.assets.debug = true end 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 de56d47688..b4754cfc6d 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 @@ -14,6 +14,12 @@ # Compress JavaScripts and CSS config.assets.compress = true + # Don't fallback to assets pipeline if a precompiled asset is missed + config.assets.compile = false + + # Generate digests for assets URLs + config.assets.digest = true + # Specifies the header that your server uses for sending files # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 9df10e84d8..a4d7fc92f5 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -37,6 +37,8 @@ module ApplicationTests test "assets do not require compressors until it is used" do app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" + app_file "config/initializers/compile.rb", "Rails.application.config.assets.compile = true" + ENV["RAILS_ENV"] = "production" require "#{app_path}/config/environment" @@ -62,18 +64,7 @@ module ApplicationTests end end - test "precompile don't create a manifest file when manifest option is off" do - app_file "app/assets/javascripts/application.js", "alert();" - app_file "config/initializers/manifest.rb", "Rails.application.config.assets.manifest = false" - - capture(:stdout) do - Dir.chdir(app_path){ `bundle exec rake assets:precompile` } - end - - assert !File.exist?("#{app_path}/public/assets/manifest.yml") - end - - test "precompile creates a manifest file with all the assets listed when manifest option is on" do + test "precompile creates a manifest file with all the assets listed" do app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" app_file "app/assets/javascripts/application.js", "alert();" @@ -88,7 +79,7 @@ module ApplicationTests assert_match /application-([0-z]+)\.css/, assets["application.css"] end - test "assets do not require any assets group gem when manifest option is on and manifest file is present" do + test "assets do not require any assets group gem when manifest file is present" do app_file "app/assets/javascripts/application.js", "alert();" ENV["RAILS_ENV"] = "production" @@ -108,10 +99,8 @@ module ApplicationTests assert !defined?(Uglifier) end - test "assets raise AssetNotPrecompiledError if config.assets.precompile_only is on and file isn't precompiled" do - app_file "app/assets/javascripts/app.js", "alert();" + test "assets raise AssetNotPrecompiledError when manifest file is present and requested file isn't precompiled" do app_file "app/views/posts/index.html.erb", "<%= javascript_include_tag 'app' %>" - app_file "config/initializers/precompile_only.rb", "Rails.application.config.assets.precompile_only = true" app_file "config/routes.rb", <<-RUBY AppTemplate::Application.routes.draw do @@ -120,15 +109,25 @@ module ApplicationTests RUBY ENV["RAILS_ENV"] = "production" + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + + # Create file after of precompile + app_file "app/assets/javascripts/app.js", "alert();" + require "#{app_path}/config/environment" class ::PostsController < ActionController::Base ; end get '/posts' assert_match /AssetNotPrecompiledError/, last_response.body + assert_match /app.js isn't precompiled/, last_response.body end test "precompile appends the md5 hash to files referenced with asset_path and run in the provided RAILS_ENV" do app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" + # digest is default in false, we must enable it for test environment + app_file "config/initializers/compile.rb", "Rails.application.config.assets.digest = true" # capture(:stdout) do Dir.chdir(app_path){ `bundle exec rake assets:precompile RAILS_ENV=test` } @@ -139,6 +138,7 @@ module ApplicationTests test "precompile appends the md5 hash to files referenced with asset_path and run in production as default even using RAILS_GROUPS=assets" do app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" + app_file "config/initializers/compile.rb", "Rails.application.config.assets.compile = true" ENV["RAILS_ENV"] = nil capture(:stdout) do -- cgit v1.2.3 From d0b3937b8fe2cbc4385e843d47249af3e7181a83 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 30 Aug 2011 16:30:53 -0500 Subject: Set default location of manifest with config.assets.manifest --- actionpack/lib/sprockets/assets.rake | 3 ++- actionpack/lib/sprockets/railtie.rb | 8 +++++++- railties/lib/rails/application/configuration.rb | 1 + .../app/templates/config/environments/production.rb.tt | 3 +++ railties/test/application/assets_test.rb | 17 +++++++++++++++++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 54907abb39..6f38ece0c3 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -21,6 +21,7 @@ namespace :assets do env = Rails.application.assets target = Pathname.new(File.join(Rails.public_path, config.assets.prefix)) manifest = {} + manifest_path = config.assets.manifest || target if env.respond_to?(:each_logical_path) config.assets.precompile.each do |path| @@ -47,7 +48,7 @@ namespace :assets do env.precompile(*assets) end - File.open("#{target}/manifest.yml", 'w') do |f| + File.open("#{manifest_path}/manifest.yml", 'w') do |f| YAML.dump(manifest, f) end end diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb index 4adfd000f8..7927b7bc2c 100644 --- a/actionpack/lib/sprockets/railtie.rb +++ b/actionpack/lib/sprockets/railtie.rb @@ -26,7 +26,13 @@ module Sprockets end end - if File.exist?(path = File.join(Rails.public_path, config.assets.prefix, "manifest.yml")) + if config.assets.manifest + path = File.join(config.assets.manifest, "manifest.yml") + else + path = File.join(Rails.public_path, config.assets.prefix, "manifest.yml") + end + + if File.exist?(path) config.assets.digests = YAML.load_file(path) end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 85e0cd5061..fa7e3b820b 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -43,6 +43,7 @@ module Rails @assets.debug = false @assets.compile = true @assets.digest = false + @assets.manifest = "#{root}/public#{@assets.prefix}" @assets.cache_store = [ :file_store, "#{root}/tmp/cache/assets/" ] @assets.js_compressor = nil @assets.css_compressor = nil 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 b4754cfc6d..64e2c09467 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 @@ -20,6 +20,9 @@ # Generate digests for assets URLs config.assets.digest = true + # Defaults to Rails.root.join("public/assets") + # config.assets.manifest = YOUR_PATH + # Specifies the header that your server uses for sending files # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index a4d7fc92f5..ccadf0b2c0 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -79,6 +79,23 @@ module ApplicationTests assert_match /application-([0-z]+)\.css/, assets["application.css"] end + test "precompile creates a manifest file in a custom path with all the assets listed" do + app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" + app_file "app/assets/javascripts/application.js", "alert();" + FileUtils.mkdir "#{app_path}/shared" + app_file "config/initializers/manifest.rb", "Rails.application.config.assets.manifest = '#{app_path}/shared'" + + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + + manifest = "#{app_path}/shared/manifest.yml" + + assets = YAML.load_file(manifest) + assert_match /application-([0-z]+)\.js/, assets["application.js"] + assert_match /application-([0-z]+)\.css/, assets["application.css"] + end + test "assets do not require any assets group gem when manifest file is present" do app_file "app/assets/javascripts/application.js", "alert();" -- cgit v1.2.3 From 87074600d3f7909bce7884c4588aab83f1b3a2d1 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Wed, 31 Aug 2011 13:09:35 -0500 Subject: Fix asset debugging tests to reflect last changes in 3-1-stable --- railties/test/application/asset_debugging_test.rb | 27 +++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb index 38e1e21d17..707abe7191 100644 --- a/railties/test/application/asset_debugging_test.rb +++ b/railties/test/application/asset_debugging_test.rb @@ -33,24 +33,33 @@ module ApplicationTests teardown_app end - test "assets are concatenated when debug is off and allow_debugging is off either if debug_assets param is provided" do - # config.assets.debug and config.assets.allow_debugging are false for production environment + test "assets are concatenated when debug is off and compile is off either if debug_assets param is provided" do + # config.assets.debug and config.assets.compile are false for production environment + ENV["RAILS_ENV"] = "production" + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end require "#{app_path}/config/environment" - # the debug_assets params isn't used if allow_debugging is off + class ::PostsController < ActionController::Base ; end + + # the debug_assets params isn't used if compile is off get '/posts?debug_assets=true' - assert_match %r{}, last_response.body - assert_no_match %r{}, last_response.body + assert_match /}, last_response.body - assert_match %r{}, last_response.body + assert_match / + + + -When the +debug_assets+ parameter is set, this line is expanded out into three separate lines, separating out the combined file into their parts. +h4. Turning Debugging off + +You can turn off debug mode by updating +development.rb+ to include: + + +config.assets.debug = false + + +When debug mode is off Sprockets will concatenate and run the necessary preprocessors on all files, generating the following HTML: - - -This allows the individual parts of an asset to be rendered and debugged separately. +Assets are compiled and cached on the first request after the server is started. Sprockets sets a +must-validate+ Cache-Control HTTP header to reduce request overhead on subsequent requests - on these the browser gets a 304 (not-modified) response. + +If any of the files in the manifest have changed between requests, the server responds with a new compiled file. + +You can put +?debug_assets=true+ or +?debug_assets=1+ at the end of a URL to enable debug mode on-demand, and this will render indivudual tags for each file. This is useful for tracking down exact line numbers when debugging. + +You could potentially also enable compression in development mode as a sanity check, and disable it on-demand as required for debugging. -NOTE. Assets debugging is turned on by default in development and test environments. h3. In Production -In the production environment, assets are served slightly differently. +In the production environment Rails uses the fingerprinting scheme outlined above. By default it is assumed that assets have been precompiled and will be served as static assets by your web server. -On the first request the assets are compiled and cached as described above, however the manifest names are altered to include an MD5 hash. Files names typically look like these: +During the precompilation phase an MD5 is generated from the contents of the compiled files, and inserted into the filenames as they are written to disc. These fingerprinted names are used by the Rails helpers in place of the manifest name. - -/assets/application-908e25f4bf641868d8683022a5b62f54.js -/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css - +For example this: -The MD5 is generated from the contents of the compiled files, and is included in the HTTP +Content-MD5+ header. + +<%= javascript_include_tag "application" %> +<%= stylesheet_link_tag "application" %> + -Sprockets also sets the +Cache-Control+ HTTP header to +max-age=31536000+. This signals all caches between your server and the client browser that this content (the file served) can be cached for 1 year. The effect of this is to reduce the number of requests for this asset from your server; the asset has a good chance of being in the local browser cache or some intermediate cache. +generates something like this: + + + + + -This behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). +The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). under normal circumstances the default options should not be changed. h4. Precompiling Assets -Even though assets are served by Rack::Cache with far-future headers, in high traffic sites this may not be fast enough. +Rails comes bundled with a rake task to compile the asset manifests and other files in the pipeline to disc. -Rails comes bundled with a rake task to compile the manifests to files on disc. These are located in the +public/assets+ directory where they are served by your web server instead of the Rails application. +Compiled assets are written to the location specified in +config.assets.prefix+. The default setting will use the +public/assets+ directory. + +You must use this task either during deployment or locally if you do not have write access to your production filesystem. The rake task is: @@ -288,7 +305,7 @@ Capistrano (v2.8.0+) has a recipe to handle this in deployment. Add the followin load 'deploy/assets' -This links the folder specified in +config.assets.prefix+ to +shared/assets+. If you already use this folder you'll need to write your own deployment task. +This links the folder specified in +config.assets.prefix+ to +shared/assets+. If you already use this shared folder you'll need to write your own deployment task. It is important that this folder is shared between deployments so that remotely cached pages that reference the old compiled assets still work for the life of the cached page. @@ -298,13 +315,13 @@ The default matcher for compiling files includes +application.js+, +application. [ /\w+\.(?!js|css).+/, /application.(css|js)$/ ] -If you have other manifests or individual stylesheets and JavaScript files to include, you can append them to the +precompile+ array: +If you have other manifests or individual stylesheets and JavaScript files to include, you can add them to the +precompile+ array: config.assets.precompile += ['admin.js', 'admin.css', 'swfObject.js'] -The rake task also generates a +manifest.yml+ that contains a list with all your assets and their fingerprints, using this manifest file the assets helpers avoid hitting to Sprockets to recalculate MD5 hashes for files. Manifest file typically look like this: +The rake task also generates a +manifest.yml+ that contains a list with all your assets and their respective fingerprints. This is used by the Rails helper methods and avoids handing the mapping requests back to Sprockets. Manifest file typically look like this: --- @@ -315,8 +332,17 @@ application.js: application-3fdab497b8fb70d20cfc5495239dfc29.js application.css: application-8af74128f904600e41a6e39241464e03.css -The manifest file is generated by default in same folder of your precompiled assets, you can change the location of the file setting the +config.assets.manifest+ option with the full path of the folder where you want save it. +The default location for the manifest is the root of the location specified in +config.assets.prefix+ ('/assets' by default). + +This can be changed with the +config.assets.manifest+ option. A fully specified path is required: + +config.assets.manifest = '/path/to/some/other/location' + + +NOTE: If there are missing precompiled files in production you will get an "AssetNoPrecompiledError" exception indicating the name of the missing file. + +h5. Server Configuration Precompiled assets exist on the filesystem and are served directly by your webserver. They do not have far-future headers by default, so to get the benefit of fingerprinting you'll have to update your server configuration to add them. @@ -370,10 +396,23 @@ location ~ ^/(assets)/ { } -By default Rails assumes that you have your files precompiled in the production environment, if you want use live compiling (compile your assets during runtime) in production you must set the +config.assets.compile+ to true. You can use this option to fallback to Sprockets when you are using precompiled assets but there are any missing precompiled files. If +config.assets.compile+ option is set to false and there are missing precompiled files you will get an "AssetNoPrecompiledError" indicating the name of the missing file. +h4. Live Compilation -h3. Customizing the Pipeline +In some circumstances you may wish to use live compilation. In this mode all requests for assets in the Pipeline are handled by Sprockets directly. + +To enable this options set: + + +config.assets.compile = true + + +On the first request the assets are compiled and cached as outlined in development above, and the manifest names used in the helpers are altered to include the MD5 hash. + +Sprockets also sets the +Cache-Control+ HTTP header to +max-age=31536000+. This signals all caches between your server and the client browser that this content (the file served) can be cached for 1 year. The effect of this is to reduce the number of requests for this asset from your server; the asset has a good chance of being in the local browser cache or some intermediate cache. + +This mode uses more memory and is lower performance than the default. It is not recommended. +h3. Customizing the Pipeline h4. CSS Compression @@ -475,6 +514,10 @@ config.assets.enabled = true # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' + +# Change the path that assets are served from +# config.assets.prefix = "/assets" + In +development.rb+: @@ -493,6 +536,11 @@ And in +production.rb+: # Compress JavaScripts and CSS config.assets.compress = true +# Choose the compressors to use +# config.assets.js_compressor = :uglifier +# config.assets.css_compressor = :yui + + # Don't fallback to assets pipeline if a precompiled asset is missed config.assets.compile = false @@ -507,3 +555,16 @@ config.assets.digest = true There are no changes to +test.rb+. + +The following should also be added to +Gemfile+: + + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', " ~> 3.1.0" + gem 'coffee-rails', "~> 3.1.0" + gem 'uglifier' +end + + -- cgit v1.2.3 From 3ce3b5b1f1f92d79ee015d246a9f62a725eca5ca Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 31 Aug 2011 18:50:38 -0700 Subject: Merge pull request #2780 from guilleiguaran/assets-pipeline-minor-changes Assets pipeline: fix in manifest location and remove unused code --- actionpack/lib/sprockets/assets.rake | 33 ++++++++++--------------- railties/lib/rails/application/configuration.rb | 2 +- railties/test/application/assets_test.rb | 13 ++++++++++ 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 6f38ece0c3..f1fc7857a7 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -23,29 +23,22 @@ namespace :assets do manifest = {} manifest_path = config.assets.manifest || target - if env.respond_to?(:each_logical_path) - config.assets.precompile.each do |path| - env.each_logical_path do |logical_path| - if path.is_a?(Regexp) - next unless path.match(logical_path) - else - next unless File.fnmatch(path.to_s, logical_path) - end + config.assets.precompile.each do |path| + env.each_logical_path do |logical_path| + if path.is_a?(Regexp) + next unless path.match(logical_path) + else + next unless File.fnmatch(path.to_s, logical_path) + end - if asset = env.find_asset(logical_path) - manifest[logical_path] = asset.digest_path - filename = target.join(asset.digest_path) - mkdir_p filename.dirname - asset.write_to(filename) - asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/ - end + if asset = env.find_asset(logical_path) + manifest[logical_path] = asset.digest_path + filename = target.join(asset.digest_path) + mkdir_p filename.dirname + asset.write_to(filename) + asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/ end end - else - # TODO: Remove this once we're depending on sprockets beta 15 - assets = config.assets.precompile.dup - assets << {:to => target} - env.precompile(*assets) end File.open("#{manifest_path}/manifest.yml", 'w') do |f| diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index fa7e3b820b..0ca664e4f0 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -43,7 +43,7 @@ module Rails @assets.debug = false @assets.compile = true @assets.digest = false - @assets.manifest = "#{root}/public#{@assets.prefix}" + @assets.manifest = nil @assets.cache_store = [ :file_store, "#{root}/tmp/cache/assets/" ] @assets.js_compressor = nil @assets.css_compressor = nil diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index ccadf0b2c0..721d082908 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -96,6 +96,19 @@ module ApplicationTests assert_match /application-([0-z]+)\.css/, assets["application.css"] end + test "the manifest file should be saved by default in the same assets folder" do + app_file "app/assets/javascripts/application.js", "alert();" + app_file "config/initializers/manifest.rb", "Rails.application.config.assets.prefix = '/x'" + + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + + manifest = "#{app_path}/public/x/manifest.yml" + assets = YAML.load_file(manifest) + assert_match /application-([0-z]+)\.js/, assets["application.js"] + end + test "assets do not require any assets group gem when manifest file is present" do app_file "app/assets/javascripts/application.js", "alert();" -- cgit v1.2.3 From 4ba35dd26b8f02ab851e9d8431a1fe78264e2d51 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Thu, 1 Sep 2011 00:35:01 -0500 Subject: Giving info about what are the defaults for test environment --- railties/guides/source/asset_pipeline.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index f62b7e5c65..8bcddfbb4b 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -554,7 +554,7 @@ config.assets.digest = true # config.assets.precompile += %w( search.js ) -There are no changes to +test.rb+. +There are no changes to +test.rb+. For test environment by default +config.assets.compile+ is true and +config.assets.compress+, +config.assets.debug+ and +config.assets.digest+ are false The following should also be added to +Gemfile+: -- cgit v1.2.3 From 418e321b506645bc0fb69116f01de41546a8cacf Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Thu, 1 Sep 2011 01:01:31 -0500 Subject: Fixing sass-rails helpers methods examples --- railties/guides/source/asset_pipeline.textile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 8bcddfbb4b..9ff4f0d062 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -158,13 +158,13 @@ h5. CSS and SCSS When using the asset pipeline, paths to assets must be re-written and +sass-rails+ provides +_url+ and +_path+ helpers for the following asset classes: image, font, video, audio, javascript, stylesheet. -* +image_url("rails.png")+ becomes +url(/assets/rails.png)+ -* +image_path("rails.png")+ becomes +"/assets/rails.png"+. +* +image-url("rails.png")+ becomes +url(/assets/rails.png)+ +* +image-path("rails.png")+ becomes +"/assets/rails.png"+. The more generic form can also be used but the asset path and class must both be specified: -* +asset_url("rails.png", "image")+ becomes +url(/assets/rails.png)+ -* +asset_path("rails.png", "image")+ becomes +"/assets/rails.png"+ +* +asset-url("rails.png", image)+ becomes +url(/assets/rails.png)+ +* +asset-path("rails.png", image)+ becomes +"/assets/rails.png"+ h4. Manifest Files and Directives -- cgit v1.2.3 From fdf2f519bd948003b851a1eff8a6f157297a46ad Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Thu, 1 Sep 2011 01:15:19 -0500 Subject: Add reference to ExecJS in JavaScript Compression section --- railties/guides/source/asset_pipeline.textile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 9ff4f0d062..b06abc82cf 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -426,7 +426,7 @@ config.assets.css_compressor = :yui The +config.assets.compress+ must be set to +true+ to enable CSS compression -h4. JavaScript +h4. JavaScript Compression Possible options for JavaScript compression are +:closure+, +:uglifier+ and +:yui+. These require the use of the +closure-compiler+, +uglifier+ or +yui-compressor+ gems respectively. @@ -440,6 +440,8 @@ config.assets.js_compressor = :uglifier The +config.assets.compress+ must be set to +true+ to enable JavaScript compression +NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have a JavaScript engine in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. + h4. Using Your Own Compressor The compressor config settings for CSS and JavaScript also take any Object. This object must have a +compress+ method that takes a string as the sole argument and it must return a string. -- cgit v1.2.3 From 72fea6d2ebd9a40d78f0d6ad0fdbdf80298458e9 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Thu, 1 Sep 2011 01:18:20 -0500 Subject: Adding reference about ExecJS for CoffeeScript --- railties/guides/source/asset_pipeline.textile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index b06abc82cf..e428684079 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -89,10 +89,12 @@ In previous versions of Rails, all assets were located in subdirectories of +pub This is not to say that assets can (or should) no longer be placed in +public+; they still can be and will be served as static files by the application or web server. You would only use +app/assets+ if you wish your files to undergo some pre-processing before they are served. -When a scaffold or controller is generated for the application, Rails also generates a JavaScript file (or CoffeeScript file if the +coffee-script+ gem is in the +Gemfile+) and a Cascading Style Sheet file (or SCSS file if +sass-rails+ is in the +Gemfile+) for that controller. +When a scaffold or controller is generated for the application, Rails also generates a JavaScript file (or CoffeeScript file if the +coffee-rails+ gem is in the +Gemfile+) and a Cascading Style Sheet file (or SCSS file if +sass-rails+ is in the +Gemfile+) for that controller. For example, if a +ProjectsController+ is generated, there will be a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as +<%= javascript_include_tag params[:controller] %>+ or +<%= stylesheet_link_tag params[:controller] %>+. +NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use CoffeeScript. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. + h4. Asset Organization Assets can be placed inside an application in one of three locations: +app/assets+, +lib/assets+ or +vendor/assets+. @@ -440,7 +442,7 @@ config.assets.js_compressor = :uglifier The +config.assets.compress+ must be set to +true+ to enable JavaScript compression -NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have a JavaScript engine in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. +NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have installed a JavaScript runtime in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. h4. Using Your Own Compressor -- cgit v1.2.3 From 5421d4d0161949e24f63bab30b82be694761a6d4 Mon Sep 17 00:00:00 2001 From: Richard Hulse Date: Thu, 1 Sep 2011 18:25:24 +1200 Subject: pipeline docs - spelling and some whitespace --- railties/guides/source/asset_pipeline.textile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index e428684079..a0e51aa57c 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -282,7 +282,7 @@ generates something like this: - + The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). under normal circumstances the default options should not be changed. @@ -375,7 +375,7 @@ For Apache: # 2 lines to serve pre-gzipped version RewriteCond %{REQUEST_FILENAME}.gz -s RewriteRule ^(.+) $1.gz [L] - + # without it, Content-Type will be "application/x-gzip" ForceType text/css @@ -402,7 +402,7 @@ h4. Live Compilation In some circumstances you may wish to use live compilation. In this mode all requests for assets in the Pipeline are handled by Sprockets directly. -To enable this options set: +To enable this option set: config.assets.compile = true @@ -442,7 +442,7 @@ config.assets.js_compressor = :uglifier The +config.assets.compress+ must be set to +true+ to enable JavaScript compression -NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have installed a JavaScript runtime in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. +NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have installed a JavaScript runtime in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. h4. Using Your Own Compressor @@ -506,7 +506,7 @@ TODO: Registering gems on "Tilt":https://github.com/rtomayko/tilt enabling Sproc h3. Upgrading from Old Versions of Rails -There are two issues when upgrading. The first is moving the files to the new locations. See the section above for guidance on the correct locations for different file types. +There are two issues when upgrading. The first is moving the files to the new locations. See the section above for guidance on the correct locations for different file types. The second is updating the various environment files with the correct default options. The following changes reflect the defaults in version 3.1.0. -- cgit v1.2.3 From d5165e5ab0829bd4cb0345f24ab619109cd1fbe2 Mon Sep 17 00:00:00 2001 From: Sam Pohlenz Date: Thu, 1 Sep 2011 14:59:16 +0930 Subject: Move references to Rails.application.config out of Sprockets AssetPaths --- actionpack/lib/sprockets/helpers/rails_helper.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 975dc9e80c..2dde2e9cc9 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -15,6 +15,8 @@ module Sprockets paths.asset_environment = asset_environment paths.asset_prefix = asset_prefix paths.asset_digests = asset_digests + paths.compile_assets = compile_assets? + paths.digest_assets = digest_assets? paths end end @@ -60,8 +62,7 @@ module Sprockets private def debug_assets? begin - config = Rails.application.config.assets - config.compile && (config.debug || params[:debug_assets]) + compile_assets? && (Rails.application.config.assets.debug || params[:debug_assets]) rescue NoMethodError false end @@ -81,6 +82,14 @@ module Sprockets Rails.application.config.assets.digests end + def compile_assets? + Rails.application.config.assets.compile + end + + def digest_assets? + Rails.application.config.assets.digest + end + # Override to specify an alternative asset environment for asset # path generation. The environment should already have been mounted # at the prefix returned by +asset_prefix+. @@ -89,7 +98,7 @@ module Sprockets end class AssetPaths < ::ActionView::AssetPaths #:nodoc: - attr_accessor :asset_environment, :asset_prefix, :asset_digests + attr_accessor :asset_environment, :asset_prefix, :asset_digests, :compile_assets, :digest_assets class AssetNotPrecompiledError < StandardError; end @@ -114,7 +123,7 @@ module Sprockets return digest end - if Rails.application.config.assets.compile + if compile_assets if asset = asset_environment[logical_path] return asset.digest_path end @@ -128,7 +137,7 @@ module Sprockets if source[0] == ?/ source else - source = digest_for(source) if Rails.application.config.assets.digest + source = digest_for(source) if digest_assets source = File.join(dir, source) source = "/#{source}" unless source =~ /^\// source -- cgit v1.2.3 From 5bb1c7acdc5c9566bd8ef89f5b651ecc84dc1150 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Thu, 1 Sep 2011 03:12:13 -0500 Subject: Add missing changelog entries for 3.1.1 --- actionpack/CHANGELOG | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 6b654e149e..dd27325055 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -28,7 +28,16 @@ for your test you need to do it before the cookie jar is created. -*Rails 3.1.0 (unreleased)* +*Rails 3.1.1 (unreleased)* + +* Fixed AssetNotPrecompiled error raised when rake assets:precompile is compiling certain .erb files. [Guillermo Iguaran] + +* Manifest is correctly placed in assets path when default assets prefix is changed. [Guillermo Iguaran] + +* Fixed stylesheet_link_tag and javascript_include_tag to respect additional options passed by the users when debug is on. [Guillermo Iguaran] + + +*Rails 3.1.0 (August 30, 2011)* * Param values are `paramified` in controller tests. [David Chelimsky] -- cgit v1.2.3 From 58b0c9734777a4610e812a48ee64881b4f88b107 Mon Sep 17 00:00:00 2001 From: Sam Pohlenz Date: Thu, 1 Sep 2011 09:23:51 +0930 Subject: assets:precompile should not append asset digests when config.assets.digest is false --- actionpack/lib/sprockets/assets.rake | 9 +++++---- railties/test/application/assets_test.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index f1fc7857a7..a8128d9a82 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -13,8 +13,7 @@ namespace :assets do # Ensure that action view is loaded and the appropriate sprockets hooks get executed ActionView::Base - # Always calculate digests and compile files - Rails.application.config.assets.digest = true + # Always compile files Rails.application.config.assets.compile = true config = Rails.application.config @@ -32,8 +31,10 @@ namespace :assets do end if asset = env.find_asset(logical_path) - manifest[logical_path] = asset.digest_path - filename = target.join(asset.digest_path) + asset_path = config.assets.digest ? asset.digest_path : logical_path + manifest[logical_path] = asset_path + filename = target.join(asset_path) + mkdir_p filename.dirname asset.write_to(filename) asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/ diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 721d082908..a412b7d99b 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -67,6 +67,8 @@ module ApplicationTests test "precompile creates a manifest file with all the assets listed" do app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" app_file "app/assets/javascripts/application.js", "alert();" + # digest is default in false, we must enable it for test environment + app_file "config/initializers/compile.rb", "Rails.application.config.assets.digest = true" capture(:stdout) do Dir.chdir(app_path){ `bundle exec rake assets:precompile` } @@ -84,6 +86,8 @@ module ApplicationTests app_file "app/assets/javascripts/application.js", "alert();" FileUtils.mkdir "#{app_path}/shared" app_file "config/initializers/manifest.rb", "Rails.application.config.assets.manifest = '#{app_path}/shared'" + # digest is default in false, we must enable it for test environment + app_file "config/initializers/compile.rb", "Rails.application.config.assets.digest = true" capture(:stdout) do Dir.chdir(app_path){ `bundle exec rake assets:precompile` } @@ -96,9 +100,12 @@ module ApplicationTests assert_match /application-([0-z]+)\.css/, assets["application.css"] end + test "the manifest file should be saved by default in the same assets folder" do app_file "app/assets/javascripts/application.js", "alert();" app_file "config/initializers/manifest.rb", "Rails.application.config.assets.prefix = '/x'" + # digest is default in false, we must enable it for test environment + app_file "config/initializers/compile.rb", "Rails.application.config.assets.digest = true" capture(:stdout) do Dir.chdir(app_path){ `bundle exec rake assets:precompile` } @@ -109,6 +116,25 @@ module ApplicationTests assert_match /application-([0-z]+)\.js/, assets["application.js"] end + test "precompile does not append asset digests when config.assets.digest is false" do + app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" + app_file "app/assets/javascripts/application.js", "alert();" + app_file "config/initializers/compile.rb", "Rails.application.config.assets.digest = false" + + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + + assert File.exists?("#{app_path}/public/assets/application.js") + assert File.exists?("#{app_path}/public/assets/application.css") + + manifest = "#{app_path}/public/assets/manifest.yml" + + assets = YAML.load_file(manifest) + assert_equal "application.js", assets["application.js"] + assert_equal "application.css", assets["application.css"] + end + test "assets do not require any assets group gem when manifest file is present" do app_file "app/assets/javascripts/application.js", "alert();" -- cgit v1.2.3 From 1f998c7578d343310a4309bc0b06af224132648d Mon Sep 17 00:00:00 2001 From: Richard Hulse Date: Thu, 1 Sep 2011 21:15:06 +1200 Subject: pipeline docs improvement Some cleaning up of whitespace/punctuation and text refinements to clarify some things. --- railties/guides/source/asset_pipeline.textile | 45 +++++++++++++++------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index a0e51aa57c..3ed75a28ef 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -105,13 +105,17 @@ Assets can be placed inside an application in one of three locations: +app/asset +vendor/assets+ is for assets that are owned by outside entities, such as code for JavaScript plugins. -All subdirectories that exist within these three locations are added to the search path for Sprockets (visible by calling +Rails.application.config.assets.paths+ in a console). When an asset is requested, these paths are looked through to see if they contain an asset matching the name specified. Once an asset has been found, it's processed by Sprockets and served. +All subdirectories that exist within these three locations are added to the search path for Sprockets (visible by calling +Rails.application.config.assets.paths+ in a console). When an asset is requested, these paths are traversed to see if they contain an asset matching the name specified. Once an asset has been found, it's processed by Sprockets and served. -h4. Coding Links to Assets +You can add additional (fully qualified) paths to the pipeline in +application.rb+. For example: + + +config.assets.paths << File.join(Rails.root, 'app', 'assets', 'flash') + -To access assets, you use the same tags that you are generally familiar with: +h4. Coding Links to Assets -Sprockets does not add any new methods to require your assets, you still use the familiar +javascript_include_tag+ and +stylesheet_link_tag+. +Sprockets does not add any new methods to access your assets - you still use the familiar +javascript_include_tag+ and +stylesheet_link_tag+. <%= stylesheet_link_tag "application" %> @@ -124,17 +128,17 @@ In regular views you can access images in the +assets/images+ directory like thi <%= image_tag "rails.png" %> -Images can be organized into directories if required, and they can be accessed by specifying the directory's name in the tag: +Provided that the pipeline is enabled within your application (and not disabled in the current environment context), this file is served by Sprockets. If a file exists at +public/assets/rails.png+ it is served by the webserver. - -<%= image_tag "icons/rails.png" %> - +Alternatively, a request for a file with an MD5 hash such as +public/assets/rails-af27b6a414e6da00003503148be9b409.png+ is treated the same way. How these hashes are generated is covered in the "Production Assets":#production_assets section later on in this guide. -Providing that assets are enabled within your application (+config.assets.enabled+ in the current environment's file is not set to +false+), this file is served by Sprockets unless a file at +public/assets/rails.png+ exists, in which case that file is served. +Sprockets will also look through the paths specified in +config.assets.paths+ which includes the standard application paths and any path added by Rails engines. -Alternatively, a file with an MD5 hash after its name such as +public/assets/rails-af27b6a414e6da00003503148be9b409.png+ is also picked up by Sprockets. How these hashes are generated is covered in the "Production Assets":#production_assets section later on in this guide. +Images can also be organized into subdirectories if required, and they can be accessed by specifying the directory's name in the tag: -Otherwise, Sprockets looks through the available paths until it finds a file that matches the name and then serves it, first looking in the application's assets directories and then falling back to the various engines of the application. + +<%= image_tag "icons/rails.png" %> + If you want to use a "css data URI":http://en.wikipedia.org/wiki/Data_URI_scheme -- a method of embedding the image data directly into the CSS file -- you can use the +asset_data_uri+ helper. @@ -256,7 +260,7 @@ When debug mode is off Sprockets will concatenate and run the necessary preproce -Assets are compiled and cached on the first request after the server is started. Sprockets sets a +must-validate+ Cache-Control HTTP header to reduce request overhead on subsequent requests - on these the browser gets a 304 (not-modified) response. +Assets are compiled and cached on the first request after the server is started. Sprockets sets a +must-validate+ Cache-Control HTTP header to reduce request overhead on subsequent requests -- on these the browser gets a 304 (not-modified) response. If any of the files in the manifest have changed between requests, the server responds with a new compiled file. @@ -285,7 +289,9 @@ generates something like this: -The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). under normal circumstances the default options should not be changed. +The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). + +NOTE: Under normal circumstances the default options should not be changed. If there are no digests in the filenames, and far-future headers are set, remote clients will never know to refetch the files when their content changes. h4. Precompiling Assets @@ -366,7 +372,7 @@ For Apache: TODO: nginx instructions -When files are precompiled, Sprockets also creates a "Gzip":http://en.wikipedia.org/wiki/Gzip (.gz) version of your assets. This avoids the server having to do this for any requests; it can simply read the compressed files from disc. You must configure your server to use gzip compression and serve the compressed assets that will be stored in the public/assets folder. The following configuration options can be used: +When files are precompiled, Sprockets also creates a "Gzip":http://en.wikipedia.org/wiki/Gzip (.gz) version of your assets. This avoids the server having to do this for any requests; it can simply read the compressed files from disc. You must configure your server to use gzip compression and serve the compressed assets that will be stored in the +public/assets+ folder. The following configuration options can be used: For Apache: @@ -418,7 +424,7 @@ h3. Customizing the Pipeline h4. CSS Compression -There is currently one option for compressing CSS - YUI. This Gem extends the CSS syntax and offers minification. +There is currently one option for compressing CSS, YUI. This Gem extends the CSS syntax and offers minification. The following line enables YUI compression, and requires the +yui-compressor+ gem. @@ -442,7 +448,7 @@ config.assets.js_compressor = :uglifier The +config.assets.compress+ must be set to +true+ to enable JavaScript compression -NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have installed a JavaScript runtime in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. +NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme -- supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have installed a JavaScript runtime in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. h4. Using Your Own Compressor @@ -490,7 +496,7 @@ WARNING: If you are upgrading an existing application and intend to use this opt h3. How Caching Works -Sprockets uses the default rails cache store to cache assets in dev and production. The only difference is file names are fingerprinted and get far-future headers in production. +Sprockets uses the default rails cache store to cache assets in development and production. TODO: Add more about changing the default store. @@ -544,11 +550,10 @@ config.assets.compress = true # config.assets.js_compressor = :uglifier # config.assets.css_compressor = :yui - # Don't fallback to assets pipeline if a precompiled asset is missed config.assets.compile = false -# Generate digests for assets URLs +# Generate digests for assets URLs. config.assets.digest = true # Defaults to Rails.root.join("public/assets") @@ -558,7 +563,7 @@ config.assets.digest = true # config.assets.precompile += %w( search.js ) -There are no changes to +test.rb+. For test environment by default +config.assets.compile+ is true and +config.assets.compress+, +config.assets.debug+ and +config.assets.digest+ are false +There are no changes to +test.rb+. The defaults in the test environment are: +config.assets.compile+ is true and +config.assets.compress+, +config.assets.debug+ and +config.assets.digest+ are false. The following should also be added to +Gemfile+: -- cgit v1.2.3 From cfd785f910fc914c576133fee263875833ba0c92 Mon Sep 17 00:00:00 2001 From: Richard Hulse Date: Thu, 1 Sep 2011 21:20:26 +1200 Subject: Move css data URI into css/erb section --- railties/guides/source/asset_pipeline.textile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 3ed75a28ef..cfed1b5bdf 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -140,14 +140,6 @@ Images can also be organized into subdirectories if required, and they can be ac <%= image_tag "icons/rails.png" %> -If you want to use a "css data URI":http://en.wikipedia.org/wiki/Data_URI_scheme -- a method of embedding the image data directly into the CSS file -- you can use the +asset_data_uri+ helper. - - -#logo { background: url(<%= asset_data_uri 'logo.png' %>) } - - -This inserts a correctly-formatted data URI into the CSS source. - h5. CSS and ERB If you add an +erb+ extension to a CSS asset, making it something such as +application.css.erb+, then you can use the +asset_path+ helper in your CSS rules: @@ -158,6 +150,14 @@ If you add an +erb+ extension to a CSS asset, making it something such as +appli This writes the path to the particular asset being referenced. In this example, it would make sense to have an image in one of the asset load paths, such as +app/assets/images/image.png+, which would be referenced here. If this image is already available in +public/assets+ as a fingerprinted file, then that path is referenced. +If you want to use a "css data URI":http://en.wikipedia.org/wiki/Data_URI_scheme -- a method of embedding the image data directly into the CSS file -- you can use the +asset_data_uri+ helper. + + +#logo { background: url(<%= asset_data_uri 'logo.png' %>) } + + +This inserts a correctly-formatted data URI into the CSS source. + Note that the closing tag cannot be of the style +-%>+. h5. CSS and SCSS -- cgit v1.2.3 From 752d74f9522be3a9a0b2d904d5b6f9007100ea22 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Thu, 1 Sep 2011 01:35:28 +0530 Subject: docs formatting changes --- activesupport/lib/active_support/core_ext/enumerable.rb | 4 ++-- activesupport/lib/active_support/core_ext/hash/indifferent_access.rb | 2 +- activesupport/lib/active_support/hash_with_indifferent_access.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index ddb4f3012f..9343bb7106 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -97,7 +97,7 @@ module Enumerable end # Returns true if the enumerable has more than 1 element. Functionally equivalent to enum.to_a.size > 1. - # Can be called with a block too, much like any?, so people.many? { |p| p.age > 26 } returns true if more than 1 person is over 26. + # Can be called with a block too, much like any?, so people.many? { |p| p.age > 26 } returns true if more than one person is over 26. def many? cnt = 0 if block_given? @@ -110,7 +110,7 @@ module Enumerable end end - # The negative of the Enumerable#include?. Returns true if the collection does not include the object. + # The negative of the Enumerable#include?. Returns true if the collection does not include the object. def exclude?(object) !include?(object) end diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb index 0b368fe7b7..f4cb445444 100644 --- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb +++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb @@ -2,7 +2,7 @@ require 'active_support/hash_with_indifferent_access' class Hash - # Returns an +ActiveSupport::HashWithIndifferentAccess+ out of its receiver: + # Returns an ActiveSupport::HashWithIndifferentAccess out of its receiver: # # {:a => 1}.with_indifferent_access["a"] # => 1 # diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 59ffd24698..636f019cd5 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -112,7 +112,7 @@ module ActiveSupport end end - # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash + # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash. # Does not overwrite the existing hash. def merge(hash) self.dup.update(hash) -- cgit v1.2.3 From 3461a5d4368ab0e41f28d831170794f967286611 Mon Sep 17 00:00:00 2001 From: Roy Tomeij Date: Thu, 1 Sep 2011 17:24:26 +0200 Subject: Change "SCSS" to "Sass" in sentences where it's referred to as "language", because Sass is the language (SCSS is one possible syntax within the Sass language), as per documentation on sass-lang.com. --- railties/guides/source/asset_pipeline.textile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index cfed1b5bdf..550485d038 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -13,7 +13,7 @@ endprologue. h3. What is the Asset Pipeline? -The asset pipeline provides a framework to concatenate and minify or compress JavaScript and CSS assets. It also adds the ability to write these assets in other languages such as CoffeeScript, SCSS and ERB. +The asset pipeline provides a framework to concatenate and minify or compress JavaScript and CSS assets. It also adds the ability to write these assets in other languages such as CoffeeScript, Sass and ERB. Prior to Rails 3.1 these features were added through third-party Ruby libraries such as Jammit and Sprockets. Rails 3.1 is integrated with Sprockets through ActionPack which depends on the +sprockets+ gem, by default. @@ -36,7 +36,7 @@ The default behavior in Rails 3.1 and onward is to concatenate all files into on The second feature is to minify or compress assets. For CSS, this usually involves removing whitespace and comments. For JavaScript, more complex processes can be applied. You can choose from a set of built in options or specify your own. -The third feature is the ability to code these assets using another language, or language extension. These include SCSS or Sass for CSS, CoffeeScript for JavaScript, and ERB for both. +The third feature is the ability to code these assets using another language, or language extension. These include Sass for CSS, CoffeeScript for JavaScript, and ERB for both. h4. What is Fingerprinting and Why Should I Care? @@ -108,7 +108,7 @@ Assets can be placed inside an application in one of three locations: +app/asset All subdirectories that exist within these three locations are added to the search path for Sprockets (visible by calling +Rails.application.config.assets.paths+ in a console). When an asset is requested, these paths are traversed to see if they contain an asset matching the name specified. Once an asset has been found, it's processed by Sprockets and served. You can add additional (fully qualified) paths to the pipeline in +application.rb+. For example: - + config.assets.paths << File.join(Rails.root, 'app', 'assets', 'flash') @@ -160,7 +160,7 @@ This inserts a correctly-formatted data URI into the CSS source. Note that the closing tag cannot be of the style +-%>+. -h5. CSS and SCSS +h5. CSS and Sass When using the asset pipeline, paths to assets must be re-written and +sass-rails+ provides +_url+ and +_path+ helpers for the following asset classes: image, font, video, audio, javascript, stylesheet. @@ -289,7 +289,7 @@ generates something like this: -The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). +The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). NOTE: Under normal circumstances the default options should not be changed. If there are no digests in the filenames, and far-future headers are set, remote clients will never know to refetch the files when their content changes. -- cgit v1.2.3 From 28d605ff7fe1de0ae9b3bcdb48ac6209859c7ecf Mon Sep 17 00:00:00 2001 From: Marc G Gauthier Date: Thu, 1 Sep 2011 18:26:29 +0200 Subject: Do not use objects that don't respond to to_sym (integers, floats, dates...) as parameters --- activeresource/lib/active_resource/base.rb | 2 +- activeresource/test/cases/base/load_test.rb | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index f88772a7ff..990d9a38dd 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -955,7 +955,7 @@ module ActiveResource prefix_options, query_options = {}, {} (options || {}).each do |key, value| - next if key.blank? || [Fixnum, Date, Time, Float].include?(key.class) + next if key.blank? || !key.respond_to?(:to_sym) (prefix_parameters.include?(key.to_sym) ? prefix_options : query_options)[key.to_sym] = value end diff --git a/activeresource/test/cases/base/load_test.rb b/activeresource/test/cases/base/load_test.rb index 0d030148d0..0bbd3ab5f5 100644 --- a/activeresource/test/cases/base/load_test.rb +++ b/activeresource/test/cases/base/load_test.rb @@ -51,9 +51,28 @@ class BaseLoadTest < Test::Unit::TestCase :votes => [ true, false, true ], :places => [ "Columbia City", "Unknown" ]}}} + + # List of books formated as [{timestamp_of_publication => name}, ...] + @books = {:books => [ + {1009839600 => "Ruby in a Nutshell"}, + {1199142000 => "The Ruby Programming Language"} + ]} + + @books_date = {:books => [ + {Time.at(1009839600) => "Ruby in a Nutshell"}, + {Time.at(1199142000) => "The Ruby Programming Language"} + ]} @person = Person.new end + def test_load_hash_with_integers_as_keys + assert_nothing_raised{person = @person.load(@books)} + end + + def test_load_hash_with_dates_as_keys + assert_nothing_raised{person = @person.load(@books_date)} + end + def test_load_expects_hash assert_raise(ArgumentError) { @person.load nil } assert_raise(ArgumentError) { @person.load '' } -- cgit v1.2.3 From 8e900f1e38166ea906967eb8ede9bd14e78eb417 Mon Sep 17 00:00:00 2001 From: Andy Leeper Date: Thu, 1 Sep 2011 10:42:28 -0700 Subject: Modified ActionMailer Basics doc with the following change: * Changed the lines that said config/environments/env.rb to config/environments/$RAILS_ENV.rb. People were mis-interpreting the filename to literally be env.rb. --- railties/guides/source/action_mailer_basics.textile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile index 142b9dba7e..351a4498b1 100644 --- a/railties/guides/source/action_mailer_basics.textile +++ b/railties/guides/source/action_mailer_basics.textile @@ -467,7 +467,7 @@ The following configuration options are best made in one of the environment file h4. Example Action Mailer Configuration -An example would be adding the following to your appropriate config/environments/env.rb file: +An example would be adding the following to your appropriate config/environments/$RAILS_ENV.rb file: config.action_mailer.delivery_method = :sendmail @@ -482,7 +482,7 @@ config.action_mailer.raise_delivery_errors = true h4. Action Mailer Configuration for GMail -As Action Mailer now uses the Mail gem, this becomes as simple as adding to your config/environments/env.rb file: +As Action Mailer now uses the Mail gem, this becomes as simple as adding to your config/environments/$RAILS_ENV.rb file: config.action_mailer.delivery_method = :smtp @@ -524,4 +524,5 @@ In the test we send the email and store the returned object in the +email+ varia h3. Changelog +* September 1, 2011: Changed the lines that said config/environments/env.rb to config/environments/$RAILS_ENV.rb. People were mis-interpreting the filename to literally be env.rb. "Andy Leeper":http://mochaleaf.com * September 30, 2010: Fixed typos and reformatted Action Mailer configuration table for better understanding. "Jaime Iniesta":http://jaimeiniesta.com -- cgit v1.2.3 From c96cb8897b4afb0fea7b5fed4ec41d1772d99644 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Thu, 1 Sep 2011 23:50:31 +0530 Subject: Revert "Fix logic in 3.1 release notes sentence" This reverts commit 30d65da17e5fb1cdd3f10a6d14f4295b57e26286. Reason: This commit is incorrect. It is indeed recommended to use update_attribute when you want callbacks to be invoked. --- railties/guides/source/3_1_release_notes.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/3_1_release_notes.textile b/railties/guides/source/3_1_release_notes.textile index 7de8866ff6..4412d32cce 100644 --- a/railties/guides/source/3_1_release_notes.textile +++ b/railties/guides/source/3_1_release_notes.textile @@ -271,7 +271,7 @@ Post.new(params[:post], :as => :admin) * +ConnectionManagement+ middleware is changed to clean up the connection pool after the rack body has been flushed. -* Added an +update_column+ method on Active Record. This new method updates a given attribute on an object, skipping validations and callbacks. It is not recommended to use +update_attribute+ unless you are sure you do not want to execute any callback, including the modification of the +updated_at+ column. It should not be called on new records. +* Added an +update_column+ method on Active Record. This new method updates a given attribute on an object, skipping validations and callbacks. It is recommended to use +update_attribute+ unless you are sure you do not want to execute any callback, including the modification of the +updated_at+ column. It should not be called on new records. * Associations with a +:through+ option can now use any association as the through or source association, including other associations which have a +:through+ option and +has_and_belongs_to_many+ associations. -- cgit v1.2.3 From 3f64fa9289a7bedb509acd319bf68c0cc0d977fb Mon Sep 17 00:00:00 2001 From: Carlos Paramio Date: Thu, 1 Sep 2011 20:34:15 +0200 Subject: Fix name of parent resource params when declaring nested resources at routes --- actionpack/lib/action_dispatch/routing/mapper.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index a5c1501f61..0c43954d81 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1036,12 +1036,12 @@ module ActionDispatch # # This generates the following comments routes: # - # GET /photos/:id/comments/new - # POST /photos/:id/comments - # GET /photos/:id/comments/:id - # GET /photos/:id/comments/:id/edit - # PUT /photos/:id/comments/:id - # DELETE /photos/:id/comments/:id + # GET /photos/:photo_id/comments/new + # POST /photos/:photo_id/comments + # GET /photos/:photo_id/comments/:id + # GET /photos/:photo_id/comments/:id/edit + # PUT /photos/:photo_id/comments/:id + # DELETE /photos/:photo_id/comments/:id # # === Options # Takes same options as Base#match as well as: -- cgit v1.2.3 From 2d92962701d545c29ebd38f51b787e48faabb504 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Thu, 1 Sep 2011 16:02:08 -0300 Subject: Add #update_attributes as another alternative to #update_column. --- railties/guides/source/3_1_release_notes.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/3_1_release_notes.textile b/railties/guides/source/3_1_release_notes.textile index 4412d32cce..73a96388af 100644 --- a/railties/guides/source/3_1_release_notes.textile +++ b/railties/guides/source/3_1_release_notes.textile @@ -271,7 +271,7 @@ Post.new(params[:post], :as => :admin) * +ConnectionManagement+ middleware is changed to clean up the connection pool after the rack body has been flushed. -* Added an +update_column+ method on Active Record. This new method updates a given attribute on an object, skipping validations and callbacks. It is recommended to use +update_attribute+ unless you are sure you do not want to execute any callback, including the modification of the +updated_at+ column. It should not be called on new records. +* Added an +update_column+ method on Active Record. This new method updates a given attribute on an object, skipping validations and callbacks. It is recommended to use +update_attributes+ or +update_attribute+ unless you are sure you do not want to execute any callback, including the modification of the +updated_at+ column. It should not be called on new records. * Associations with a +:through+ option can now use any association as the through or source association, including other associations which have a +:through+ option and +has_and_belongs_to_many+ associations. -- cgit v1.2.3 From fdd619e9a7a5b9457f77e6322c920b99c3c09599 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 1 Sep 2011 13:37:14 -0700 Subject: CookieJar is enumerable. fixes #2795 --- actionpack/CHANGELOG | 2 ++ actionpack/lib/action_dispatch/middleware/cookies.rb | 5 +++++ actionpack/test/dispatch/cookies_test.rb | 16 ++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index dd27325055..71f38797ae 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -30,6 +30,8 @@ *Rails 3.1.1 (unreleased)* +* CookieJar is now Enumerable. Fixes #2795 + * Fixed AssetNotPrecompiled error raised when rake assets:precompile is compiling certain .erb files. [Guillermo Iguaran] * Manifest is correctly placed in assets path when default assets prefix is changed. [Guillermo Iguaran] diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 1c312f2587..8c4615c0c1 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -85,6 +85,7 @@ module ActionDispatch class CookieOverflow < StandardError; end class CookieJar #:nodoc: + include Enumerable # This regular expression is used to split the levels of a domain. # The top level domain can be any string without a period or @@ -124,6 +125,10 @@ module ActionDispatch alias :closed? :closed def close!; @closed = true end + def each(&block) + @cookies.each(&block) + end + # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists. def [](name) @cookies[name.to_s] diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index fb67ecb07d..49da448001 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -148,6 +148,22 @@ class CookiesTest < ActionController::TestCase @request.host = "www.nextangle.com" end + def test_each + request.cookie_jar['foo'] = :bar + list = [] + request.cookie_jar.each do |k,v| + list << [k, v] + end + + assert_equal [['foo', :bar]], list + end + + def test_enumerable + request.cookie_jar['foo'] = :bar + actual = request.cookie_jar.map { |k,v| [k.to_s, v.to_s] } + assert_equal [['foo', 'bar']], actual + end + def test_key_methods assert !request.cookie_jar.key?(:foo) assert !request.cookie_jar.has_key?("foo") -- cgit v1.2.3 From ca7c37a660b66b6b3cdd7fe4ab850ea5a32cc2c0 Mon Sep 17 00:00:00 2001 From: Richard Hulse Date: Fri, 2 Sep 2011 08:39:16 +1200 Subject: fix some minor omissions in pipeline docs --- railties/guides/source/asset_pipeline.textile | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 550485d038..e40310a9ec 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -89,6 +89,8 @@ In previous versions of Rails, all assets were located in subdirectories of +pub This is not to say that assets can (or should) no longer be placed in +public+; they still can be and will be served as static files by the application or web server. You would only use +app/assets+ if you wish your files to undergo some pre-processing before they are served. +In production, the default is to precompile these files to +public/assets+ so that they can be more efficiently delivered by the webserver. + When a scaffold or controller is generated for the application, Rails also generates a JavaScript file (or CoffeeScript file if the +coffee-rails+ gem is in the +Gemfile+) and a Cascading Style Sheet file (or SCSS file if +sass-rails+ is in the +Gemfile+) for that controller. For example, if a +ProjectsController+ is generated, there will be a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as +<%= javascript_include_tag params[:controller] %>+ or +<%= stylesheet_link_tag params[:controller] %>+. @@ -241,11 +243,13 @@ This manifest +application.js+: would generate this HTML: - - - + + + +The +body+ param is required by Sprockets. + h4. Turning Debugging off You can turn off debug mode by updating +development.rb+ to include: @@ -264,7 +268,16 @@ Assets are compiled and cached on the first request after the server is started. If any of the files in the manifest have changed between requests, the server responds with a new compiled file. -You can put +?debug_assets=true+ or +?debug_assets=1+ at the end of a URL to enable debug mode on-demand, and this will render indivudual tags for each file. This is useful for tracking down exact line numbers when debugging. +You can put +?debug_assets=true+ or +?debug_assets=1+ at the end of a URL to enable debug mode on-demand, and this will render individual tags for each file. This is useful for tracking down exact line numbers when debugging. + +Debug can also be set in the Rails helper methods: + + +<%= stylesheet_link_tag "application", :debug => true %> +<%= javascript_include_tag "application", :debug => true %> + + +Don't forget to remove this before deploying to production! You could potentially also enable compression in development mode as a sanity check, and disable it on-demand as required for debugging. @@ -291,7 +304,7 @@ generates something like this: The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). -NOTE: Under normal circumstances the default options should not be changed. If there are no digests in the filenames, and far-future headers are set, remote clients will never know to refetch the files when their content changes. +NOTE: Under normal circumstances the default option should not be changed. If there are no digests in the filenames, and far-future headers are set, remote clients will never know to refetch the files when their content changes. h4. Precompiling Assets -- cgit v1.2.3 From 8b9ddbd8f912d4aac475bcbcbd3e3d39b9b73bf9 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 1 Sep 2011 14:06:20 -0700 Subject: make sure encoding_aware? is available --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 1996e49296..7d793e3cb8 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -1,4 +1,6 @@ require 'active_record/connection_adapters/abstract_adapter' +require 'active_support/core_ext/kernel/requires' +require 'active_support/core_ext/string/encoding' module ActiveRecord module ConnectionAdapters #:nodoc: -- cgit v1.2.3 From 6f3c6992c529a09c8f8bfdb1f714bb8ff1e23300 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 1 Sep 2011 15:00:31 -0700 Subject: * Psych errors with poor yaml formatting are proxied. Fixes #2645, #2731 --- .../active_record/connection_adapters/sqlite_adapter.rb | 1 - activerecord/lib/active_record/fixtures/file.rb | 12 +++++++++++- activerecord/test/cases/fixtures_test.rb | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 7d793e3cb8..a90c675bf6 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -1,5 +1,4 @@ require 'active_record/connection_adapters/abstract_adapter' -require 'active_support/core_ext/kernel/requires' require 'active_support/core_ext/string/encoding' module ActiveRecord diff --git a/activerecord/lib/active_record/fixtures/file.rb b/activerecord/lib/active_record/fixtures/file.rb index 04f494db2c..6bad36abb9 100644 --- a/activerecord/lib/active_record/fixtures/file.rb +++ b/activerecord/lib/active_record/fixtures/file.rb @@ -29,11 +29,21 @@ module ActiveRecord rows.each(&block) end + RESCUE_ERRORS = [ ArgumentError ] # :nodoc: + private + if defined?(Psych) && defined?(Psych::SyntaxError) + RESCUE_ERRORS << Psych::SyntaxError + end + def rows return @rows if @rows - data = YAML.load(render(IO.read(@file))) + begin + data = YAML.load(render(IO.read(@file))) + rescue *RESCUE_ERRORS => error + raise Fixture::FormatError, "a YAML error occurred parsing #{@file}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n #{error.class}: #{error}", error.backtrace + end @rows = data ? validate(data).to_a : [] end diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 913f6a3340..866dcefbab 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -20,6 +20,7 @@ require 'models/book' require 'models/admin' require 'models/admin/account' require 'models/admin/user' +require 'tempfile' class FixturesTest < ActiveRecord::TestCase self.use_instantiated_fixtures = true @@ -45,6 +46,21 @@ class FixturesTest < ActiveRecord::TestCase end end + def test_broken_yaml_exception + badyaml = Tempfile.new ['foo', '.yml'] + badyaml.write 'a: !ruby.yaml.org,2002:str |\nfoo' + badyaml.flush + + dir = File.dirname badyaml.path + name =File.basename badyaml.path, '.yml' + assert_raises(ActiveRecord::Fixture::FormatError) do + ActiveRecord::Fixtures.create_fixtures(dir, name) + end + ensure + badyaml.close + badyaml.unlink + end + def test_create_fixtures ActiveRecord::Fixtures.create_fixtures(FIXTURES_ROOT, "parrots") assert Parrot.find_by_name('Curious George'), 'George is in the database' -- cgit v1.2.3 From 16aa4330d7a07736ce59ea3a96e57d17fa628a2d Mon Sep 17 00:00:00 2001 From: "Stephen J. Butler" Date: Thu, 1 Sep 2011 19:55:38 -0500 Subject: Change the styling of 'initialize' to '+initialize+' (the former breaks the HTML generation). --- railties/guides/source/initialization.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 9cc4dd5f04..8aabc3ae91 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -454,7 +454,7 @@ app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", TOPLEVEL_BINDING, config -The initialize method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run: +The +initialize+ method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run: require ::File.expand_path('../config/environment', __FILE__) -- cgit v1.2.3 From e61d6afbab24163d37a73b25262ef73119b99a78 Mon Sep 17 00:00:00 2001 From: Alexey Vakhov Date: Fri, 2 Sep 2011 13:31:00 +0400 Subject: fix indent for generator environment method --- railties/lib/rails/generators/actions.rb | 2 +- railties/test/generators/actions_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index b8541c236e..a7462f39ba 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -97,7 +97,7 @@ module Rails in_root do if options[:env].nil? - inject_into_file 'config/application.rb', "\n #{data}", :after => sentinel, :verbose => false + inject_into_file 'config/application.rb', "\n #{data}", :after => sentinel, :verbose => false else Array.wrap(options[:env]).each do |env| inject_into_file "config/environments/#{env}.rb", "\n #{data}", :after => env_file_sentinel, :verbose => false diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index e4a8000425..56cb53c1ad 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -106,7 +106,7 @@ class ActionsTest < Rails::Generators::TestCase run_generator autoload_paths = 'config.autoload_paths += %w["#{Rails.root}/app/extras"]' action :environment, autoload_paths - assert_file 'config/application.rb', /#{Regexp.escape(autoload_paths)}/ + assert_file 'config/application.rb', / class Application < Rails::Application\n #{Regexp.escape(autoload_paths)}/ end def test_environment_should_include_data_in_environment_initializer_block_with_env_option -- cgit v1.2.3 From d0f9f4e66467f7ab6a75c16e1a5b9d00912870cc Mon Sep 17 00:00:00 2001 From: Josh Nesbitt Date: Fri, 2 Sep 2011 13:28:38 +0100 Subject: Fix typo in ActiveModel::Dirty comment. define_attribute_methods is a class method, not attribute. --- activemodel/lib/active_model/dirty.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index e3e71525fa..166cccf161 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -29,7 +29,7 @@ module ActiveModel # # include ActiveModel::Dirty # - # define_attribute_methods = [:name] + # define_attribute_methods [:name] # # def name # @name -- cgit v1.2.3 From fddf7ea1c1e520f33fa26fe340f3fc107bcc95c8 Mon Sep 17 00:00:00 2001 From: Alexey Vakhov Date: Fri, 2 Sep 2011 18:20:10 +0400 Subject: current_page? returns false for non-GET requests --- actionpack/lib/action_view/helpers/url_helper.rb | 8 ++++++++ actionpack/test/template/url_helper_test.rb | 10 ++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 4dbb0135f6..5a043846a7 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -569,6 +569,12 @@ module ActionView # # current_page?(:controller => 'library', :action => 'checkout') # # => false + # + # Let's say we're in the /products action with method POST in case of invalid product. + # + # current_page?(:controller => 'product', :action => 'index') + # # => false + # def current_page?(options) unless request raise "You cannot use helpers that need to determine the current " \ @@ -576,6 +582,8 @@ module ActionView "in a #request method" end + return false unless request.get? + url_string = url_for(options) # We ignore any extra parameters in the request_uri if the diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 78245c1f95..dbac2e1fc0 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -304,8 +304,8 @@ class UrlHelperTest < ActiveSupport::TestCase assert_equal "Showing", link_to_if(false, "Showing", url_hash) end - def request_for_url(url) - env = Rack::MockRequest.env_for("http://www.example.com#{url}") + def request_for_url(url, opts = {}) + env = Rack::MockRequest.env_for("http://www.example.com#{url}", opts) ActionDispatch::Request.new(env) end @@ -329,6 +329,12 @@ class UrlHelperTest < ActiveSupport::TestCase assert current_page?("http://www.example.com/?order=desc&page=1") end + def test_current_page_with_not_get_verb + @request = request_for_url("/events", :method => :post) + + assert !current_page?('/events') + end + def test_link_unless_current @request = request_for_url("/") -- cgit v1.2.3 From 3a7c16dbb9c1a4ea96c516c0a9f9ce5d34cee49a Mon Sep 17 00:00:00 2001 From: Matt Burke Date: Fri, 2 Sep 2011 10:20:23 -0400 Subject: When a collection is empty, render returns nil. --- railties/guides/source/layouts_and_rendering.textile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index 310a70ca9b..3252f17c56 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -1093,6 +1093,13 @@ In Rails 3.0, there is also a shorthand for this. Assuming +@products+ is a coll Rails determines the name of the partial to use by looking at the model name in the collection. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection: +In the event that the collection is empty, +render+ will return nil, so it should be fairly simple to provide alternative content. + + +

Products

+<%= render(@products) || 'There are no products available.' %> +
+ * +index.html.erb+ -- cgit v1.2.3 From d20281add192e5afba66e555ce67cf73943b033b Mon Sep 17 00:00:00 2001 From: Andrew Olson Date: Fri, 2 Sep 2011 11:48:45 -0400 Subject: Fixing guides validation errors. --- railties/guides/source/action_view_overview.textile | 6 +++--- railties/guides/source/active_model_basics.textile | 2 ++ railties/guides/source/active_record_querying.textile | 4 ++-- railties/guides/source/active_support_core_extensions.textile | 4 ++-- railties/guides/source/ajax_on_rails.textile | 6 +++++- railties/guides/source/asset_pipeline.textile | 6 +++--- railties/guides/source/form_helpers.textile | 2 +- railties/guides/source/generators.textile | 2 +- railties/guides/source/initialization.textile | 6 +++--- railties/guides/source/performance_testing.textile | 4 ++-- 10 files changed, 24 insertions(+), 18 deletions(-) diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index 5a1e8b1247..c43fd8cc14 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -126,7 +126,7 @@ Rails supports multiple template systems and uses a file extension to distinguis h5. ERB -Within an ERB template Ruby code can be included using both +<% %>+ and +<%= %>+ tags. The +<% %>+ are used to execute Ruby code that does not return anything, such as conditions, loops or blocks, and the +<%= %>+ tags are used when you want output. +Within an ERB template Ruby code can be included using both +<% %>+ and +<%= %>+ tags. The +<% %>+ are used to execute Ruby code that does not return anything, such as conditions, loops or blocks, and the +<%= %>+ tags are used when you want output. Consider the following loop for names: @@ -137,14 +137,14 @@ Consider the following loop for names: <% end %> -The loop is setup in regular embedding tags +<% %>+ and the name is written using the output embedding tag +<%= %>+. Note that this is not just a usage suggestion, for Regular output functions like print or puts won't work with ERB templates. So this would be wrong: +The loop is setup in regular embedding tags +<% %>+ and the name is written using the output embedding tag +<%= %>+. Note that this is not just a usage suggestion, for Regular output functions like print or puts won't work with ERB templates. So this would be wrong: <%# WRONG %> Hi, Mr. <% puts "Frodo" %> -To suppress leading and trailing whitespaces, you can use +<%-+ +-%>+ interchangeably with +<%+ and +%>+. +To suppress leading and trailing whitespaces, you can use +<%-+ +-%>+ interchangeably with +<%+ and +%>+. h5. Builder diff --git a/railties/guides/source/active_model_basics.textile b/railties/guides/source/active_model_basics.textile index 0672669dc5..73df567579 100644 --- a/railties/guides/source/active_model_basics.textile +++ b/railties/guides/source/active_model_basics.textile @@ -163,12 +163,14 @@ person.first_name_changed? #=> true
Track what was the previous value of the attribute. + #attr_name_was accessor person.first_name_was #=> "First Name" Track both previous and current value of the changed attribute. Returns an array if changed else returns nil + #attr_name_change person.first_name_change #=> ["First Name", "First Name 1"] diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 4e77a6e803..3a163fb943 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -132,7 +132,7 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1 Model.last returns +nil+ if no matching record is found. No exception will be raised. -h5. +first!+ +h5(#first-1). +first!+ Model.first! finds the first record. For example: @@ -149,7 +149,7 @@ SELECT * FROM clients LIMIT 1 Model.first! raises +RecordNotFound+ if no matching record is found. -h5. +last!+ +h5(#last-1). +last!+ Model.last! finds the last record. For example: diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index b2436a2e68..aab14dac8d 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -190,7 +190,7 @@ WARNING: Fixnums and symbols have no singleton classes, +singleton_class+ raises NOTE: Defined in +active_support/core_ext/kernel/singleton_class.rb+. -h4. +class_eval(*args, &block)+ +h4. +class_eval(*args, &block)+ You can evaluate code in the context of any object's singleton class using +class_eval+: @@ -2097,7 +2097,7 @@ NOTE: Defined in +active_support/core_ext/array/prepend_and_append.rb+. h4. Options Extraction -When the last argument in a method call is a hash, except perhaps for a +&block+ argument, Ruby allows you to omit the brackets: +When the last argument in a method call is a hash, except perhaps for a +&block+ argument, Ruby allows you to omit the brackets: User.exists?(:email => params[:email]) diff --git a/railties/guides/source/ajax_on_rails.textile b/railties/guides/source/ajax_on_rails.textile index 77f7661deb..e189c49bcd 100644 --- a/railties/guides/source/ajax_on_rails.textile +++ b/railties/guides/source/ajax_on_rails.textile @@ -67,7 +67,7 @@ link_to_remote "Add to cart", If the server returns 200, the output of the above example is equivalent to our first, simple one. However, in case of error, the element with the DOM id +error+ is updated rather than the +cart+ element. -** *position* By default (i.e. when not specifying this option, like in the examples before) the response is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities: +** *:position* By default (i.e. when not specifying this option, like in the examples before) the response is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities: *** +:before+ Inserts the response text just before the target element. More precisely, it creates a text node from the response and inserts it as the left sibling of the target element. *** +:after+ Similar behavior to +:before+, but in this case the response is inserted after the target element. *** +:top+ Inserts the text into the target element, before it's original content. If the target element was empty, this is equivalent with not specifying +:position+ at all. @@ -123,7 +123,9 @@ link_to_remote "Add new item", :update => "item_list", 404 => "alert('Item not found!')" + Let's see a typical example for the most frequent callbacks, +:success+, +:failure+ and +:complete+ in action: + link_to_remote "Add new item", :url => items_url, @@ -133,7 +135,9 @@ link_to_remote "Add new item", :success => "display_item_added(request)", :failure => "display_error(request)" + ** *:type* If you want to fire a synchronous request for some obscure reason (blocking the browser while the request is processed and doesn't return a status code), you can use the +:type+ option with the value of +:synchronous+. + * Finally, using the +html_options+ parameter you can add HTML attributes to the generated tag. It works like the same parameter of the +link_to+ helper. There are interesting side effects for the +href+ and +onclick+ parameters though: ** If you specify the +href+ parameter, the AJAX link will degrade gracefully, i.e. the link will point to the URL even if JavaScript is disabled in the client browser ** +link_to_remote+ gains it's AJAX behavior by specifying the remote call in the onclick handler of the link. If you supply +html_options[:onclick]+ you override the default behavior, so use this with care! diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index cfed1b5bdf..bbd2e24da5 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -62,11 +62,11 @@ This has several disadvantages:
  1. - Not all caches will cache content with a query string
    + Not all caches will cache content with a query string
    "Steve Souders recommends":http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/, "...avoiding a querystring for cacheable resources". He found that in these case 5-20% of requests will not be cached.
  2. - The file name can change between nodes in multi-server environments.
    + The file name can change between nodes in multi-server environments.
    The query string in Rails is based on the modification time of the files. When assets are deployed to a cluster, there is no guarantee that the timestamps will be the same, resulting in different values being used depending on which server handles the request.
@@ -91,7 +91,7 @@ This is not to say that assets can (or should) no longer be placed in +public+; When a scaffold or controller is generated for the application, Rails also generates a JavaScript file (or CoffeeScript file if the +coffee-rails+ gem is in the +Gemfile+) and a Cascading Style Sheet file (or SCSS file if +sass-rails+ is in the +Gemfile+) for that controller. -For example, if a +ProjectsController+ is generated, there will be a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as +<%= javascript_include_tag params[:controller] %>+ or +<%= stylesheet_link_tag params[:controller] %>+. +For example, if a +ProjectsController+ is generated, there will be a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as +<%= javascript_include_tag params[:controller] %>+ or +<%= stylesheet_link_tag params[:controller] %>+. NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use CoffeeScript. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index c277f5723a..9b35c409b3 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -98,7 +98,7 @@ form_tag({:controller => "people", :action => "search"}, :method => "get", :clas h4. Helpers for Generating Form Elements -Rails provides a series of helpers for generating form elements such as checkboxes, text fields, and radio buttons. These basic helpers, with names ending in "_tag" (such as +text_field_tag+ and +check_box_tag+), generate just a single +<input>+ element. The first parameter to these is always the name of the input. When the form is submitted, the name will be passed along with the form data, and will make its way to the +params+ hash in the controller with the value entered by the user for that field. For example, if the form contains +<%= text_field_tag(:query) %>+, then you would be able to get the value of this field in the controller with +params[:query]+. +Rails provides a series of helpers for generating form elements such as checkboxes, text fields, and radio buttons. These basic helpers, with names ending in "_tag" (such as +text_field_tag+ and +check_box_tag+), generate just a single +<input>+ element. The first parameter to these is always the name of the input. When the form is submitted, the name will be passed along with the form data, and will make its way to the +params+ hash in the controller with the value entered by the user for that field. For example, if the form contains +<%= text_field_tag(:query) %>+, then you would be able to get the value of this field in the controller with +params[:query]+. When naming inputs, Rails uses certain conventions that make it possible to submit parameters with non-scalar values such as arrays or hashes, which will also be accessible in +params+. You can read more about them in "chapter 7 of this guide":#understanding-parameter-naming-conventions. For details on the precise usage of these helpers, please refer to the "API documentation":http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html. diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile index 2fa1d6e21d..24f100187a 100644 --- a/railties/guides/source/generators.textile +++ b/railties/guides/source/generators.textile @@ -1,4 +1,4 @@ -h2. Creating and Customizing Rails Generators & Templates +h2. Creating and Customizing Rails Generators & Templates Rails generators are an essential tool if you plan to improve your workflow. With this guide you will learn how to create generators and customize existing ones. diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 9cc4dd5f04..3804f5e81f 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -454,7 +454,7 @@ app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", TOPLEVEL_BINDING, config
-The initialize method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run: +The +initialize+ method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run: require ::File.expand_path('../config/environment', __FILE__) @@ -676,11 +676,11 @@ h4. Back to +railties/lib/rails/railtie.rb+ Once the inflector files have been loaded, the +Rails::Railtie+ class is defined. This class includes a module called +Initializable+, which is actually +Rails::Initializable+. This module includes the +initializer+ method which is used later on for setting up initializers, amongst other methods. -h4. +railties/lib/rails/initializable.rb+ +h4(#railties-lib-rails-initializable-rb-1). +railties/lib/rails/initializable.rb+ When the module from this file (+Rails::Initializable+) is included, it extends the class it's included into with the +ClassMethods+ module inside of it. This module defines the +initializer+ method which is used to define initializers throughout all of the railties. This file completes the loading of +railties/lib/rails/railtie.rb+. Now we go back to +rails/engine.rb+. -h4. +railties/lib/rails/engine.rb+ +h4(#railties-lib-rails-engine-rb-1). +railties/lib/rails/engine.rb+ The next file required in +rails/engine.rb+ is +active_support/core_ext/module/delegation+ which is documented in the "Active Support Core Extensions Guide":http://guides.rubyonrails.org/active_support_core_extensions.html#method-delegation. diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile index 75f81cf13d..0ea88d8385 100644 --- a/railties/guides/source/performance_testing.textile +++ b/railties/guides/source/performance_testing.textile @@ -207,7 +207,7 @@ GC Time measures the amount of time spent in GC for the performance test case. h5. Metric Availability -h6. Benchmarking +h6(#benchmarking-1). Benchmarking |_.Interpreter|_.Wall Time|_.Process Time|_.CPU Time|_.User Time|_.Memory|_.Objects|_.GC Runs|_.GC Time| |_.MRI | yes | yes | yes | no | yes | yes | yes | yes | @@ -215,7 +215,7 @@ h6. Benchmarking |_.Rubinius | yes | no | no | no | yes | yes | yes | yes | |_.JRuby | yes | no | no | yes | yes | yes | yes | yes | -h6. Profiling +h6(#profiling-1). Profiling |_.Interpreter|_.Wall Time|_.Process Time|_.CPU Time|_.User Time|_.Memory|_.Objects|_.GC Runs|_.GC Time| |_.MRI | yes | yes | no | no | yes | yes | yes | yes | -- cgit v1.2.3 From 67790644372ad3a771810f1d6d99687d795789ea Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Thu, 1 Sep 2011 23:54:17 -0500 Subject: Remove hard dependency on bcrypt. --- Gemfile | 1 + activemodel/activemodel.gemspec | 1 - activemodel/lib/active_model/secure_password.rb | 5 +++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index f0880926a3..d36aec6b4a 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ if ENV['AREL'] gem "arel", :path => ENV['AREL'] end +gem "bcrypt-ruby", "~> 3.0.0" gem "jquery-rails" # This needs to be with require false to avoid # it being automatically loaded by sprockets diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index e5075485bb..260ad01b65 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -19,5 +19,4 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', version) s.add_dependency('builder', '~> 3.0.0') s.add_dependency('i18n', '~> 0.6') - s.add_dependency('bcrypt-ruby', '~> 3.0.0') end diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 63380d6ffd..a73276199a 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -1,5 +1,3 @@ -require 'bcrypt' - module ActiveModel module SecurePassword extend ActiveSupport::Concern @@ -30,6 +28,9 @@ module ActiveModel # User.find_by_name("david").try(:authenticate, "notright") # => nil # User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user def has_secure_password + gem 'bcrypt-ruby', '~> 3.0.0' + require 'bcrypt' + attr_reader :password validates_confirmation_of :password -- cgit v1.2.3 From 220c77dd68430cc150c61119a14c86dee659911c Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Fri, 2 Sep 2011 22:42:23 +0530 Subject: debug option to js, stylesheet tags are ignored when debug mode is off --- railties/guides/source/asset_pipeline.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 73f77ac05e..86ae23ab11 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -277,7 +277,7 @@ Debug can also be set in the Rails helper methods: <%= javascript_include_tag "application", :debug => true %> -Don't forget to remove this before deploying to production! +The +:debug+ option is ignored if the debug mode is off. You could potentially also enable compression in development mode as a sanity check, and disable it on-demand as required for debugging. -- cgit v1.2.3 From 44284a613b3efe2319db3f84090c0004505942c1 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Fri, 2 Sep 2011 22:57:03 +0530 Subject: Revert "Fixing guides validation errors." This reverts commit d20281add192e5afba66e555ce67cf73943b033b. Reason: This needs more investigation. Will apply when this is verified. --- railties/guides/source/action_view_overview.textile | 6 +++--- railties/guides/source/active_model_basics.textile | 2 -- railties/guides/source/active_record_querying.textile | 4 ++-- railties/guides/source/active_support_core_extensions.textile | 4 ++-- railties/guides/source/ajax_on_rails.textile | 6 +----- railties/guides/source/asset_pipeline.textile | 6 +++--- railties/guides/source/form_helpers.textile | 2 +- railties/guides/source/generators.textile | 2 +- railties/guides/source/initialization.textile | 6 +++--- railties/guides/source/performance_testing.textile | 4 ++-- 10 files changed, 18 insertions(+), 24 deletions(-) diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index c43fd8cc14..5a1e8b1247 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -126,7 +126,7 @@ Rails supports multiple template systems and uses a file extension to distinguis h5. ERB -Within an ERB template Ruby code can be included using both +<% %>+ and +<%= %>+ tags. The +<% %>+ are used to execute Ruby code that does not return anything, such as conditions, loops or blocks, and the +<%= %>+ tags are used when you want output. +Within an ERB template Ruby code can be included using both +<% %>+ and +<%= %>+ tags. The +<% %>+ are used to execute Ruby code that does not return anything, such as conditions, loops or blocks, and the +<%= %>+ tags are used when you want output. Consider the following loop for names: @@ -137,14 +137,14 @@ Consider the following loop for names: <% end %> -The loop is setup in regular embedding tags +<% %>+ and the name is written using the output embedding tag +<%= %>+. Note that this is not just a usage suggestion, for Regular output functions like print or puts won't work with ERB templates. So this would be wrong: +The loop is setup in regular embedding tags +<% %>+ and the name is written using the output embedding tag +<%= %>+. Note that this is not just a usage suggestion, for Regular output functions like print or puts won't work with ERB templates. So this would be wrong: <%# WRONG %> Hi, Mr. <% puts "Frodo" %> -To suppress leading and trailing whitespaces, you can use +<%-+ +-%>+ interchangeably with +<%+ and +%>+. +To suppress leading and trailing whitespaces, you can use +<%-+ +-%>+ interchangeably with +<%+ and +%>+. h5. Builder diff --git a/railties/guides/source/active_model_basics.textile b/railties/guides/source/active_model_basics.textile index 73df567579..0672669dc5 100644 --- a/railties/guides/source/active_model_basics.textile +++ b/railties/guides/source/active_model_basics.textile @@ -163,14 +163,12 @@ person.first_name_changed? #=> true Track what was the previous value of the attribute. - #attr_name_was accessor person.first_name_was #=> "First Name" Track both previous and current value of the changed attribute. Returns an array if changed else returns nil - #attr_name_change person.first_name_change #=> ["First Name", "First Name 1"] diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 3a163fb943..4e77a6e803 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -132,7 +132,7 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1 Model.last returns +nil+ if no matching record is found. No exception will be raised. -h5(#first-1). +first!+ +h5. +first!+ Model.first! finds the first record. For example: @@ -149,7 +149,7 @@ SELECT * FROM clients LIMIT 1 Model.first! raises +RecordNotFound+ if no matching record is found. -h5(#last-1). +last!+ +h5. +last!+ Model.last! finds the last record. For example: diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index aab14dac8d..b2436a2e68 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -190,7 +190,7 @@ WARNING: Fixnums and symbols have no singleton classes, +singleton_class+ raises NOTE: Defined in +active_support/core_ext/kernel/singleton_class.rb+. -h4. +class_eval(*args, &block)+ +h4. +class_eval(*args, &block)+ You can evaluate code in the context of any object's singleton class using +class_eval+: @@ -2097,7 +2097,7 @@ NOTE: Defined in +active_support/core_ext/array/prepend_and_append.rb+. h4. Options Extraction -When the last argument in a method call is a hash, except perhaps for a +&block+ argument, Ruby allows you to omit the brackets: +When the last argument in a method call is a hash, except perhaps for a +&block+ argument, Ruby allows you to omit the brackets: User.exists?(:email => params[:email]) diff --git a/railties/guides/source/ajax_on_rails.textile b/railties/guides/source/ajax_on_rails.textile index e189c49bcd..77f7661deb 100644 --- a/railties/guides/source/ajax_on_rails.textile +++ b/railties/guides/source/ajax_on_rails.textile @@ -67,7 +67,7 @@ link_to_remote "Add to cart", If the server returns 200, the output of the above example is equivalent to our first, simple one. However, in case of error, the element with the DOM id +error+ is updated rather than the +cart+ element. -** *:position* By default (i.e. when not specifying this option, like in the examples before) the response is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities: +** *position* By default (i.e. when not specifying this option, like in the examples before) the response is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities: *** +:before+ Inserts the response text just before the target element. More precisely, it creates a text node from the response and inserts it as the left sibling of the target element. *** +:after+ Similar behavior to +:before+, but in this case the response is inserted after the target element. *** +:top+ Inserts the text into the target element, before it's original content. If the target element was empty, this is equivalent with not specifying +:position+ at all. @@ -123,9 +123,7 @@ link_to_remote "Add new item", :update => "item_list", 404 => "alert('Item not found!')" - Let's see a typical example for the most frequent callbacks, +:success+, +:failure+ and +:complete+ in action: - link_to_remote "Add new item", :url => items_url, @@ -135,9 +133,7 @@ link_to_remote "Add new item", :success => "display_item_added(request)", :failure => "display_error(request)" - ** *:type* If you want to fire a synchronous request for some obscure reason (blocking the browser while the request is processed and doesn't return a status code), you can use the +:type+ option with the value of +:synchronous+. - * Finally, using the +html_options+ parameter you can add HTML attributes to the generated tag. It works like the same parameter of the +link_to+ helper. There are interesting side effects for the +href+ and +onclick+ parameters though: ** If you specify the +href+ parameter, the AJAX link will degrade gracefully, i.e. the link will point to the URL even if JavaScript is disabled in the client browser ** +link_to_remote+ gains it's AJAX behavior by specifying the remote call in the onclick handler of the link. If you supply +html_options[:onclick]+ you override the default behavior, so use this with care! diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 86ae23ab11..192c393dca 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -62,11 +62,11 @@ This has several disadvantages:
  1. - Not all caches will cache content with a query string
    + Not all caches will cache content with a query string
    "Steve Souders recommends":http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/, "...avoiding a querystring for cacheable resources". He found that in these case 5-20% of requests will not be cached.
  2. - The file name can change between nodes in multi-server environments.
    + The file name can change between nodes in multi-server environments.
    The query string in Rails is based on the modification time of the files. When assets are deployed to a cluster, there is no guarantee that the timestamps will be the same, resulting in different values being used depending on which server handles the request.
@@ -93,7 +93,7 @@ In production, the default is to precompile these files to +public/assets+ so th When a scaffold or controller is generated for the application, Rails also generates a JavaScript file (or CoffeeScript file if the +coffee-rails+ gem is in the +Gemfile+) and a Cascading Style Sheet file (or SCSS file if +sass-rails+ is in the +Gemfile+) for that controller. -For example, if a +ProjectsController+ is generated, there will be a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as +<%= javascript_include_tag params[:controller] %>+ or +<%= stylesheet_link_tag params[:controller] %>+. +For example, if a +ProjectsController+ is generated, there will be a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as +<%= javascript_include_tag params[:controller] %>+ or +<%= stylesheet_link_tag params[:controller] %>+. NOTE: You will need a "ExecJS":https://github.com/sstephenson/execjs#readme - supported runtime in order to use CoffeeScript. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index 9b35c409b3..c277f5723a 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -98,7 +98,7 @@ form_tag({:controller => "people", :action => "search"}, :method => "get", :clas h4. Helpers for Generating Form Elements -Rails provides a series of helpers for generating form elements such as checkboxes, text fields, and radio buttons. These basic helpers, with names ending in "_tag" (such as +text_field_tag+ and +check_box_tag+), generate just a single +<input>+ element. The first parameter to these is always the name of the input. When the form is submitted, the name will be passed along with the form data, and will make its way to the +params+ hash in the controller with the value entered by the user for that field. For example, if the form contains +<%= text_field_tag(:query) %>+, then you would be able to get the value of this field in the controller with +params[:query]+. +Rails provides a series of helpers for generating form elements such as checkboxes, text fields, and radio buttons. These basic helpers, with names ending in "_tag" (such as +text_field_tag+ and +check_box_tag+), generate just a single +<input>+ element. The first parameter to these is always the name of the input. When the form is submitted, the name will be passed along with the form data, and will make its way to the +params+ hash in the controller with the value entered by the user for that field. For example, if the form contains +<%= text_field_tag(:query) %>+, then you would be able to get the value of this field in the controller with +params[:query]+. When naming inputs, Rails uses certain conventions that make it possible to submit parameters with non-scalar values such as arrays or hashes, which will also be accessible in +params+. You can read more about them in "chapter 7 of this guide":#understanding-parameter-naming-conventions. For details on the precise usage of these helpers, please refer to the "API documentation":http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html. diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile index 24f100187a..2fa1d6e21d 100644 --- a/railties/guides/source/generators.textile +++ b/railties/guides/source/generators.textile @@ -1,4 +1,4 @@ -h2. Creating and Customizing Rails Generators & Templates +h2. Creating and Customizing Rails Generators & Templates Rails generators are an essential tool if you plan to improve your workflow. With this guide you will learn how to create generators and customize existing ones. diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 3804f5e81f..9cc4dd5f04 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -454,7 +454,7 @@ app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", TOPLEVEL_BINDING, config
-The +initialize+ method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run: +The initialize method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run: require ::File.expand_path('../config/environment', __FILE__) @@ -676,11 +676,11 @@ h4. Back to +railties/lib/rails/railtie.rb+ Once the inflector files have been loaded, the +Rails::Railtie+ class is defined. This class includes a module called +Initializable+, which is actually +Rails::Initializable+. This module includes the +initializer+ method which is used later on for setting up initializers, amongst other methods. -h4(#railties-lib-rails-initializable-rb-1). +railties/lib/rails/initializable.rb+ +h4. +railties/lib/rails/initializable.rb+ When the module from this file (+Rails::Initializable+) is included, it extends the class it's included into with the +ClassMethods+ module inside of it. This module defines the +initializer+ method which is used to define initializers throughout all of the railties. This file completes the loading of +railties/lib/rails/railtie.rb+. Now we go back to +rails/engine.rb+. -h4(#railties-lib-rails-engine-rb-1). +railties/lib/rails/engine.rb+ +h4. +railties/lib/rails/engine.rb+ The next file required in +rails/engine.rb+ is +active_support/core_ext/module/delegation+ which is documented in the "Active Support Core Extensions Guide":http://guides.rubyonrails.org/active_support_core_extensions.html#method-delegation. diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile index 0ea88d8385..75f81cf13d 100644 --- a/railties/guides/source/performance_testing.textile +++ b/railties/guides/source/performance_testing.textile @@ -207,7 +207,7 @@ GC Time measures the amount of time spent in GC for the performance test case. h5. Metric Availability -h6(#benchmarking-1). Benchmarking +h6. Benchmarking |_.Interpreter|_.Wall Time|_.Process Time|_.CPU Time|_.User Time|_.Memory|_.Objects|_.GC Runs|_.GC Time| |_.MRI | yes | yes | yes | no | yes | yes | yes | yes | @@ -215,7 +215,7 @@ h6(#benchmarking-1). Benchmarking |_.Rubinius | yes | no | no | no | yes | yes | yes | yes | |_.JRuby | yes | no | no | yes | yes | yes | yes | yes | -h6(#profiling-1). Profiling +h6. Profiling |_.Interpreter|_.Wall Time|_.Process Time|_.CPU Time|_.User Time|_.Memory|_.Objects|_.GC Runs|_.GC Time| |_.MRI | yes | yes | no | no | yes | yes | yes | yes | -- cgit v1.2.3 From 78497c7c27879aa735db24377f056de96a260bb9 Mon Sep 17 00:00:00 2001 From: Franco Catena Date: Fri, 2 Sep 2011 14:52:58 -0300 Subject: Change photos_path to photos_url in Using redirect_to Is more "correct" a complete url than only the path --- railties/guides/source/layouts_and_rendering.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index 3252f17c56..f49c2000ee 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -515,7 +515,7 @@ h4. Using +redirect_to+ Another way to handle returning responses to an HTTP request is with +redirect_to+. As you've seen, +render+ tells Rails which view (or other asset) to use in constructing a response. The +redirect_to+ method does something completely different: it tells the browser to send a new request for a different URL. For example, you could redirect from wherever you are in your code to the index of photos in your application with this call: -redirect_to photos_path +redirect_to photos_url You can use +redirect_to+ with any arguments that you could use with +link_to+ or +url_for+. In addition, there's a special redirect that sends the user back to the page they just came from: -- cgit v1.2.3 From f83f169b85eea4f580ae95609506fbb3cc5b8ccb Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Sat, 3 Sep 2011 01:40:00 +0530 Subject: some of the changes for validation earlier reverted from d20281a --- railties/guides/source/active_model_basics.textile | 2 ++ railties/guides/source/active_record_querying.textile | 4 ++-- railties/guides/source/performance_testing.textile | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/active_model_basics.textile b/railties/guides/source/active_model_basics.textile index 0672669dc5..73df567579 100644 --- a/railties/guides/source/active_model_basics.textile +++ b/railties/guides/source/active_model_basics.textile @@ -163,12 +163,14 @@ person.first_name_changed? #=> true Track what was the previous value of the attribute. + #attr_name_was accessor person.first_name_was #=> "First Name" Track both previous and current value of the changed attribute. Returns an array if changed else returns nil + #attr_name_change person.first_name_change #=> ["First Name", "First Name 1"] diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 4e77a6e803..95a7bfebc3 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -132,7 +132,7 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1 Model.last returns +nil+ if no matching record is found. No exception will be raised. -h5. +first!+ +h5(#first_1). +first!+ Model.first! finds the first record. For example: @@ -149,7 +149,7 @@ SELECT * FROM clients LIMIT 1 Model.first! raises +RecordNotFound+ if no matching record is found. -h5. +last!+ +h5(#last_1). +last!+ Model.last! finds the last record. For example: diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile index 75f81cf13d..5947735deb 100644 --- a/railties/guides/source/performance_testing.textile +++ b/railties/guides/source/performance_testing.textile @@ -207,7 +207,7 @@ GC Time measures the amount of time spent in GC for the performance test case. h5. Metric Availability -h6. Benchmarking +h6(#benchmarking_1). Benchmarking |_.Interpreter|_.Wall Time|_.Process Time|_.CPU Time|_.User Time|_.Memory|_.Objects|_.GC Runs|_.GC Time| |_.MRI | yes | yes | yes | no | yes | yes | yes | yes | @@ -215,7 +215,7 @@ h6. Benchmarking |_.Rubinius | yes | no | no | no | yes | yes | yes | yes | |_.JRuby | yes | no | no | yes | yes | yes | yes | yes | -h6. Profiling +h6(#profiling_1). Profiling |_.Interpreter|_.Wall Time|_.Process Time|_.CPU Time|_.User Time|_.Memory|_.Objects|_.GC Runs|_.GC Time| |_.MRI | yes | yes | no | no | yes | yes | yes | yes | -- cgit v1.2.3 From b3a03253a78234dfc3bef0fab7dae2e49c2bfd2a Mon Sep 17 00:00:00 2001 From: David Peckham Date: Fri, 2 Sep 2011 13:38:13 -0700 Subject: Fixed a typo in the section about migration. --- railties/guides/source/getting_started.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 256df0eded..6e9613cdae 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -592,7 +592,7 @@ class CreatePosts < ActiveRecord::Migration end -The above migration creates a method name +change+ which will be called when you +The above migration creates a method named +change+ which will be called when you run this migration. The action defined in that method is also reversible, which means Rails knows how to reverse the change made by this migration, in case you want to reverse it at later date. By default, when you run this migration it -- cgit v1.2.3 From a3edf3d2a307630980731b1963721c60ba2a14e0 Mon Sep 17 00:00:00 2001 From: Richard Hulse Date: Sat, 3 Sep 2011 09:11:20 +1200 Subject: fix YUI description YUI CSS compressor does not extend syntax! Also added link to more info --- railties/guides/source/asset_pipeline.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 192c393dca..ef35d1ed76 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -437,7 +437,7 @@ h3. Customizing the Pipeline h4. CSS Compression -There is currently one option for compressing CSS, YUI. This Gem extends the CSS syntax and offers minification. +There is currently one option for compressing CSS, YUI. The "YUI CSS compressor":http://developer.yahoo.com/yui/compressor/css.html provides minification. The following line enables YUI compression, and requires the +yui-compressor+ gem. -- cgit v1.2.3 From 5b7bcb4959a33d7a31acdd2823eb3272bcd1f322 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Sat, 3 Sep 2011 02:44:49 +0530 Subject: document send_file guesses content type from the file extension and remove info about x_send_file option to send_file --- railties/guides/source/action_controller_overview.textile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile index 073e3bddcf..4e47712636 100644 --- a/railties/guides/source/action_controller_overview.textile +++ b/railties/guides/source/action_controller_overview.textile @@ -684,9 +684,11 @@ end This will read and stream the file 4kB at the time, avoiding loading the entire file into memory at once. You can turn off streaming with the +:stream+ option or adjust the block size with the +:buffer_size+ option. +If +:type+ is not specified, it will be guessed from the file extension specified in +:filename+. If the content type is not registered for the extension, application/octet-stream will be used. + WARNING: Be careful when using data coming from the client (params, cookies, etc.) to locate the file on disk, as this is a security risk that might allow someone to gain access to files they are not meant to see. -TIP: It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack. Although if you do need the request to go through Rails for some reason, you can set the +:x_sendfile+ option to true, and Rails will let the web server handle sending the file to the user, freeing up the Rails process to do other things. Note that your web server needs to support the +X-Sendfile+ header for this to work. +TIP: It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack. h4. RESTful Downloads -- cgit v1.2.3 From 1b8290db527e29c6b503cb036bc42d67368f766c Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Fri, 2 Sep 2011 17:10:11 -0500 Subject: Fix asset_path example in CSS and ERB section --- railties/guides/source/asset_pipeline.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index ef35d1ed76..82aa0a5256 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -147,7 +147,7 @@ h5. CSS and ERB If you add an +erb+ extension to a CSS asset, making it something such as +application.css.erb+, then you can use the +asset_path+ helper in your CSS rules: -.class { background-image: <%= asset_path 'image.png' %> } +.class { background-image: url(<%= asset_path 'image.png') %> } This writes the path to the particular asset being referenced. In this example, it would make sense to have an image in one of the asset load paths, such as +app/assets/images/image.png+, which would be referenced here. If this image is already available in +public/assets+ as a fingerprinted file, then that path is referenced. -- cgit v1.2.3 From 5912ed99029f76b3ec51955f05323b77fa0b22f2 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sat, 3 Sep 2011 01:36:57 +0200 Subject: fixes CSS example in the asset pipeline guide --- railties/guides/source/asset_pipeline.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 192c393dca..6935533f4a 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -147,7 +147,7 @@ h5. CSS and ERB If you add an +erb+ extension to a CSS asset, making it something such as +application.css.erb+, then you can use the +asset_path+ helper in your CSS rules: -.class { background-image: <%= asset_path 'image.png' %> } +.class { background-image: url(<%= asset_path 'image.png' %>) } This writes the path to the particular asset being referenced. In this example, it would make sense to have an image in one of the asset load paths, such as +app/assets/images/image.png+, which would be referenced here. If this image is already available in +public/assets+ as a fingerprinted file, then that path is referenced. -- cgit v1.2.3 From af54fc5586f00bbb82063f5110801ef08ad9ff39 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Sat, 3 Sep 2011 00:05:37 -0500 Subject: Add bcrypt-ruby to Gemfile template --- railties/lib/rails/generators/rails/app/templates/Gemfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index c83e7ddf80..910cd16950 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -10,6 +10,9 @@ source 'http://rubygems.org' <%= assets_gemfile_entry %> <%= javascript_gemfile_entry %> +# To use ActiveModel has_secure_password +# gem 'bcrypt-ruby', '~> 3.0.0' + # Use unicorn as the web server # gem 'unicorn' -- cgit v1.2.3 From 9b02f3f41f9be96bcc61222a8dcd197c1a2edf79 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Sat, 3 Sep 2011 00:27:07 -0500 Subject: Add comments about bcrypt-ruby gem to SecurePassword --- activemodel/lib/active_model/secure_password.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index a73276199a..7a109d9a52 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -10,6 +10,10 @@ module ActiveModel # a "password_confirmation" attribute) are automatically added. # You can add more validations by hand if need be. # + # You need to add bcrypt-ruby (~> 3.0.0) to Gemfile to use has_secure_password: + # + # gem 'bcrypt-ruby', '~> 3.0.0' + # # Example using Active Record (which automatically includes ActiveModel::SecurePassword): # # # Schema: User(name:string, password_digest:string) @@ -28,6 +32,8 @@ module ActiveModel # User.find_by_name("david").try(:authenticate, "notright") # => nil # User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user def has_secure_password + # Load bcrypt-ruby only when has_secured_password is used to avoid make ActiveModel + # (and by extension the entire framework) dependent on a binary library. gem 'bcrypt-ruby', '~> 3.0.0' require 'bcrypt' -- cgit v1.2.3 From 9984266c041e1079a09140f9307fc1ca13858988 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sat, 3 Sep 2011 14:43:33 +0700 Subject: Make `ActiveSupport::OrderedHash` extractable when using `Array#extract_options!` `ActiveSupport::OrderedHash` is actually a subclass of the hash, so it does make sense that it should be extractable from the array list. --- activesupport/CHANGELOG | 2 ++ activesupport/lib/active_support/ordered_hash.rb | 5 +++++ activesupport/test/ordered_hash_test.rb | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 3508ec0f34..18164234a5 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.2.0 (unreleased)* +* ActiveSupport::OrderedHash is now marked as extractable when using Array#extract_options! [Prem Sichanugrist] + * Added Array#prepend as an alias for Array#unshift and Array#append as an alias for Array#<< [DHH] * The definition of blank string for Ruby 1.9 has been extended to Unicode whitespace. diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index 7f70628933..0264133581 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -47,6 +47,11 @@ module ActiveSupport self end + # Returns true to make sure that this hash is extractable via Array#extract_options! + def extractable_options? + true + end + # Hash is ordered in Ruby 1.9! if RUBY_VERSION < '1.9' diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index bf851dbcbc..0b5f912dc4 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -329,4 +329,9 @@ class OrderedHashTest < Test::Unit::TestCase assert_equal expected, @ordered_hash.invert assert_equal @values.zip(@keys), @ordered_hash.invert.to_a end + + def test_extractable + @ordered_hash[:rails] = "snowman" + assert_equal @ordered_hash, [1, 2, @ordered_hash].extract_options! + end end -- cgit v1.2.3 From bf4117a8b1d29662902eedd4dbfc810d4b629395 Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Sat, 3 Sep 2011 10:07:07 +0530 Subject: Need to add here to pass the test As in previous commit it's removed. --- activerecord/test/cases/base_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 1e647b5970..8b95eb958b 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -24,6 +24,7 @@ require 'models/joke' require 'models/bulb' require 'rexml/document' require 'active_support/core_ext/exception' +require 'bcrypt' class Category < ActiveRecord::Base; end class Categorization < ActiveRecord::Base; end -- cgit v1.2.3 From 19ec3c1ae6d0e0b452a4b2d92b4840abb23f4035 Mon Sep 17 00:00:00 2001 From: Alexey Vakhov Date: Sat, 3 Sep 2011 23:13:40 +0400 Subject: fix helpers behavior description --- actionpack/lib/action_controller/metal/helpers.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index 2df0e9422c..bd515bba82 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -7,9 +7,12 @@ module ActionController # by default. # # In addition to using the standard template helpers provided, creating custom helpers to - # extract complicated logic or reusable functionality is strongly encouraged. By default, the controller will - # include a helper whose name matches that of the controller, e.g., MyController will automatically - # include MyHelper. + # extract complicated logic or reusable functionality is strongly encouraged. By default, each controller + # will include all helpers. + # + # In previous versions of \Rails the controller will include a helper whose + # name matches that of the controller, e.g., MyController will automatically + # include MyHelper. To return old behavior set +config.action_controller.include_all_helpers+ to +false+. # # Additional helpers can be specified using the +helper+ class method in ActionController::Base or any # controller which inherits from it. -- cgit v1.2.3 From 510a9707d8a3af5a81006cdb25e8089025acada1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 3 Sep 2011 15:12:48 -0700 Subject: Merge pull request #2835 from guilleiguaran/actionpack-changelog Include ticket numbers in AP CHANGELOG --- actionpack/CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 71f38797ae..31a03ea5d8 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -32,9 +32,9 @@ * CookieJar is now Enumerable. Fixes #2795 -* Fixed AssetNotPrecompiled error raised when rake assets:precompile is compiling certain .erb files. [Guillermo Iguaran] +* Fixed AssetNotPrecompiled error raised when rake assets:precompile is compiling certain .erb files. See GH #2763 #2765 #2805 [Guillermo Iguaran] -* Manifest is correctly placed in assets path when default assets prefix is changed. [Guillermo Iguaran] +* Manifest is correctly placed in assets path when default assets prefix is changed. Fixes #2776 [Guillermo Iguaran] * Fixed stylesheet_link_tag and javascript_include_tag to respect additional options passed by the users when debug is on. [Guillermo Iguaran] -- cgit v1.2.3 From 5014b330288d41680477800847e83e049a5b57c3 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Sun, 4 Sep 2011 03:44:47 +0530 Subject: add some missing dots in the docs --- railties/guides/source/configuring.textile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index 050fcd823d..ae84bb5b92 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -134,15 +134,15 @@ Rails 3.1, by default, is set up to use the +sprockets+ gem to manage assets wit * +config.assets.prefix+ defines the prefix where assets are served from. Defaults to +/assets+. -* +config.assets.digest+ enables the use of MD5 fingerprints in asset names. Set to +true+ by default in +production.rb+ +* +config.assets.digest+ enables the use of MD5 fingerprints in asset names. Set to +true+ by default in +production.rb+. -* +config.assets.debug+ disables the concatenation and compression of assets. Set to +false+ by default in +development.rb+ +* +config.assets.debug+ disables the concatenation and compression of assets. Set to +false+ by default in +development.rb+. -* +config.assets.manifest+ defines the full path to be used for the asset precompiler's manifest file. Defaults to using +config.assets.prefix+ +* +config.assets.manifest+ defines the full path to be used for the asset precompiler's manifest file. Defaults to using +config.assets.prefix+. * +config.assets.cache_store+ defines the cache store that Sprockets will use. The default is the Rails file store. -* +config.assets.version+ is an option string that is used in MD5 hash generation. This can be changed to force all files to be recompiled. +* +config.assets.version+ is an option string that is used in MD5 hash generation. This can be changed to force all files to be recompiled. * +config.assets.compile+ is a boolean that can be used to turn on live Sprockets compilation in production. -- cgit v1.2.3 From 0a38e2a5ce2eaf7393958721edbfcf2a7fe87334 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sat, 3 Sep 2011 15:20:18 -0700 Subject: restores the API docs of AR::Fixtures, made a quick pass over them, revises link in fixture template [closes #2840] --- activerecord/lib/active_record/fixtures.rb | 729 ++++++++++----------- activerecord/test/fixtures/tasks.yml | 2 +- .../test_unit/model/templates/fixtures.yml | 2 +- 3 files changed, 363 insertions(+), 370 deletions(-) diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 2674430116..6f1ec7f9b3 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -24,375 +24,368 @@ end class FixturesFileNotFound < StandardError; end -# Fixtures are a way of organizing data that you want to test against; in short, sample data. -# -# = Fixture formats -# -# Fixtures come in 1 flavor: -# -# 1. YAML fixtures -# -# == YAML fixtures -# -# This type of fixture is in YAML format and the preferred default. YAML is a file format which describes data structures -# in a non-verbose, human-readable format. It ships with Ruby 1.8.1+. -# -# Unlike single-file fixtures, YAML fixtures are stored in a single file per model, which are placed -# in the directory appointed by ActiveSupport::TestCase.fixture_path=(path) (this is -# automatically configured for Rails, so you can just put your files in /test/fixtures/). -# The fixture file ends with the .yml file extension (Rails example: -# /test/fixtures/web_sites.yml). The format of a YAML fixture file looks like this: -# -# rubyonrails: -# id: 1 -# name: Ruby on Rails -# url: http://www.rubyonrails.org -# -# google: -# id: 2 -# name: Google -# url: http://www.google.com -# -# This YAML fixture file includes two fixtures. Each YAML fixture (ie. record) is given a name and is followed by an -# indented list of key/value pairs in the "key: value" format. Records are separated by a blank line for your viewing -# pleasure. -# -# Note that YAML fixtures are unordered. If you want ordered fixtures, use the omap YAML type. -# See http://yaml.org/type/omap.html -# for the specification. You will need ordered fixtures when you have foreign key constraints on keys in the same table. -# This is commonly needed for tree structures. Example: -# -# --- !omap -# - parent: -# id: 1 -# parent_id: NULL -# title: Parent -# - child: -# id: 2 -# parent_id: 1 -# title: Child -# -# = Using fixtures in testcases -# -# Since fixtures are a testing construct, we use them in our unit and functional tests. There are two ways to use the -# fixtures, but first let's take a look at a sample unit test: -# -# require 'test_helper' -# -# class WebSiteTest < ActiveSupport::TestCase -# test "web_site_count" do -# assert_equal 2, WebSite.count -# end -# end -# -# By default, the test_helper module will load all of your fixtures into your test database, -# so this test will succeed. -# The testing environment will automatically load the all fixtures into the database before each test. -# To ensure consistent data, the environment deletes the fixtures before running the load. -# -# In addition to being available in the database, the fixture's data may also be accessed by -# using a special dynamic method, which has the same name as the model, and accepts the -# name of the fixture to instantiate: -# -# test "find" do -# assert_equal "Ruby on Rails", web_sites(:rubyonrails).name -# end -# -# Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the following tests: -# -# test "find_alt_method_1" do -# assert_equal "Ruby on Rails", @web_sites['rubyonrails']['name'] -# end -# -# test "find_alt_method_2" do -# assert_equal "Ruby on Rails", @rubyonrails.news -# end -# -# In order to use these methods to access fixtured data within your testcases, you must specify one of the -# following in your ActiveSupport::TestCase-derived class: -# -# - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above) -# self.use_instantiated_fixtures = true -# -# - create only the hash for the fixtures, do not 'find' each instance (enable alternate method #1 only) -# self.use_instantiated_fixtures = :no_instances -# -# Using either of these alternate methods incurs a performance hit, as the fixtured data must be fully -# traversed in the database to create the fixture hash and/or instance variables. This is expensive for -# large sets of fixtured data. -# -# = Dynamic fixtures with ERB -# -# Some times you don't care about the content of the fixtures as much as you care about the volume. In these cases, you can -# mix ERB in with your YAML fixtures to create a bunch of fixtures for load testing, like: -# -# <% (1..1000).each do |i| %> -# fix_<%= i %>: -# id: <%= i %> -# name: guy_<%= 1 %> -# <% end %> -# -# This will create 1000 very simple YAML fixtures. -# -# Using ERB, you can also inject dynamic values into your fixtures with inserts like <%= Date.today.strftime("%Y-%m-%d") %>. -# This is however a feature to be used with some caution. The point of fixtures are that they're -# stable units of predictable sample data. If you feel that you need to inject dynamic values, then -# perhaps you should reexamine whether your application is properly testable. Hence, dynamic values -# in fixtures are to be considered a code smell. -# -# = Transactional fixtures -# -# TestCases can use begin+rollback to isolate their changes to the database instead of having to -# delete+insert for every test case. -# -# class FooTest < ActiveSupport::TestCase -# self.use_transactional_fixtures = true -# -# test "godzilla" do -# assert !Foo.all.empty? -# Foo.destroy_all -# assert Foo.all.empty? -# end -# -# test "godzilla aftermath" do -# assert !Foo.all.empty? -# end -# end -# -# If you preload your test database with all fixture data (probably in the Rakefile task) and use transactional fixtures, -# then you may omit all fixtures declarations in your test cases since all the data's already there -# and every case rolls back its changes. -# -# In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to true. This will provide -# access to fixture data for every table that has been loaded through fixtures (depending on the -# value of +use_instantiated_fixtures+) -# -# When *not* to use transactional fixtures: -# -# 1. You're testing whether a transaction works correctly. Nested transactions don't commit until -# all parent transactions commit, particularly, the fixtures transaction which is begun in setup -# and rolled back in teardown. Thus, you won't be able to verify -# the results of your transaction until Active Record supports nested transactions or savepoints (in progress). -# 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM. -# Use InnoDB, MaxDB, or NDB instead. -# -# = Advanced YAML Fixtures -# -# YAML fixtures that don't specify an ID get some extra features: -# -# * Stable, autogenerated IDs -# * Label references for associations (belongs_to, has_one, has_many) -# * HABTM associations as inline lists -# * Autofilled timestamp columns -# * Fixture label interpolation -# * Support for YAML defaults -# -# == Stable, autogenerated IDs -# -# Here, have a monkey fixture: -# -# george: -# id: 1 -# name: George the Monkey -# -# reginald: -# id: 2 -# name: Reginald the Pirate -# -# Each of these fixtures has two unique identifiers: one for the database -# and one for the humans. Why don't we generate the primary key instead? -# Hashing each fixture's label yields a consistent ID: -# -# george: # generated id: 503576764 -# name: George the Monkey -# -# reginald: # generated id: 324201669 -# name: Reginald the Pirate -# -# Active Record looks at the fixture's model class, discovers the correct -# primary key, and generates it right before inserting the fixture -# into the database. -# -# The generated ID for a given label is constant, so we can discover -# any fixture's ID without loading anything, as long as we know the label. -# -# == Label references for associations (belongs_to, has_one, has_many) -# -# Specifying foreign keys in fixtures can be very fragile, not to -# mention difficult to read. Since Active Record can figure out the ID of -# any fixture from its label, you can specify FK's by label instead of ID. -# -# === belongs_to -# -# Let's break out some more monkeys and pirates. -# -# ### in pirates.yml -# -# reginald: -# id: 1 -# name: Reginald the Pirate -# monkey_id: 1 -# -# ### in monkeys.yml -# -# george: -# id: 1 -# name: George the Monkey -# pirate_id: 1 -# -# Add a few more monkeys and pirates and break this into multiple files, -# and it gets pretty hard to keep track of what's going on. Let's -# use labels instead of IDs: -# -# ### in pirates.yml -# -# reginald: -# name: Reginald the Pirate -# monkey: george -# -# ### in monkeys.yml -# -# george: -# name: George the Monkey -# pirate: reginald -# -# Pow! All is made clear. Active Record reflects on the fixture's model class, -# finds all the +belongs_to+ associations, and allows you to specify -# a target *label* for the *association* (monkey: george) rather than -# a target *id* for the *FK* (monkey_id: 1). -# -# ==== Polymorphic belongs_to -# -# Supporting polymorphic relationships is a little bit more complicated, since -# Active Record needs to know what type your association is pointing at. Something -# like this should look familiar: -# -# ### in fruit.rb -# -# belongs_to :eater, :polymorphic => true -# -# ### in fruits.yml -# -# apple: -# id: 1 -# name: apple -# eater_id: 1 -# eater_type: Monkey -# -# Can we do better? You bet! -# -# apple: -# eater: george (Monkey) -# -# Just provide the polymorphic target type and Active Record will take care of the rest. -# -# === has_and_belongs_to_many -# -# Time to give our monkey some fruit. -# -# ### in monkeys.yml -# -# george: -# id: 1 -# name: George the Monkey -# -# ### in fruits.yml -# -# apple: -# id: 1 -# name: apple -# -# orange: -# id: 2 -# name: orange -# -# grape: -# id: 3 -# name: grape -# -# ### in fruits_monkeys.yml -# -# apple_george: -# fruit_id: 1 -# monkey_id: 1 -# -# orange_george: -# fruit_id: 2 -# monkey_id: 1 -# -# grape_george: -# fruit_id: 3 -# monkey_id: 1 -# -# Let's make the HABTM fixture go away. -# -# ### in monkeys.yml -# -# george: -# id: 1 -# name: George the Monkey -# fruits: apple, orange, grape -# -# ### in fruits.yml -# -# apple: -# name: apple -# -# orange: -# name: orange -# -# grape: -# name: grape -# -# Zap! No more fruits_monkeys.yml file. We've specified the list of fruits -# on George's fixture, but we could've just as easily specified a list -# of monkeys on each fruit. As with +belongs_to+, Active Record reflects on -# the fixture's model class and discovers the +has_and_belongs_to_many+ -# associations. -# -# == Autofilled timestamp columns -# -# If your table/model specifies any of Active Record's -# standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+), -# they will automatically be set to Time.now. -# -# If you've set specific values, they'll be left alone. -# -# == Fixture label interpolation -# -# The label of the current fixture is always available as a column value: -# -# geeksomnia: -# name: Geeksomnia's Account -# subdomain: $LABEL -# -# Also, sometimes (like when porting older join table fixtures) you'll need -# to be able to get a hold of the identifier for a given label. ERB -# to the rescue: -# -# george_reginald: -# monkey_id: <%= ActiveRecord::Fixtures.identify(:reginald) %> -# pirate_id: <%= ActiveRecord::Fixtures.identify(:george) %> -# -# == Support for YAML defaults -# -# You probably already know how to use YAML to set and reuse defaults in -# your database.yml file. You can use the same technique in your fixtures: -# -# DEFAULTS: &DEFAULTS -# created_on: <%= 3.weeks.ago.to_s(:db) %> -# -# first: -# name: Smurf -# *DEFAULTS -# -# second: -# name: Fraggle -# *DEFAULTS -# -# Any fixture labeled "DEFAULTS" is safely ignored. - module ActiveRecord + # \Fixtures are a way of organizing data that you want to test against; in short, sample data. + # + # They are stored in YAML files, one file per model, which are placed in the directory + # appointed by ActiveSupport::TestCase.fixture_path=(path) (this is automatically + # configured for Rails, so you can just put your files in /test/fixtures/). + # The fixture file ends with the .yml file extension (Rails example: + # /test/fixtures/web_sites.yml). The format of a fixture file looks + # like this: + # + # rubyonrails: + # id: 1 + # name: Ruby on Rails + # url: http://www.rubyonrails.org + # + # google: + # id: 2 + # name: Google + # url: http://www.google.com + # + # This fixture file includes two fixtures. Each YAML fixture (ie. record) is given a name and + # is followed by an indented list of key/value pairs in the "key: value" format. Records are + # separated by a blank line for your viewing pleasure. + # + # Note that fixtures are unordered. If you want ordered fixtures, use the omap YAML type. + # See http://yaml.org/type/omap.html + # for the specification. You will need ordered fixtures when you have foreign key constraints + # on keys in the same table. This is commonly needed for tree structures. Example: + # + # --- !omap + # - parent: + # id: 1 + # parent_id: NULL + # title: Parent + # - child: + # id: 2 + # parent_id: 1 + # title: Child + # + # = Using Fixtures in Test Cases + # + # Since fixtures are a testing construct, we use them in our unit and functional tests. There + # are two ways to use the fixtures, but first let's take a look at a sample unit test: + # + # require 'test_helper' + # + # class WebSiteTest < ActiveSupport::TestCase + # test "web_site_count" do + # assert_equal 2, WebSite.count + # end + # end + # + # By default, test_helper.rb will load all of your fixtures into your test database, + # so this test will succeed. + # + # The testing environment will automatically load the all fixtures into the database before each + # test. To ensure consistent data, the environment deletes the fixtures before running the load. + # + # In addition to being available in the database, the fixture's data may also be accessed by + # using a special dynamic method, which has the same name as the model, and accepts the + # name of the fixture to instantiate: + # + # test "find" do + # assert_equal "Ruby on Rails", web_sites(:rubyonrails).name + # end + # + # Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the + # following tests: + # + # test "find_alt_method_1" do + # assert_equal "Ruby on Rails", @web_sites['rubyonrails']['name'] + # end + # + # test "find_alt_method_2" do + # assert_equal "Ruby on Rails", @rubyonrails.news + # end + # + # In order to use these methods to access fixtured data within your testcases, you must specify one of the + # following in your ActiveSupport::TestCase-derived class: + # + # - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above) + # self.use_instantiated_fixtures = true + # + # - create only the hash for the fixtures, do not 'find' each instance (enable alternate method #1 only) + # self.use_instantiated_fixtures = :no_instances + # + # Using either of these alternate methods incurs a performance hit, as the fixtured data must be fully + # traversed in the database to create the fixture hash and/or instance variables. This is expensive for + # large sets of fixtured data. + # + # = Dynamic fixtures with ERB + # + # Some times you don't care about the content of the fixtures as much as you care about the volume. + # In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load + # testing, like: + # + # <% 1.upto(1000) do |i| %> + # fix_<%= i %>: + # id: <%= i %> + # name: guy_<%= 1 %> + # <% end %> + # + # This will create 1000 very simple fixtures. + # + # Using ERB, you can also inject dynamic values into your fixtures with inserts like + # <%= Date.today.strftime("%Y-%m-%d") %>. + # This is however a feature to be used with some caution. The point of fixtures are that they're + # stable units of predictable sample data. If you feel that you need to inject dynamic values, then + # perhaps you should reexamine whether your application is properly testable. Hence, dynamic values + # in fixtures are to be considered a code smell. + # + # = Transactional Fixtures + # + # Test cases can use begin+rollback to isolate their changes to the database instead of having to + # delete+insert for every test case. + # + # class FooTest < ActiveSupport::TestCase + # self.use_transactional_fixtures = true + # + # test "godzilla" do + # assert !Foo.all.empty? + # Foo.destroy_all + # assert Foo.all.empty? + # end + # + # test "godzilla aftermath" do + # assert !Foo.all.empty? + # end + # end + # + # If you preload your test database with all fixture data (probably in the rake task) and use + # transactional fixtures, then you may omit all fixtures declarations in your test cases since + # all the data's already there and every case rolls back its changes. + # + # In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to + # true. This will provide access to fixture data for every table that has been loaded through + # fixtures (depending on the value of +use_instantiated_fixtures+). + # + # When *not* to use transactional fixtures: + # + # 1. You're testing whether a transaction works correctly. Nested transactions don't commit until + # all parent transactions commit, particularly, the fixtures transaction which is begun in setup + # and rolled back in teardown. Thus, you won't be able to verify + # the results of your transaction until Active Record supports nested transactions or savepoints (in progress). + # 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM. + # Use InnoDB, MaxDB, or NDB instead. + # + # = Advanced Fixtures + # + # Fixtures that don't specify an ID get some extra features: + # + # * Stable, autogenerated IDs + # * Label references for associations (belongs_to, has_one, has_many) + # * HABTM associations as inline lists + # * Autofilled timestamp columns + # * Fixture label interpolation + # * Support for YAML defaults + # + # == Stable, Autogenerated IDs + # + # Here, have a monkey fixture: + # + # george: + # id: 1 + # name: George the Monkey + # + # reginald: + # id: 2 + # name: Reginald the Pirate + # + # Each of these fixtures has two unique identifiers: one for the database + # and one for the humans. Why don't we generate the primary key instead? + # Hashing each fixture's label yields a consistent ID: + # + # george: # generated id: 503576764 + # name: George the Monkey + # + # reginald: # generated id: 324201669 + # name: Reginald the Pirate + # + # Active Record looks at the fixture's model class, discovers the correct + # primary key, and generates it right before inserting the fixture + # into the database. + # + # The generated ID for a given label is constant, so we can discover + # any fixture's ID without loading anything, as long as we know the label. + # + # == Label references for associations (belongs_to, has_one, has_many) + # + # Specifying foreign keys in fixtures can be very fragile, not to + # mention difficult to read. Since Active Record can figure out the ID of + # any fixture from its label, you can specify FK's by label instead of ID. + # + # === belongs_to + # + # Let's break out some more monkeys and pirates. + # + # ### in pirates.yml + # + # reginald: + # id: 1 + # name: Reginald the Pirate + # monkey_id: 1 + # + # ### in monkeys.yml + # + # george: + # id: 1 + # name: George the Monkey + # pirate_id: 1 + # + # Add a few more monkeys and pirates and break this into multiple files, + # and it gets pretty hard to keep track of what's going on. Let's + # use labels instead of IDs: + # + # ### in pirates.yml + # + # reginald: + # name: Reginald the Pirate + # monkey: george + # + # ### in monkeys.yml + # + # george: + # name: George the Monkey + # pirate: reginald + # + # Pow! All is made clear. Active Record reflects on the fixture's model class, + # finds all the +belongs_to+ associations, and allows you to specify + # a target *label* for the *association* (monkey: george) rather than + # a target *id* for the *FK* (monkey_id: 1). + # + # ==== Polymorphic belongs_to + # + # Supporting polymorphic relationships is a little bit more complicated, since + # Active Record needs to know what type your association is pointing at. Something + # like this should look familiar: + # + # ### in fruit.rb + # + # belongs_to :eater, :polymorphic => true + # + # ### in fruits.yml + # + # apple: + # id: 1 + # name: apple + # eater_id: 1 + # eater_type: Monkey + # + # Can we do better? You bet! + # + # apple: + # eater: george (Monkey) + # + # Just provide the polymorphic target type and Active Record will take care of the rest. + # + # === has_and_belongs_to_many + # + # Time to give our monkey some fruit. + # + # ### in monkeys.yml + # + # george: + # id: 1 + # name: George the Monkey + # + # ### in fruits.yml + # + # apple: + # id: 1 + # name: apple + # + # orange: + # id: 2 + # name: orange + # + # grape: + # id: 3 + # name: grape + # + # ### in fruits_monkeys.yml + # + # apple_george: + # fruit_id: 1 + # monkey_id: 1 + # + # orange_george: + # fruit_id: 2 + # monkey_id: 1 + # + # grape_george: + # fruit_id: 3 + # monkey_id: 1 + # + # Let's make the HABTM fixture go away. + # + # ### in monkeys.yml + # + # george: + # id: 1 + # name: George the Monkey + # fruits: apple, orange, grape + # + # ### in fruits.yml + # + # apple: + # name: apple + # + # orange: + # name: orange + # + # grape: + # name: grape + # + # Zap! No more fruits_monkeys.yml file. We've specified the list of fruits + # on George's fixture, but we could've just as easily specified a list + # of monkeys on each fruit. As with +belongs_to+, Active Record reflects on + # the fixture's model class and discovers the +has_and_belongs_to_many+ + # associations. + # + # == Autofilled Timestamp Columns + # + # If your table/model specifies any of Active Record's + # standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+), + # they will automatically be set to Time.now. + # + # If you've set specific values, they'll be left alone. + # + # == Fixture label interpolation + # + # The label of the current fixture is always available as a column value: + # + # geeksomnia: + # name: Geeksomnia's Account + # subdomain: $LABEL + # + # Also, sometimes (like when porting older join table fixtures) you'll need + # to be able to get a hold of the identifier for a given label. ERB + # to the rescue: + # + # george_reginald: + # monkey_id: <%= ActiveRecord::Fixtures.identify(:reginald) %> + # pirate_id: <%= ActiveRecord::Fixtures.identify(:george) %> + # + # == Support for YAML defaults + # + # You probably already know how to use YAML to set and reuse defaults in + # your database.yml file. You can use the same technique in your fixtures: + # + # DEFAULTS: &DEFAULTS + # created_on: <%= 3.weeks.ago.to_s(:db) %> + # + # first: + # name: Smurf + # *DEFAULTS + # + # second: + # name: Fraggle + # *DEFAULTS + # + # Any fixture labeled "DEFAULTS" is safely ignored. class Fixtures MAX_ID = 2 ** 30 - 1 diff --git a/activerecord/test/fixtures/tasks.yml b/activerecord/test/fixtures/tasks.yml index 01c95b3a4c..402ca85faf 100644 --- a/activerecord/test/fixtures/tasks.yml +++ b/activerecord/test/fixtures/tasks.yml @@ -1,4 +1,4 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html first_task: id: 1 starting: 2005-03-30t06:30:00.00+01:00 diff --git a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml index d4138ca2f5..5c8780aa64 100644 --- a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml +++ b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml @@ -1,4 +1,4 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html <% unless attributes.empty? -%> one: -- cgit v1.2.3 From 34618e6697475bca8b4bcfaaa2d55a99e78c031a Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Sun, 4 Sep 2011 08:17:53 +0530 Subject: Warnings removed for using shadow variable. --- railties/lib/rails/generators/actions.rb | 4 ++-- railties/test/generators/shared_generator_tests.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index a7462f39ba..c43a99e85c 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -119,8 +119,8 @@ module Rails if commands.is_a?(Symbol) run "git #{commands}" else - commands.each do |command, options| - run "git #{command} #{options}" + commands.each do |cmd, options| + run "git #{cmd} #{options}" end end end diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index d3074afd91..1534f0d828 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -191,11 +191,11 @@ module SharedCustomGeneratorTests end def test_builder_option_with_http - path = "http://gist.github.com/103208.txt" + url = "http://gist.github.com/103208.txt" template = "class #{builder_class}; end" template.instance_eval "def read; self; end" # Make the string respond to read - generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) + generator([destination_root], :builder => url).expects(:open).with(url, 'Accept' => 'application/x-thor-template').returns(template) quietly { generator.invoke_all } default_files.each{ |path| assert_no_file(path) } -- cgit v1.2.3 From c8d0dc376a72b976ccef17b8d0b413961b306a5f Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Sun, 4 Sep 2011 08:23:13 +0530 Subject: Warnings removed for "assert_match /" Please do not add more.! --- railties/test/application/asset_debugging_test.rb | 8 ++++---- railties/test/application/assets_test.rb | 18 +++++++++--------- railties/test/application/rake_test.rb | 6 +++--- railties/test/generators/plugin_new_generator_test.rb | 6 +++--- railties/test/railties/engine_test.rb | 2 +- railties/test/railties/shared_tests.rb | 10 +++++----- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb index 707abe7191..1b99af22a4 100644 --- a/railties/test/application/asset_debugging_test.rb +++ b/railties/test/application/asset_debugging_test.rb @@ -45,8 +45,8 @@ module ApplicationTests # the debug_assets params isn't used if compile is off get '/posts?debug_assets=true' - assert_match / -Assets are compiled and cached on the first request after the server is started. Sprockets sets a +must-validate+ Cache-Control HTTP header to reduce request overhead on subsequent requests -- on these the browser gets a 304 (not-modified) response. +Assets are compiled and cached on the first request after the server is started. Sprockets sets a +must-revalidate+ Cache-Control HTTP header to reduce request overhead on subsequent requests -- on these the browser gets a 304 (not-modified) response. If any of the files in the manifest have changed between requests, the server responds with a new compiled file. -- cgit v1.2.3 From e47bb1cbe7bb33318f2ed2f1ca021ddd71f6c50f Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Sun, 11 Sep 2011 19:44:42 +0530 Subject: merged the contribution guides and changed the link in the layout accordingly --- railties/guides/source/contributing_to_ruby_on_rails.textile | 10 ++++++---- railties/guides/source/layout.html.erb | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile index c302d393aa..968fa7a1f1 100644 --- a/railties/guides/source/contributing_to_ruby_on_rails.textile +++ b/railties/guides/source/contributing_to_ruby_on_rails.textile @@ -257,16 +257,18 @@ h3. Contributing to the Rails Documentation Ruby on Rails has two main sets of documentation: The guides help you to learn Ruby on Rails, and the API is a reference. -You can create an issue in GitHub issues to fix or expand documentation. However, if you're confident about your changes you can push them yourself directly via "docrails":https://github.com/lifo/docrails/tree/master. docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but that happens after they are pushed. docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation. +You can help improve the Rails guides by making them more coherent, adding missing information, correcting factual errors, fixing typos, bringing it up to date with the latest edge Rails. To get involved in the translation of Rails guides, please see "Translating Rails Guides":https://wiki.github.com/lifo/docrails/translating-rails-guides. + +If you're confident about your changes, you can push them yourself directly via "docrails":https://github.com/lifo/docrails. docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but that happens after they are pushed. docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation. + +If you are unsure of the documentation changes, you can create an issue in the "Rails":https://github.com/rails/rails repository on GitHub. When working with documentation, please take into account the "API Documentation Guidelines":api_documentation_guidelines.html and the "Ruby on Rails Guides Guidelines":ruby_on_rails_guides_guidelines.html. -NOTE: As explained above, ordinary code patches should have proper documentation coverage. docrails is only used for isolated documentation improvements. +NOTE: As explained earlier, ordinary code patches should have proper documentation coverage. docrails is only used for isolated documentation improvements. WARNING: docrails has a very strict policy: no code can be touched whatsoever, no matter how trivial or small the change. Only RDoc and guides can be edited via docrails. Also, CHANGELOGs should never be edited in docrails. -If you have an idea for a new guide you can refer to the "contribution page":contribute.html for instructions on getting involved. - h3. Contributing to the Rails Code h4. Clone the Rails Repository diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb index 4ef569013c..4c979888b7 100644 --- a/railties/guides/source/layout.html.erb +++ b/railties/guides/source/layout.html.erb @@ -91,7 +91,7 @@
-
  • Contribute
  • +
  • Contribute
  • Credits
  • -- cgit v1.2.3 From a06d17480ff533fbc375df219a4e70886fb4899b Mon Sep 17 00:00:00 2001 From: John Mileham Date: Tue, 23 Aug 2011 19:04:35 -0400 Subject: ActiveResource shouldn't rely on the presence of Content-Length --- activeresource/lib/active_resource/base.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index 693bd0592e..236dc565f3 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -1357,7 +1357,9 @@ module ActiveResource end def load_attributes_from_response(response) - if !response['Content-Length'].blank? && response['Content-Length'] != "0" && !response.body.nil? && response.body.strip.size > 0 + if (response_code_allows_body?(response.code) && + (response['Content-Length'].nil? || response['Content-Length'] != "0") && + !response.body.nil? && response.body.strip.size > 0) load(self.class.format.decode(response.body), true) @persisted = true end @@ -1381,6 +1383,12 @@ module ActiveResource end private + + # Determine whether the response is allowed to have a body per HTTP 1.1 spec section 4.4.1 + def response_code_allows_body?(c) + !((100..199).include?(c) || [204,304].include?(c)) + end + # Tries to find a resource for a given collection name; if it fails, then the resource is created def find_or_create_resource_for_collection(name) find_or_create_resource_for(ActiveSupport::Inflector.singularize(name.to_s)) -- cgit v1.2.3 From 4bcacc80667a548664b5ca09d85074c6c383748e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 11 Sep 2011 17:05:16 -0700 Subject: Merge pull request #2936 from joelmoss/migration_status db:migrate:status not looking at all migration paths --- activerecord/lib/active_record/railties/databases.rake | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 13c41350fb..b3316fd1a2 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -203,11 +203,13 @@ db_namespace = namespace :db do end db_list = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}") file_list = [] - Dir.foreach(File.join(Rails.root, 'db', 'migrate')) do |file| - # only files matching "20091231235959_some_name.rb" pattern - if match_data = /^(\d{14})_(.+)\.rb$/.match(file) - status = db_list.delete(match_data[1]) ? 'up' : 'down' - file_list << [status, match_data[1], match_data[2].humanize] + ActiveRecord::Migrator.migrations_paths.each do |path| + Dir.foreach(path) do |file| + # only files matching "20091231235959_some_name.rb" pattern + if match_data = /^(\d{14})_(.+)\.rb$/.match(file) + status = db_list.delete(match_data[1]) ? 'up' : 'down' + file_list << [status, match_data[1], match_data[2].humanize] + end end end db_list.map! do |version| -- cgit v1.2.3 From 6e782f8944122e99091b38b07dcc777f02b1836c Mon Sep 17 00:00:00 2001 From: Alan Zeino Date: Mon, 12 Sep 2011 11:12:09 +1000 Subject: Slight change to reflect current 'destroy' code generated by scaffold in 3.1 release. --- railties/guides/source/getting_started.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 1587b20c18..219fa5afde 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1083,8 +1083,8 @@ def destroy @post.destroy respond_to do |format| - format.html { redirect_to(posts_url) } - format.json { render :json => {}, :status => :ok } + format.html { redirect_to posts_url } + format.json { head :ok } end end -- cgit v1.2.3 From d7154d483269fc25d771d5b8b7b8a2c889e4b3f5 Mon Sep 17 00:00:00 2001 From: James Gifford Date: Mon, 12 Sep 2011 10:30:45 -0400 Subject: Added getting_started code, updated guide with link to rails github repo and path to code --- railties/guides/code/getting_started/Gemfile | 32 +++ railties/guides/code/getting_started/README | 261 +++++++++++++++++++++ railties/guides/code/getting_started/Rakefile | 7 + .../getting_started/app/assets/images/rails.png | Bin 0 -> 6646 bytes .../app/assets/javascripts/application.js | 9 + .../app/assets/javascripts/comments.js.coffee | 3 + .../app/assets/javascripts/home.js.coffee | 3 + .../app/assets/javascripts/posts.js.coffee | 3 + .../app/assets/stylesheets/application.css | 7 + .../app/assets/stylesheets/comments.css.scss | 3 + .../app/assets/stylesheets/home.css.scss | 3 + .../app/assets/stylesheets/posts.css.scss | 3 + .../app/assets/stylesheets/scaffolds.css.scss | 56 +++++ .../app/controllers/application_controller.rb | 3 + .../app/controllers/comments_controller.rb | 16 ++ .../app/controllers/home_controller.rb | 5 + .../app/controllers/posts_controller.rb | 84 +++++++ .../app/helpers/application_helper.rb | 2 + .../getting_started/app/helpers/comments_helper.rb | 2 + .../getting_started/app/helpers/home_helper.rb | 2 + .../getting_started/app/helpers/posts_helper.rb | 5 + .../code/getting_started/app/mailers/.gitkeep | 0 .../code/getting_started/app/models/.gitkeep | 0 .../code/getting_started/app/models/comment.rb | 3 + .../guides/code/getting_started/app/models/post.rb | 11 + .../guides/code/getting_started/app/models/tag.rb | 3 + .../app/views/comments/_comment.html.erb | 15 ++ .../app/views/comments/_form.html.erb | 13 + .../getting_started/app/views/home/index.html.erb | 2 + .../getting_started/app/views/home/index.html.erb~ | 2 + .../app/views/layouts/application.html.erb | 14 ++ .../getting_started/app/views/posts/_form.html.erb | 32 +++ .../getting_started/app/views/posts/edit.html.erb | 6 + .../getting_started/app/views/posts/index.html.erb | 27 +++ .../getting_started/app/views/posts/new.html.erb | 5 + .../getting_started/app/views/posts/show.html.erb | 31 +++ .../getting_started/app/views/tags/_form.html.erb | 12 + railties/guides/code/getting_started/config.ru | 4 + .../code/getting_started/config/application.rb | 48 ++++ .../guides/code/getting_started/config/boot.rb | 6 + .../code/getting_started/config/database.yml | 25 ++ .../code/getting_started/config/environment.rb | 5 + .../config/environments/development.rb | 30 +++ .../config/environments/production.rb | 60 +++++ .../getting_started/config/environments/test.rb | 42 ++++ .../config/initializers/backtrace_silencers.rb | 7 + .../config/initializers/inflections.rb | 10 + .../config/initializers/mime_types.rb | 5 + .../config/initializers/secret_token.rb | 7 + .../config/initializers/session_store.rb | 8 + .../config/initializers/wrap_parameters.rb | 14 ++ .../code/getting_started/config/locales/en.yml | 5 + .../guides/code/getting_started/config/routes.rb | 64 +++++ .../guides/code/getting_started/config/routes.rb~ | 60 +++++ .../db/migrate/20110901012504_create_posts.rb | 11 + .../db/migrate/20110901012815_create_comments.rb | 12 + .../db/migrate/20110901013701_create_tags.rb | 11 + railties/guides/code/getting_started/db/schema.rb | 43 ++++ railties/guides/code/getting_started/db/seeds.rb | 7 + .../guides/code/getting_started/doc/README_FOR_APP | 2 + .../code/getting_started/lib/assets/.gitkeep | 0 .../guides/code/getting_started/lib/tasks/.gitkeep | 0 .../guides/code/getting_started/public/404.html | 26 ++ .../guides/code/getting_started/public/422.html | 26 ++ .../guides/code/getting_started/public/500.html | 26 ++ .../guides/code/getting_started/public/favicon.ico | 0 .../guides/code/getting_started/public/robots.txt | 5 + railties/guides/code/getting_started/script/rails | 6 + .../code/getting_started/test/fixtures/.gitkeep | 0 .../getting_started/test/fixtures/comments.yml | 11 + .../code/getting_started/test/fixtures/posts.yml | 11 + .../code/getting_started/test/fixtures/tags.yml | 9 + .../code/getting_started/test/functional/.gitkeep | 0 .../test/functional/comments_controller_test.rb | 7 + .../test/functional/home_controller_test.rb | 9 + .../test/functional/posts_controller_test.rb | 49 ++++ .../code/getting_started/test/integration/.gitkeep | 0 .../test/performance/browsing_test.rb | 12 + .../code/getting_started/test/test_helper.rb | 13 + .../guides/code/getting_started/test/unit/.gitkeep | 0 .../code/getting_started/test/unit/comment_test.rb | 7 + .../test/unit/helpers/comments_helper_test.rb | 4 + .../test/unit/helpers/home_helper_test.rb | 4 + .../test/unit/helpers/posts_helper_test.rb | 4 + .../code/getting_started/test/unit/post_test.rb | 7 + .../code/getting_started/test/unit/tag_test.rb | 7 + .../vendor/assets/stylesheets/.gitkeep | 0 .../code/getting_started/vendor/plugins/.gitkeep | 0 railties/guides/source/getting_started.textile | 3 + 89 files changed, 1417 insertions(+) create mode 100644 railties/guides/code/getting_started/Gemfile create mode 100644 railties/guides/code/getting_started/README create mode 100644 railties/guides/code/getting_started/Rakefile create mode 100644 railties/guides/code/getting_started/app/assets/images/rails.png create mode 100644 railties/guides/code/getting_started/app/assets/javascripts/application.js create mode 100644 railties/guides/code/getting_started/app/assets/javascripts/comments.js.coffee create mode 100644 railties/guides/code/getting_started/app/assets/javascripts/home.js.coffee create mode 100644 railties/guides/code/getting_started/app/assets/javascripts/posts.js.coffee create mode 100644 railties/guides/code/getting_started/app/assets/stylesheets/application.css create mode 100644 railties/guides/code/getting_started/app/assets/stylesheets/comments.css.scss create mode 100644 railties/guides/code/getting_started/app/assets/stylesheets/home.css.scss create mode 100644 railties/guides/code/getting_started/app/assets/stylesheets/posts.css.scss create mode 100644 railties/guides/code/getting_started/app/assets/stylesheets/scaffolds.css.scss create mode 100644 railties/guides/code/getting_started/app/controllers/application_controller.rb create mode 100644 railties/guides/code/getting_started/app/controllers/comments_controller.rb create mode 100644 railties/guides/code/getting_started/app/controllers/home_controller.rb create mode 100644 railties/guides/code/getting_started/app/controllers/posts_controller.rb create mode 100644 railties/guides/code/getting_started/app/helpers/application_helper.rb create mode 100644 railties/guides/code/getting_started/app/helpers/comments_helper.rb create mode 100644 railties/guides/code/getting_started/app/helpers/home_helper.rb create mode 100644 railties/guides/code/getting_started/app/helpers/posts_helper.rb create mode 100644 railties/guides/code/getting_started/app/mailers/.gitkeep create mode 100644 railties/guides/code/getting_started/app/models/.gitkeep create mode 100644 railties/guides/code/getting_started/app/models/comment.rb create mode 100644 railties/guides/code/getting_started/app/models/post.rb create mode 100644 railties/guides/code/getting_started/app/models/tag.rb create mode 100644 railties/guides/code/getting_started/app/views/comments/_comment.html.erb create mode 100644 railties/guides/code/getting_started/app/views/comments/_form.html.erb create mode 100644 railties/guides/code/getting_started/app/views/home/index.html.erb create mode 100644 railties/guides/code/getting_started/app/views/home/index.html.erb~ create mode 100644 railties/guides/code/getting_started/app/views/layouts/application.html.erb create mode 100644 railties/guides/code/getting_started/app/views/posts/_form.html.erb create mode 100644 railties/guides/code/getting_started/app/views/posts/edit.html.erb create mode 100644 railties/guides/code/getting_started/app/views/posts/index.html.erb create mode 100644 railties/guides/code/getting_started/app/views/posts/new.html.erb create mode 100644 railties/guides/code/getting_started/app/views/posts/show.html.erb create mode 100644 railties/guides/code/getting_started/app/views/tags/_form.html.erb create mode 100644 railties/guides/code/getting_started/config.ru create mode 100644 railties/guides/code/getting_started/config/application.rb create mode 100644 railties/guides/code/getting_started/config/boot.rb create mode 100644 railties/guides/code/getting_started/config/database.yml create mode 100644 railties/guides/code/getting_started/config/environment.rb create mode 100644 railties/guides/code/getting_started/config/environments/development.rb create mode 100644 railties/guides/code/getting_started/config/environments/production.rb create mode 100644 railties/guides/code/getting_started/config/environments/test.rb create mode 100644 railties/guides/code/getting_started/config/initializers/backtrace_silencers.rb create mode 100644 railties/guides/code/getting_started/config/initializers/inflections.rb create mode 100644 railties/guides/code/getting_started/config/initializers/mime_types.rb create mode 100644 railties/guides/code/getting_started/config/initializers/secret_token.rb create mode 100644 railties/guides/code/getting_started/config/initializers/session_store.rb create mode 100644 railties/guides/code/getting_started/config/initializers/wrap_parameters.rb create mode 100644 railties/guides/code/getting_started/config/locales/en.yml create mode 100644 railties/guides/code/getting_started/config/routes.rb create mode 100644 railties/guides/code/getting_started/config/routes.rb~ create mode 100644 railties/guides/code/getting_started/db/migrate/20110901012504_create_posts.rb create mode 100644 railties/guides/code/getting_started/db/migrate/20110901012815_create_comments.rb create mode 100644 railties/guides/code/getting_started/db/migrate/20110901013701_create_tags.rb create mode 100644 railties/guides/code/getting_started/db/schema.rb create mode 100644 railties/guides/code/getting_started/db/seeds.rb create mode 100644 railties/guides/code/getting_started/doc/README_FOR_APP create mode 100644 railties/guides/code/getting_started/lib/assets/.gitkeep create mode 100644 railties/guides/code/getting_started/lib/tasks/.gitkeep create mode 100644 railties/guides/code/getting_started/public/404.html create mode 100644 railties/guides/code/getting_started/public/422.html create mode 100644 railties/guides/code/getting_started/public/500.html create mode 100644 railties/guides/code/getting_started/public/favicon.ico create mode 100644 railties/guides/code/getting_started/public/robots.txt create mode 100755 railties/guides/code/getting_started/script/rails create mode 100644 railties/guides/code/getting_started/test/fixtures/.gitkeep create mode 100644 railties/guides/code/getting_started/test/fixtures/comments.yml create mode 100644 railties/guides/code/getting_started/test/fixtures/posts.yml create mode 100644 railties/guides/code/getting_started/test/fixtures/tags.yml create mode 100644 railties/guides/code/getting_started/test/functional/.gitkeep create mode 100644 railties/guides/code/getting_started/test/functional/comments_controller_test.rb create mode 100644 railties/guides/code/getting_started/test/functional/home_controller_test.rb create mode 100644 railties/guides/code/getting_started/test/functional/posts_controller_test.rb create mode 100644 railties/guides/code/getting_started/test/integration/.gitkeep create mode 100644 railties/guides/code/getting_started/test/performance/browsing_test.rb create mode 100644 railties/guides/code/getting_started/test/test_helper.rb create mode 100644 railties/guides/code/getting_started/test/unit/.gitkeep create mode 100644 railties/guides/code/getting_started/test/unit/comment_test.rb create mode 100644 railties/guides/code/getting_started/test/unit/helpers/comments_helper_test.rb create mode 100644 railties/guides/code/getting_started/test/unit/helpers/home_helper_test.rb create mode 100644 railties/guides/code/getting_started/test/unit/helpers/posts_helper_test.rb create mode 100644 railties/guides/code/getting_started/test/unit/post_test.rb create mode 100644 railties/guides/code/getting_started/test/unit/tag_test.rb create mode 100644 railties/guides/code/getting_started/vendor/assets/stylesheets/.gitkeep create mode 100644 railties/guides/code/getting_started/vendor/plugins/.gitkeep diff --git a/railties/guides/code/getting_started/Gemfile b/railties/guides/code/getting_started/Gemfile new file mode 100644 index 0000000000..51774934cd --- /dev/null +++ b/railties/guides/code/getting_started/Gemfile @@ -0,0 +1,32 @@ +source 'http://rubygems.org' + +gem 'rails', '3.1.0' +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'sqlite3' + + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', " ~> 3.1.0" + gem 'coffee-rails', "~> 3.1.0" + gem 'uglifier' +end + +gem 'jquery-rails' + +# Use unicorn as the web server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' + +# To use debugger +# gem 'ruby-debug19', :require => 'ruby-debug' + +group :test do + # Pretty printed test output + gem 'turn', :require => false +end diff --git a/railties/guides/code/getting_started/README b/railties/guides/code/getting_started/README new file mode 100644 index 0000000000..7c36f2356e --- /dev/null +++ b/railties/guides/code/getting_started/README @@ -0,0 +1,261 @@ +== Welcome to Rails + +Rails is a web-application framework that includes everything needed to create +database-backed web applications according to the Model-View-Control pattern. + +This pattern splits the view (also called the presentation) into "dumb" +templates that are primarily responsible for inserting pre-built data in between +HTML tags. The model contains the "smart" domain objects (such as Account, +Product, Person, Post) that holds all the business logic and knows how to +persist themselves to a database. The controller handles the incoming requests +(such as Save New Account, Update Product, Show Post) by manipulating the model +and directing data to the view. + +In Rails, the model is handled by what's called an object-relational mapping +layer entitled Active Record. This layer allows you to present the data from +database rows as objects and embellish these data objects with business logic +methods. You can read more about Active Record in +link:files/vendor/rails/activerecord/README.html. + +The controller and view are handled by the Action Pack, which handles both +layers by its two parts: Action View and Action Controller. These two layers +are bundled in a single package due to their heavy interdependence. This is +unlike the relationship between the Active Record and Action Pack that is much +more separate. Each of these packages can be used independently outside of +Rails. You can read more about Action Pack in +link:files/vendor/rails/actionpack/README.html. + + +== Getting Started + +1. At the command prompt, create a new Rails application: + rails new myapp (where myapp is the application name) + +2. Change directory to myapp and start the web server: + cd myapp; rails server (run with --help for options) + +3. Go to http://localhost:3000/ and you'll see: + "Welcome aboard: You're riding Ruby on Rails!" + +4. Follow the guidelines to start developing your application. You can find +the following resources handy: + +* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html +* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ + + +== Debugging Rails + +Sometimes your application goes wrong. Fortunately there are a lot of tools that +will help you debug it and get it back on the rails. + +First area to check is the application log files. Have "tail -f" commands +running on the server.log and development.log. Rails will automatically display +debugging and runtime information to these files. Debugging info will also be +shown in the browser on requests from 127.0.0.1. + +You can also log your own messages directly into the log file from your code +using the Ruby logger class from inside your controllers. Example: + + class WeblogController < ActionController::Base + def destroy + @weblog = Weblog.find(params[:id]) + @weblog.destroy + logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") + end + end + +The result will be a message in your log file along the lines of: + + Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! + +More information on how to use the logger is at http://www.ruby-doc.org/core/ + +Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are +several books available online as well: + +* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) +* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) + +These two books will bring you up to speed on the Ruby language and also on +programming in general. + + +== Debugger + +Debugger support is available through the debugger command when you start your +Mongrel or WEBrick server with --debugger. This means that you can break out of +execution at any point in the code, investigate and change the model, and then, +resume execution! You need to install ruby-debug to run the server in debugging +mode. With gems, use sudo gem install ruby-debug. Example: + + class WeblogController < ActionController::Base + def index + @posts = Post.all + debugger + end + end + +So the controller will accept the action, run the first line, then present you +with a IRB prompt in the server window. Here you can do things like: + + >> @posts.inspect + => "[#nil, "body"=>nil, "id"=>"1"}>, + #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" + +...and even better, you can examine how your runtime objects actually work: + + >> f = @posts.first + => #nil, "body"=>nil, "id"=>"1"}> + >> f. + Display all 152 possibilities? (y or n) + +Finally, when you're ready to resume execution, you can enter "cont". + + +== Console + +The console is a Ruby shell, which allows you to interact with your +application's domain model. Here you'll have all parts of the application +configured, just like it is when the application is running. You can inspect +domain models, change values, and save to the database. Starting the script +without arguments will launch it in the development environment. + +To start the console, run rails console from the application +directory. + +Options: + +* Passing the -s, --sandbox argument will rollback any modifications + made to the database. +* Passing an environment name as an argument will load the corresponding + environment. Example: rails console production. + +To reload your controllers and models after launching the console run +reload! + +More information about irb can be found at: +link:http://www.rubycentral.org/pickaxe/irb.html + + +== dbconsole + +You can go to the command line of your database directly through rails +dbconsole. You would be connected to the database with the credentials +defined in database.yml. Starting the script without arguments will connect you +to the development database. Passing an argument will connect you to a different +database, like rails dbconsole production. Currently works for MySQL, +PostgreSQL and SQLite 3. + +== Description of Contents + +The default directory structure of a generated Ruby on Rails application: + + |-- app + | |-- assets + | |-- images + | |-- javascripts + | `-- stylesheets + | |-- controllers + | |-- helpers + | |-- mailers + | |-- models + | `-- views + | `-- layouts + |-- config + | |-- environments + | |-- initializers + | `-- locales + |-- db + |-- doc + |-- lib + | `-- tasks + |-- log + |-- public + |-- script + |-- test + | |-- fixtures + | |-- functional + | |-- integration + | |-- performance + | `-- unit + |-- tmp + | |-- cache + | |-- pids + | |-- sessions + | `-- sockets + `-- vendor + |-- assets + `-- stylesheets + `-- plugins + +app + Holds all the code that's specific to this particular application. + +app/assets + Contains subdirectories for images, stylesheets, and JavaScript files. + +app/controllers + Holds controllers that should be named like weblogs_controller.rb for + automated URL mapping. All controllers should descend from + ApplicationController which itself descends from ActionController::Base. + +app/models + Holds models that should be named like post.rb. Models descend from + ActiveRecord::Base by default. + +app/views + Holds the template files for the view that should be named like + weblogs/index.html.erb for the WeblogsController#index action. All views use + eRuby syntax by default. + +app/views/layouts + Holds the template files for layouts to be used with views. This models the + common header/footer method of wrapping views. In your views, define a layout + using the layout :default and create a file named default.html.erb. + Inside default.html.erb, call <% yield %> to render the view using this + layout. + +app/helpers + Holds view helpers that should be named like weblogs_helper.rb. These are + generated for you automatically when using generators for controllers. + Helpers can be used to wrap functionality for your views into methods. + +config + Configuration files for the Rails environment, the routing map, the database, + and other dependencies. + +db + Contains the database schema in schema.rb. db/migrate contains all the + sequence of Migrations for your schema. + +doc + This directory is where your application documentation will be stored when + generated using rake doc:app + +lib + Application specific libraries. Basically, any kind of custom code that + doesn't belong under controllers, models, or helpers. This directory is in + the load path. + +public + The directory available for the web server. Also contains the dispatchers and the + default HTML files. This should be set as the DOCUMENT_ROOT of your web + server. + +script + Helper scripts for automation and generation. + +test + Unit and functional tests along with fixtures. When using the rails generate + command, template test files will be generated for you and placed in this + directory. + +vendor + External libraries that the application depends on. Also includes the plugins + subdirectory. If the app has frozen rails, those gems also go here, under + vendor/rails/. This directory is in the load path. diff --git a/railties/guides/code/getting_started/Rakefile b/railties/guides/code/getting_started/Rakefile new file mode 100644 index 0000000000..e1d1ec8615 --- /dev/null +++ b/railties/guides/code/getting_started/Rakefile @@ -0,0 +1,7 @@ +#!/usr/bin/env rake +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Blog::Application.load_tasks diff --git a/railties/guides/code/getting_started/app/assets/images/rails.png b/railties/guides/code/getting_started/app/assets/images/rails.png new file mode 100644 index 0000000000..d5edc04e65 Binary files /dev/null and b/railties/guides/code/getting_started/app/assets/images/rails.png differ diff --git a/railties/guides/code/getting_started/app/assets/javascripts/application.js b/railties/guides/code/getting_started/app/assets/javascripts/application.js new file mode 100644 index 0000000000..37c7bfcdb5 --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/javascripts/application.js @@ -0,0 +1,9 @@ +// This is a manifest file that'll be compiled into including all the files listed below. +// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +// be included in the compiled file accessible from http://example.com/assets/application.js +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +//= require jquery +//= require jquery_ujs +//= require_tree . diff --git a/railties/guides/code/getting_started/app/assets/javascripts/comments.js.coffee b/railties/guides/code/getting_started/app/assets/javascripts/comments.js.coffee new file mode 100644 index 0000000000..761567942f --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/javascripts/comments.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/railties/guides/code/getting_started/app/assets/javascripts/home.js.coffee b/railties/guides/code/getting_started/app/assets/javascripts/home.js.coffee new file mode 100644 index 0000000000..761567942f --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/javascripts/home.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/railties/guides/code/getting_started/app/assets/javascripts/posts.js.coffee b/railties/guides/code/getting_started/app/assets/javascripts/posts.js.coffee new file mode 100644 index 0000000000..761567942f --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/javascripts/posts.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/railties/guides/code/getting_started/app/assets/stylesheets/application.css b/railties/guides/code/getting_started/app/assets/stylesheets/application.css new file mode 100644 index 0000000000..fc25b5723f --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/stylesheets/application.css @@ -0,0 +1,7 @@ +/* + * This is a manifest file that'll automatically include all the stylesheets available in this directory + * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at + * the top of the compiled file, but it's generally better to create a new file per style scope. + *= require_self + *= require_tree . +*/ \ No newline at end of file diff --git a/railties/guides/code/getting_started/app/assets/stylesheets/comments.css.scss b/railties/guides/code/getting_started/app/assets/stylesheets/comments.css.scss new file mode 100644 index 0000000000..e730912783 --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/stylesheets/comments.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Comments controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/railties/guides/code/getting_started/app/assets/stylesheets/home.css.scss b/railties/guides/code/getting_started/app/assets/stylesheets/home.css.scss new file mode 100644 index 0000000000..f0ddc6846a --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/stylesheets/home.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the home controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/railties/guides/code/getting_started/app/assets/stylesheets/posts.css.scss b/railties/guides/code/getting_started/app/assets/stylesheets/posts.css.scss new file mode 100644 index 0000000000..ed4dfd10f2 --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/stylesheets/posts.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Posts controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/railties/guides/code/getting_started/app/assets/stylesheets/scaffolds.css.scss b/railties/guides/code/getting_started/app/assets/stylesheets/scaffolds.css.scss new file mode 100644 index 0000000000..05188f08ed --- /dev/null +++ b/railties/guides/code/getting_started/app/assets/stylesheets/scaffolds.css.scss @@ -0,0 +1,56 @@ +body { + background-color: #fff; + color: #333; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; } + +p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; } + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; } + +a { + color: #000; + &:visited { + color: #666; } + &:hover { + color: #fff; + background-color: #000; } } + +div { + &.field, &.actions { + margin-bottom: 10px; } } + +#notice { + color: green; } + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; } + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; + h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; } + ul li { + font-size: 12px; + list-style: square; } } diff --git a/railties/guides/code/getting_started/app/controllers/application_controller.rb b/railties/guides/code/getting_started/app/controllers/application_controller.rb new file mode 100644 index 0000000000..e8065d9505 --- /dev/null +++ b/railties/guides/code/getting_started/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery +end diff --git a/railties/guides/code/getting_started/app/controllers/comments_controller.rb b/railties/guides/code/getting_started/app/controllers/comments_controller.rb new file mode 100644 index 0000000000..7447fd078b --- /dev/null +++ b/railties/guides/code/getting_started/app/controllers/comments_controller.rb @@ -0,0 +1,16 @@ +class CommentsController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => "secret", :only => :destroy + def create + @post = Post.find(params[:post_id]) + @comment = @post.comments.create(params[:comment]) + redirect_to post_path(@post) + end + + def destroy + @post = Post.find(params[:post_id]) + @comment = @post.comments.find(params[:id]) + @comment.destroy + redirect_to post_path(@post) + end + +end diff --git a/railties/guides/code/getting_started/app/controllers/home_controller.rb b/railties/guides/code/getting_started/app/controllers/home_controller.rb new file mode 100644 index 0000000000..6cc31c1ca3 --- /dev/null +++ b/railties/guides/code/getting_started/app/controllers/home_controller.rb @@ -0,0 +1,5 @@ +class HomeController < ApplicationController + def index + end + +end diff --git a/railties/guides/code/getting_started/app/controllers/posts_controller.rb b/railties/guides/code/getting_started/app/controllers/posts_controller.rb new file mode 100644 index 0000000000..7e903c984c --- /dev/null +++ b/railties/guides/code/getting_started/app/controllers/posts_controller.rb @@ -0,0 +1,84 @@ +class PostsController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index + # GET /posts + # GET /posts.json + def index + @posts = Post.all + + respond_to do |format| + format.html # index.html.erb + format.json { render json: @posts } + end + end + + # GET /posts/1 + # GET /posts/1.json + def show + @post = Post.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @post } + end + end + + # GET /posts/new + # GET /posts/new.json + def new + @post = Post.new + + respond_to do |format| + format.html # new.html.erb + format.json { render json: @post } + end + end + + # GET /posts/1/edit + def edit + @post = Post.find(params[:id]) + end + + # POST /posts + # POST /posts.json + def create + @post = Post.new(params[:post]) + + respond_to do |format| + if @post.save + format.html { redirect_to @post, notice: 'Post was successfully created.' } + format.json { render json: @post, status: :created, location: @post } + else + format.html { render action: "new" } + format.json { render json: @post.errors, status: :unprocessable_entity } + end + end + end + + # PUT /posts/1 + # PUT /posts/1.json + def update + @post = Post.find(params[:id]) + + respond_to do |format| + if @post.update_attributes(params[:post]) + format.html { redirect_to @post, notice: 'Post was successfully updated.' } + format.json { head :ok } + else + format.html { render action: "edit" } + format.json { render json: @post.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /posts/1 + # DELETE /posts/1.json + def destroy + @post = Post.find(params[:id]) + @post.destroy + + respond_to do |format| + format.html { redirect_to posts_url } + format.json { head :ok } + end + end +end diff --git a/railties/guides/code/getting_started/app/helpers/application_helper.rb b/railties/guides/code/getting_started/app/helpers/application_helper.rb new file mode 100644 index 0000000000..de6be7945c --- /dev/null +++ b/railties/guides/code/getting_started/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/railties/guides/code/getting_started/app/helpers/comments_helper.rb b/railties/guides/code/getting_started/app/helpers/comments_helper.rb new file mode 100644 index 0000000000..0ec9ca5f2d --- /dev/null +++ b/railties/guides/code/getting_started/app/helpers/comments_helper.rb @@ -0,0 +1,2 @@ +module CommentsHelper +end diff --git a/railties/guides/code/getting_started/app/helpers/home_helper.rb b/railties/guides/code/getting_started/app/helpers/home_helper.rb new file mode 100644 index 0000000000..23de56ac60 --- /dev/null +++ b/railties/guides/code/getting_started/app/helpers/home_helper.rb @@ -0,0 +1,2 @@ +module HomeHelper +end diff --git a/railties/guides/code/getting_started/app/helpers/posts_helper.rb b/railties/guides/code/getting_started/app/helpers/posts_helper.rb new file mode 100644 index 0000000000..b6e8e67894 --- /dev/null +++ b/railties/guides/code/getting_started/app/helpers/posts_helper.rb @@ -0,0 +1,5 @@ +module PostsHelper + def join_tags(post) + post.tags.map { |t| t.name }.join(", ") + end +end diff --git a/railties/guides/code/getting_started/app/mailers/.gitkeep b/railties/guides/code/getting_started/app/mailers/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/app/models/.gitkeep b/railties/guides/code/getting_started/app/models/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/app/models/comment.rb b/railties/guides/code/getting_started/app/models/comment.rb new file mode 100644 index 0000000000..4e76c5b5b0 --- /dev/null +++ b/railties/guides/code/getting_started/app/models/comment.rb @@ -0,0 +1,3 @@ +class Comment < ActiveRecord::Base + belongs_to :post +end diff --git a/railties/guides/code/getting_started/app/models/post.rb b/railties/guides/code/getting_started/app/models/post.rb new file mode 100644 index 0000000000..61c2b5ae44 --- /dev/null +++ b/railties/guides/code/getting_started/app/models/post.rb @@ -0,0 +1,11 @@ +class Post < ActiveRecord::Base + validates :name, :presence => true + validates :title, :presence => true, + :length => { :minimum => 5 } + + has_many :comments, :dependent => :destroy + has_many :tags + + accepts_nested_attributes_for :tags, :allow_destroy => :true, + :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } } +end diff --git a/railties/guides/code/getting_started/app/models/tag.rb b/railties/guides/code/getting_started/app/models/tag.rb new file mode 100644 index 0000000000..30992e8ba9 --- /dev/null +++ b/railties/guides/code/getting_started/app/models/tag.rb @@ -0,0 +1,3 @@ +class Tag < ActiveRecord::Base + belongs_to :post +end diff --git a/railties/guides/code/getting_started/app/views/comments/_comment.html.erb b/railties/guides/code/getting_started/app/views/comments/_comment.html.erb new file mode 100644 index 0000000000..4c3fbf26cd --- /dev/null +++ b/railties/guides/code/getting_started/app/views/comments/_comment.html.erb @@ -0,0 +1,15 @@ +

    + Commenter: + <%= comment.commenter %> +

    + +

    + Comment: + <%= comment.body %> +

    + +

    + <%= link_to 'Destroy Comment', [comment.post, comment], + :confirm => 'Are you sure?', + :method => :delete %> +

    diff --git a/railties/guides/code/getting_started/app/views/comments/_form.html.erb b/railties/guides/code/getting_started/app/views/comments/_form.html.erb new file mode 100644 index 0000000000..d15bdd6b59 --- /dev/null +++ b/railties/guides/code/getting_started/app/views/comments/_form.html.erb @@ -0,0 +1,13 @@ +<%= form_for([@post, @post.comments.build]) do |f| %> +
    + <%= f.label :commenter %>
    + <%= f.text_field :commenter %> +
    +
    + <%= f.label :body %>
    + <%= f.text_area :body %> +
    +
    + <%= f.submit %> +
    +<% end %> diff --git a/railties/guides/code/getting_started/app/views/home/index.html.erb b/railties/guides/code/getting_started/app/views/home/index.html.erb new file mode 100644 index 0000000000..bb4f3dcd1f --- /dev/null +++ b/railties/guides/code/getting_started/app/views/home/index.html.erb @@ -0,0 +1,2 @@ +

    Hello, Rails!

    +<%= link_to "My Blog", posts_path %> diff --git a/railties/guides/code/getting_started/app/views/home/index.html.erb~ b/railties/guides/code/getting_started/app/views/home/index.html.erb~ new file mode 100644 index 0000000000..2085730c72 --- /dev/null +++ b/railties/guides/code/getting_started/app/views/home/index.html.erb~ @@ -0,0 +1,2 @@ +

    Home#index

    +

    Find me in app/views/home/index.html.erb

    diff --git a/railties/guides/code/getting_started/app/views/layouts/application.html.erb b/railties/guides/code/getting_started/app/views/layouts/application.html.erb new file mode 100644 index 0000000000..1e1e4b9a99 --- /dev/null +++ b/railties/guides/code/getting_started/app/views/layouts/application.html.erb @@ -0,0 +1,14 @@ + + + + Blog + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application" %> + <%= csrf_meta_tags %> + + + +<%= yield %> + + + diff --git a/railties/guides/code/getting_started/app/views/posts/_form.html.erb b/railties/guides/code/getting_started/app/views/posts/_form.html.erb new file mode 100644 index 0000000000..e27da7f413 --- /dev/null +++ b/railties/guides/code/getting_started/app/views/posts/_form.html.erb @@ -0,0 +1,32 @@ +<% @post.tags.build %> +<%= form_for(@post) do |post_form| %> + <% if @post.errors.any? %> +
    +

    <%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:

    +
      + <% @post.errors.full_messages.each do |msg| %> +
    • <%= msg %>
    • + <% end %> +
    +
    + <% end %> + +
    + <%= post_form.label :name %>
    + <%= post_form.text_field :name %> +
    +
    + <%= post_form.label :title %>
    + <%= post_form.text_field :title %> +
    +
    + <%= post_form.label :content %>
    + <%= post_form.text_area :content %> +
    +

    Tags

    + <%= render :partial => 'tags/form', + :locals => {:form => post_form} %> +
    + <%= post_form.submit %> +
    +<% end %> diff --git a/railties/guides/code/getting_started/app/views/posts/edit.html.erb b/railties/guides/code/getting_started/app/views/posts/edit.html.erb new file mode 100644 index 0000000000..720580236b --- /dev/null +++ b/railties/guides/code/getting_started/app/views/posts/edit.html.erb @@ -0,0 +1,6 @@ +

    Editing post

    + +<%= render 'form' %> + +<%= link_to 'Show', @post %> | +<%= link_to 'Back', posts_path %> diff --git a/railties/guides/code/getting_started/app/views/posts/index.html.erb b/railties/guides/code/getting_started/app/views/posts/index.html.erb new file mode 100644 index 0000000000..45dee1b25f --- /dev/null +++ b/railties/guides/code/getting_started/app/views/posts/index.html.erb @@ -0,0 +1,27 @@ +

    Listing posts

    + + + + + + + + + + + +<% @posts.each do |post| %> + + + + + + + + +<% end %> +
    NameTitleContent
    <%= post.name %><%= post.title %><%= post.content %><%= link_to 'Show', post %><%= link_to 'Edit', edit_post_path(post) %><%= link_to 'Destroy', post, confirm: 'Are you sure?', method: :delete %>
    + +
    + +<%= link_to 'New Post', new_post_path %> diff --git a/railties/guides/code/getting_started/app/views/posts/new.html.erb b/railties/guides/code/getting_started/app/views/posts/new.html.erb new file mode 100644 index 0000000000..36ad7421f9 --- /dev/null +++ b/railties/guides/code/getting_started/app/views/posts/new.html.erb @@ -0,0 +1,5 @@ +

    New post

    + +<%= render 'form' %> + +<%= link_to 'Back', posts_path %> diff --git a/railties/guides/code/getting_started/app/views/posts/show.html.erb b/railties/guides/code/getting_started/app/views/posts/show.html.erb new file mode 100644 index 0000000000..da78a9527b --- /dev/null +++ b/railties/guides/code/getting_started/app/views/posts/show.html.erb @@ -0,0 +1,31 @@ +

    <%= notice %>

    + +

    + Name: + <%= @post.name %> +

    + +

    + Title: + <%= @post.title %> +

    + +

    + Content: + <%= @post.content %> +

    + +

    + Tags: + <%= join_tags(@post) %> +

    + +

    Comments

    +<%= render @post.comments %> + +

    Add a comment:

    +<%= render "comments/form" %> + + +<%= link_to 'Edit Post', edit_post_path(@post) %> | +<%= link_to 'Back to Posts', posts_path %> | diff --git a/railties/guides/code/getting_started/app/views/tags/_form.html.erb b/railties/guides/code/getting_started/app/views/tags/_form.html.erb new file mode 100644 index 0000000000..7e424b0e20 --- /dev/null +++ b/railties/guides/code/getting_started/app/views/tags/_form.html.erb @@ -0,0 +1,12 @@ +<%= form.fields_for :tags do |tag_form| %> +
    + <%= tag_form.label :name, 'Tag:' %> + <%= tag_form.text_field :name %> +
    + <% unless tag_form.object.nil? || tag_form.object.new_record? %> +
    + <%= tag_form.label :_destroy, 'Remove:' %> + <%= tag_form.check_box :_destroy %> +
    + <% end %> +<% end %> diff --git a/railties/guides/code/getting_started/config.ru b/railties/guides/code/getting_started/config.ru new file mode 100644 index 0000000000..ddf869e921 --- /dev/null +++ b/railties/guides/code/getting_started/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Blog::Application diff --git a/railties/guides/code/getting_started/config/application.rb b/railties/guides/code/getting_started/config/application.rb new file mode 100644 index 0000000000..e914b5a80e --- /dev/null +++ b/railties/guides/code/getting_started/config/application.rb @@ -0,0 +1,48 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +if defined?(Bundler) + # If you precompile assets before deploying to production, use this line + Bundler.require *Rails.groups(:assets => %w(development test)) + # If you want your assets lazily compiled in production, use this line + # Bundler.require(:default, :assets, Rails.env) +end + +module Blog + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] + + # Enable the asset pipeline + config.assets.enabled = true + + # Version of your assets, change this if you want to expire all your assets + config.assets.version = '1.0' + end +end diff --git a/railties/guides/code/getting_started/config/boot.rb b/railties/guides/code/getting_started/config/boot.rb new file mode 100644 index 0000000000..4489e58688 --- /dev/null +++ b/railties/guides/code/getting_started/config/boot.rb @@ -0,0 +1,6 @@ +require 'rubygems' + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + +require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/railties/guides/code/getting_started/config/database.yml b/railties/guides/code/getting_started/config/database.yml new file mode 100644 index 0000000000..51a4dd459d --- /dev/null +++ b/railties/guides/code/getting_started/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +development: + adapter: sqlite3 + database: db/development.sqlite3 + pool: 5 + timeout: 5000 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + adapter: sqlite3 + database: db/test.sqlite3 + pool: 5 + timeout: 5000 + +production: + adapter: sqlite3 + database: db/production.sqlite3 + pool: 5 + timeout: 5000 diff --git a/railties/guides/code/getting_started/config/environment.rb b/railties/guides/code/getting_started/config/environment.rb new file mode 100644 index 0000000000..8f728b7ce7 --- /dev/null +++ b/railties/guides/code/getting_started/config/environment.rb @@ -0,0 +1,5 @@ +# Load the rails application +require File.expand_path('../application', __FILE__) + +# Initialize the rails application +Blog::Application.initialize! diff --git a/railties/guides/code/getting_started/config/environments/development.rb b/railties/guides/code/getting_started/config/environments/development.rb new file mode 100644 index 0000000000..89932bf19b --- /dev/null +++ b/railties/guides/code/getting_started/config/environments/development.rb @@ -0,0 +1,30 @@ +Blog::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log + + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin + + # Do not compress assets + config.assets.compress = false + + # Expands the lines which load the assets + config.assets.debug = true +end diff --git a/railties/guides/code/getting_started/config/environments/production.rb b/railties/guides/code/getting_started/config/environments/production.rb new file mode 100644 index 0000000000..6ab63d30a6 --- /dev/null +++ b/railties/guides/code/getting_started/config/environments/production.rb @@ -0,0 +1,60 @@ +Blog::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Disable Rails's static asset server (Apache or nginx will already do this) + config.serve_static_assets = false + + # Compress JavaScripts and CSS + config.assets.compress = true + + # Don't fallback to assets pipeline if a precompiled asset is missed + config.assets.compile = false + + # Generate digests for assets URLs + config.assets.digest = true + + # Defaults to Rails.root.join("public/assets") + # config.assets.manifest = YOUR_PATH + + # Specifies the header that your server uses for sending files + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) + # config.assets.precompile += %w( search.js ) + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify +end diff --git a/railties/guides/code/getting_started/config/environments/test.rb b/railties/guides/code/getting_started/config/environments/test.rb new file mode 100644 index 0000000000..833241ace3 --- /dev/null +++ b/railties/guides/code/getting_started/config/environments/test.rb @@ -0,0 +1,42 @@ +Blog::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Configure static asset server for tests with Cache-Control for performance + config.serve_static_assets = true + config.static_cache_control = "public, max-age=3600" + + # Log error messages when you accidentally call methods on nil + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr + + # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets + config.assets.allow_debugging = true +end diff --git a/railties/guides/code/getting_started/config/initializers/backtrace_silencers.rb b/railties/guides/code/getting_started/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000000..59385cdf37 --- /dev/null +++ b/railties/guides/code/getting_started/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/railties/guides/code/getting_started/config/initializers/inflections.rb b/railties/guides/code/getting_started/config/initializers/inflections.rb new file mode 100644 index 0000000000..9e8b0131f8 --- /dev/null +++ b/railties/guides/code/getting_started/config/initializers/inflections.rb @@ -0,0 +1,10 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format +# (all these examples are active by default): +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end diff --git a/railties/guides/code/getting_started/config/initializers/mime_types.rb b/railties/guides/code/getting_started/config/initializers/mime_types.rb new file mode 100644 index 0000000000..72aca7e441 --- /dev/null +++ b/railties/guides/code/getting_started/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf +# Mime::Type.register_alias "text/html", :iphone diff --git a/railties/guides/code/getting_started/config/initializers/secret_token.rb b/railties/guides/code/getting_started/config/initializers/secret_token.rb new file mode 100644 index 0000000000..b0c8ee23c1 --- /dev/null +++ b/railties/guides/code/getting_started/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +Blog::Application.config.secret_token = '685a9bf865b728c6549a191c90851c1b5ec41ecb60b9e94ad79dd3f824749798aa7b5e94431901960bee57809db0947b481570f7f13376b7ca190fa28099c459' diff --git a/railties/guides/code/getting_started/config/initializers/session_store.rb b/railties/guides/code/getting_started/config/initializers/session_store.rb new file mode 100644 index 0000000000..1a67af58b5 --- /dev/null +++ b/railties/guides/code/getting_started/config/initializers/session_store.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +Blog::Application.config.session_store :cookie_store, key: '_blog_session' + +# Use the database for sessions instead of the cookie-based default, +# which shouldn't be used to store highly confidential information +# (create the session table with "rails generate session_migration") +# Blog::Application.config.session_store :active_record_store diff --git a/railties/guides/code/getting_started/config/initializers/wrap_parameters.rb b/railties/guides/code/getting_started/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000000..999df20181 --- /dev/null +++ b/railties/guides/code/getting_started/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# Disable root element in JSON by default. +ActiveSupport.on_load(:active_record) do + self.include_root_in_json = false +end diff --git a/railties/guides/code/getting_started/config/locales/en.yml b/railties/guides/code/getting_started/config/locales/en.yml new file mode 100644 index 0000000000..179c14ca52 --- /dev/null +++ b/railties/guides/code/getting_started/config/locales/en.yml @@ -0,0 +1,5 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + hello: "Hello world" diff --git a/railties/guides/code/getting_started/config/routes.rb b/railties/guides/code/getting_started/config/routes.rb new file mode 100644 index 0000000000..31f0d210db --- /dev/null +++ b/railties/guides/code/getting_started/config/routes.rb @@ -0,0 +1,64 @@ +Blog::Application.routes.draw do + resources :posts do + resources :comments + end + + get "home/index" + + # The priority is based upon order of creation: + # first created -> highest priority. + + # Sample of regular route: + # match 'products/:id' => 'catalog#view' + # Keep in mind you can assign values other than :controller and :action + + # Sample of named route: + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase + # This route can be invoked with purchase_url(:id => product.id) + + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end + + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + root :to => "home#index" + + # See how all your routes lay out with "rake routes" + + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))' +end diff --git a/railties/guides/code/getting_started/config/routes.rb~ b/railties/guides/code/getting_started/config/routes.rb~ new file mode 100644 index 0000000000..3d9628b55e --- /dev/null +++ b/railties/guides/code/getting_started/config/routes.rb~ @@ -0,0 +1,60 @@ +Blog::Application.routes.draw do + get "home/index" + + # The priority is based upon order of creation: + # first created -> highest priority. + + # Sample of regular route: + # match 'products/:id' => 'catalog#view' + # Keep in mind you can assign values other than :controller and :action + + # Sample of named route: + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase + # This route can be invoked with purchase_url(:id => product.id) + + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end + + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => 'welcome#index' + + # See how all your routes lay out with "rake routes" + + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))' +end diff --git a/railties/guides/code/getting_started/db/migrate/20110901012504_create_posts.rb b/railties/guides/code/getting_started/db/migrate/20110901012504_create_posts.rb new file mode 100644 index 0000000000..d45a961523 --- /dev/null +++ b/railties/guides/code/getting_started/db/migrate/20110901012504_create_posts.rb @@ -0,0 +1,11 @@ +class CreatePosts < ActiveRecord::Migration + def change + create_table :posts do |t| + t.string :name + t.string :title + t.text :content + + t.timestamps + end + end +end diff --git a/railties/guides/code/getting_started/db/migrate/20110901012815_create_comments.rb b/railties/guides/code/getting_started/db/migrate/20110901012815_create_comments.rb new file mode 100644 index 0000000000..adda8078c1 --- /dev/null +++ b/railties/guides/code/getting_started/db/migrate/20110901012815_create_comments.rb @@ -0,0 +1,12 @@ +class CreateComments < ActiveRecord::Migration + def change + create_table :comments do |t| + t.string :commenter + t.text :body + t.references :post + + t.timestamps + end + add_index :comments, :post_id + end +end diff --git a/railties/guides/code/getting_started/db/migrate/20110901013701_create_tags.rb b/railties/guides/code/getting_started/db/migrate/20110901013701_create_tags.rb new file mode 100644 index 0000000000..cf95b1c3d0 --- /dev/null +++ b/railties/guides/code/getting_started/db/migrate/20110901013701_create_tags.rb @@ -0,0 +1,11 @@ +class CreateTags < ActiveRecord::Migration + def change + create_table :tags do |t| + t.string :name + t.references :post + + t.timestamps + end + add_index :tags, :post_id + end +end diff --git a/railties/guides/code/getting_started/db/schema.rb b/railties/guides/code/getting_started/db/schema.rb new file mode 100644 index 0000000000..9db4fbe4b6 --- /dev/null +++ b/railties/guides/code/getting_started/db/schema.rb @@ -0,0 +1,43 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 20110901013701) do + + create_table "comments", :force => true do |t| + t.string "commenter" + t.text "body" + t.integer "post_id" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "comments", ["post_id"], :name => "index_comments_on_post_id" + + create_table "posts", :force => true do |t| + t.string "name" + t.string "title" + t.text "content" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "tags", :force => true do |t| + t.string "name" + t.integer "post_id" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "tags", ["post_id"], :name => "index_tags_on_post_id" + +end diff --git a/railties/guides/code/getting_started/db/seeds.rb b/railties/guides/code/getting_started/db/seeds.rb new file mode 100644 index 0000000000..4edb1e857e --- /dev/null +++ b/railties/guides/code/getting_started/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) +# Mayor.create(name: 'Emanuel', city: cities.first) diff --git a/railties/guides/code/getting_started/doc/README_FOR_APP b/railties/guides/code/getting_started/doc/README_FOR_APP new file mode 100644 index 0000000000..fe41f5cc24 --- /dev/null +++ b/railties/guides/code/getting_started/doc/README_FOR_APP @@ -0,0 +1,2 @@ +Use this README file to introduce your application and point to useful places in the API for learning more. +Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. diff --git a/railties/guides/code/getting_started/lib/assets/.gitkeep b/railties/guides/code/getting_started/lib/assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/lib/tasks/.gitkeep b/railties/guides/code/getting_started/lib/tasks/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/public/404.html b/railties/guides/code/getting_started/public/404.html new file mode 100644 index 0000000000..9a48320a5f --- /dev/null +++ b/railties/guides/code/getting_started/public/404.html @@ -0,0 +1,26 @@ + + + + The page you were looking for doesn't exist (404) + + + + + +
    +

    The page you were looking for doesn't exist.

    +

    You may have mistyped the address or the page may have moved.

    +
    + + diff --git a/railties/guides/code/getting_started/public/422.html b/railties/guides/code/getting_started/public/422.html new file mode 100644 index 0000000000..83660ab187 --- /dev/null +++ b/railties/guides/code/getting_started/public/422.html @@ -0,0 +1,26 @@ + + + + The change you wanted was rejected (422) + + + + + +
    +

    The change you wanted was rejected.

    +

    Maybe you tried to change something you didn't have access to.

    +
    + + diff --git a/railties/guides/code/getting_started/public/500.html b/railties/guides/code/getting_started/public/500.html new file mode 100644 index 0000000000..b80307fc16 --- /dev/null +++ b/railties/guides/code/getting_started/public/500.html @@ -0,0 +1,26 @@ + + + + We're sorry, but something went wrong (500) + + + + + +
    +

    We're sorry, but something went wrong.

    +

    We've been notified about this issue and we'll take a look at it shortly.

    +
    + + diff --git a/railties/guides/code/getting_started/public/favicon.ico b/railties/guides/code/getting_started/public/favicon.ico new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/public/robots.txt b/railties/guides/code/getting_started/public/robots.txt new file mode 100644 index 0000000000..085187fa58 --- /dev/null +++ b/railties/guides/code/getting_started/public/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-Agent: * +# Disallow: / diff --git a/railties/guides/code/getting_started/script/rails b/railties/guides/code/getting_started/script/rails new file mode 100755 index 0000000000..f8da2cffd4 --- /dev/null +++ b/railties/guides/code/getting_started/script/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +APP_PATH = File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands' diff --git a/railties/guides/code/getting_started/test/fixtures/.gitkeep b/railties/guides/code/getting_started/test/fixtures/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/test/fixtures/comments.yml b/railties/guides/code/getting_started/test/fixtures/comments.yml new file mode 100644 index 0000000000..d33da386bf --- /dev/null +++ b/railties/guides/code/getting_started/test/fixtures/comments.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html + +one: + commenter: MyString + body: MyText + post: + +two: + commenter: MyString + body: MyText + post: diff --git a/railties/guides/code/getting_started/test/fixtures/posts.yml b/railties/guides/code/getting_started/test/fixtures/posts.yml new file mode 100644 index 0000000000..8b0f75a33d --- /dev/null +++ b/railties/guides/code/getting_started/test/fixtures/posts.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html + +one: + name: MyString + title: MyString + content: MyText + +two: + name: MyString + title: MyString + content: MyText diff --git a/railties/guides/code/getting_started/test/fixtures/tags.yml b/railties/guides/code/getting_started/test/fixtures/tags.yml new file mode 100644 index 0000000000..8485668908 --- /dev/null +++ b/railties/guides/code/getting_started/test/fixtures/tags.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html + +one: + name: MyString + post: + +two: + name: MyString + post: diff --git a/railties/guides/code/getting_started/test/functional/.gitkeep b/railties/guides/code/getting_started/test/functional/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/test/functional/comments_controller_test.rb b/railties/guides/code/getting_started/test/functional/comments_controller_test.rb new file mode 100644 index 0000000000..2ec71b4ec5 --- /dev/null +++ b/railties/guides/code/getting_started/test/functional/comments_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class CommentsControllerTest < ActionController::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/railties/guides/code/getting_started/test/functional/home_controller_test.rb b/railties/guides/code/getting_started/test/functional/home_controller_test.rb new file mode 100644 index 0000000000..0d9bb47c3e --- /dev/null +++ b/railties/guides/code/getting_started/test/functional/home_controller_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' + +class HomeControllerTest < ActionController::TestCase + test "should get index" do + get :index + assert_response :success + end + +end diff --git a/railties/guides/code/getting_started/test/functional/posts_controller_test.rb b/railties/guides/code/getting_started/test/functional/posts_controller_test.rb new file mode 100644 index 0000000000..b8f7b07820 --- /dev/null +++ b/railties/guides/code/getting_started/test/functional/posts_controller_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class PostsControllerTest < ActionController::TestCase + setup do + @post = posts(:one) + end + + test "should get index" do + get :index + assert_response :success + assert_not_nil assigns(:posts) + end + + test "should get new" do + get :new + assert_response :success + end + + test "should create post" do + assert_difference('Post.count') do + post :create, post: @post.attributes + end + + assert_redirected_to post_path(assigns(:post)) + end + + test "should show post" do + get :show, id: @post.to_param + assert_response :success + end + + test "should get edit" do + get :edit, id: @post.to_param + assert_response :success + end + + test "should update post" do + put :update, id: @post.to_param, post: @post.attributes + assert_redirected_to post_path(assigns(:post)) + end + + test "should destroy post" do + assert_difference('Post.count', -1) do + delete :destroy, id: @post.to_param + end + + assert_redirected_to posts_path + end +end diff --git a/railties/guides/code/getting_started/test/integration/.gitkeep b/railties/guides/code/getting_started/test/integration/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/test/performance/browsing_test.rb b/railties/guides/code/getting_started/test/performance/browsing_test.rb new file mode 100644 index 0000000000..3fea27b916 --- /dev/null +++ b/railties/guides/code/getting_started/test/performance/browsing_test.rb @@ -0,0 +1,12 @@ +require 'test_helper' +require 'rails/performance_test_help' + +class BrowsingTest < ActionDispatch::PerformanceTest + # Refer to the documentation for all available options + # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory] + # :output => 'tmp/performance', :formats => [:flat] } + + def test_homepage + get '/' + end +end diff --git a/railties/guides/code/getting_started/test/test_helper.rb b/railties/guides/code/getting_started/test/test_helper.rb new file mode 100644 index 0000000000..8bf1192ffe --- /dev/null +++ b/railties/guides/code/getting_started/test/test_helper.rb @@ -0,0 +1,13 @@ +ENV["RAILS_ENV"] = "test" +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. + # + # Note: You'll currently still have to declare fixtures explicitly in integration tests + # -- they do not yet inherit this setting + fixtures :all + + # Add more helper methods to be used by all tests here... +end diff --git a/railties/guides/code/getting_started/test/unit/.gitkeep b/railties/guides/code/getting_started/test/unit/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/test/unit/comment_test.rb b/railties/guides/code/getting_started/test/unit/comment_test.rb new file mode 100644 index 0000000000..b6d6131a96 --- /dev/null +++ b/railties/guides/code/getting_started/test/unit/comment_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class CommentTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/railties/guides/code/getting_started/test/unit/helpers/comments_helper_test.rb b/railties/guides/code/getting_started/test/unit/helpers/comments_helper_test.rb new file mode 100644 index 0000000000..2518c16bd5 --- /dev/null +++ b/railties/guides/code/getting_started/test/unit/helpers/comments_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class CommentsHelperTest < ActionView::TestCase +end diff --git a/railties/guides/code/getting_started/test/unit/helpers/home_helper_test.rb b/railties/guides/code/getting_started/test/unit/helpers/home_helper_test.rb new file mode 100644 index 0000000000..4740a18dac --- /dev/null +++ b/railties/guides/code/getting_started/test/unit/helpers/home_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class HomeHelperTest < ActionView::TestCase +end diff --git a/railties/guides/code/getting_started/test/unit/helpers/posts_helper_test.rb b/railties/guides/code/getting_started/test/unit/helpers/posts_helper_test.rb new file mode 100644 index 0000000000..48549c2ea1 --- /dev/null +++ b/railties/guides/code/getting_started/test/unit/helpers/posts_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class PostsHelperTest < ActionView::TestCase +end diff --git a/railties/guides/code/getting_started/test/unit/post_test.rb b/railties/guides/code/getting_started/test/unit/post_test.rb new file mode 100644 index 0000000000..6d9d463a71 --- /dev/null +++ b/railties/guides/code/getting_started/test/unit/post_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class PostTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/railties/guides/code/getting_started/test/unit/tag_test.rb b/railties/guides/code/getting_started/test/unit/tag_test.rb new file mode 100644 index 0000000000..b8498a117c --- /dev/null +++ b/railties/guides/code/getting_started/test/unit/tag_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class TagTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/railties/guides/code/getting_started/vendor/assets/stylesheets/.gitkeep b/railties/guides/code/getting_started/vendor/assets/stylesheets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/code/getting_started/vendor/plugins/.gitkeep b/railties/guides/code/getting_started/vendor/plugins/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 1587b20c18..e1bc56823a 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -41,6 +41,9 @@ internet for learning Ruby, including: * "Programming Ruby":http://www.ruby-doc.org/docs/ProgrammingRuby/ * "Why's (Poignant) Guide to Ruby":http://mislav.uniqpath.com/poignant-guide/ +Also, the example code for this guide is available in the rails github:https://github.com/rails/rails repository +in rails/railties/guides/code/getting_started. + h3. What is Rails? Rails is a web application development framework written in the Ruby language. -- cgit v1.2.3 From 11fa70dd0903a75f2a507dd609ea640e8ec99373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 12 Sep 2011 09:05:11 -0700 Subject: Just provide the executable for railtie. This should be fine since Rubygems now warns before overriding them. --- bin/rails | 7 ------- rails.gemspec | 2 +- railties/bin/rails | 7 ++++++- 3 files changed, 7 insertions(+), 9 deletions(-) delete mode 100755 bin/rails diff --git a/bin/rails b/bin/rails deleted file mode 100755 index f9725d78d0..0000000000 --- a/bin/rails +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env ruby - -if File.exists?(File.join(File.expand_path('../..', __FILE__), '.git')) - railties_path = File.expand_path('../../railties/lib', __FILE__) - $:.unshift(railties_path) -end -require "rails/cli" diff --git a/rails.gemspec b/rails.gemspec index bb3fe85c2b..3377b4e175 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |s| s.homepage = 'http://www.rubyonrails.org' s.bindir = 'bin' - s.executables = ['rails'] + s.executables = [] s.add_dependency('activesupport', version) s.add_dependency('actionpack', version) diff --git a/railties/bin/rails b/railties/bin/rails index a7d6938e0d..a1c4faaa73 100755 --- a/railties/bin/rails +++ b/railties/bin/rails @@ -1,2 +1,7 @@ #!/usr/bin/env ruby -require "rails/cli" \ No newline at end of file + +if File.exists?(File.join(File.expand_path('../../..', __FILE__), '.git')) + railties_path = File.expand_path('../../lib', __FILE__) + $:.unshift(railties_path) +end +require "rails/cli" -- cgit v1.2.3 From 3ce830272ee0516eb864a5765abba25d4b07cca4 Mon Sep 17 00:00:00 2001 From: kennyj Date: Tue, 13 Sep 2011 01:06:31 +0900 Subject: fix https://github.com/rails/rails/issues/2582 (with testcase) --- actionpack/lib/sprockets/assets.rake | 2 +- railties/test/application/rake_test.rb | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index a8128d9a82..2e415bf6cc 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -42,7 +42,7 @@ namespace :assets do end end - File.open("#{manifest_path}/manifest.yml", 'w') do |f| + File.open("#{manifest_path}/manifest.yml", 'wb') do |f| YAML.dump(manifest, f) end end diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 0e03c3dc2d..9b1b24fca1 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -1,3 +1,4 @@ +# coding:utf-8 require "isolation/abstract_unit" module ApplicationTests @@ -244,5 +245,20 @@ module ApplicationTests assert_match(/7 tests, 10 assertions, 0 failures, 0 errors/, content) end + + def test_assets_precompile_with_utf8_filename + add_to_config <<-RUBY + config.assets.precompile = [ /\.png$$/, /application.(css|js)$/ ] + RUBY + + Dir.chdir(app_path) do + `cp app/assets/images/rails.png app/assets/images/レイルズ.png` + `rake assets:precompile` + open("public/assets/manifest.yml") do |f| + assert_match(/レイルズ.png/, f.read) + end + end + end + end -end \ No newline at end of file +end -- cgit v1.2.3 From 21b4244d410bf5832b09f9b0bb06a12f8c886072 Mon Sep 17 00:00:00 2001 From: Semyon Perepelitsa Date: Mon, 12 Sep 2011 20:53:10 +0400 Subject: Fix a typo in date --- activesupport/lib/active_support/time_with_zone.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index ec2c717942..63279d0e6d 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -12,7 +12,7 @@ module ActiveSupport # # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00 - # Time.zone.parse('2007-02-01 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00 + # Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00 # Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00 # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00 # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00 -- cgit v1.2.3 From 70198fdb3614ef0299e848440df62d18b46a7f77 Mon Sep 17 00:00:00 2001 From: dharmatech Date: Mon, 12 Sep 2011 12:05:15 -0500 Subject: getting_started.textile: Fix typos in section "Rendering a Partial Form" --- railties/guides/source/getting_started.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 1587b20c18..ae9a689678 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1453,7 +1453,7 @@ comment to a local variable named the same as the partial, in this case h4. Rendering a Partial Form -Lets also move that new comment section out to it's own partial, again, you +Let's also move that new comment section out to its own partial. Again, you create a file +app/views/comments/_form.html.erb+ and in it you put: -- cgit v1.2.3 From e9db21743b15f2c6e8dcbd18f420784c4e8de88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 12 Sep 2011 10:53:20 -0700 Subject: Use the proper executable on tests. --- railties/test/isolation/abstract_unit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 685d1b154b..4a6bdb0320 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -282,7 +282,7 @@ Module.new do require_environment = "-r #{environment}" end - `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/bin/rails new #{tmp_path('app_template')}` + `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails new #{tmp_path('app_template')}` File.open("#{tmp_path}/app_template/config/boot.rb", 'w') do |f| if require_environment f.puts "Dir.chdir('#{File.dirname(environment)}') do" -- cgit v1.2.3 From c5118f29dee30d6c806c486698f3aa6ba8af919b Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Mon, 12 Sep 2011 23:24:14 +0530 Subject: change GH issue tracker url --- railties/guides/source/contributing_to_ruby_on_rails.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile index 968fa7a1f1..90eab150a1 100644 --- a/railties/guides/source/contributing_to_ruby_on_rails.textile +++ b/railties/guides/source/contributing_to_ruby_on_rails.textile @@ -261,7 +261,7 @@ You can help improve the Rails guides by making them more coherent, adding missi If you're confident about your changes, you can push them yourself directly via "docrails":https://github.com/lifo/docrails. docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but that happens after they are pushed. docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation. -If you are unsure of the documentation changes, you can create an issue in the "Rails":https://github.com/rails/rails repository on GitHub. +If you are unsure of the documentation changes, you can create an issue in the "Rails":https://github.com/rails/rails/issues issues tracker on GitHub. When working with documentation, please take into account the "API Documentation Guidelines":api_documentation_guidelines.html and the "Ruby on Rails Guides Guidelines":ruby_on_rails_guides_guidelines.html. -- cgit v1.2.3 From acc6252cb0250df8d5554fee94b0aa6dc87b32e7 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Mon, 12 Sep 2011 23:25:33 +0530 Subject: Delete contribute.textile now that its contents are merged to the contributing_to_ruby_on_rails guide --- railties/guides/source/contribute.textile | 70 ------------------------------- 1 file changed, 70 deletions(-) delete mode 100644 railties/guides/source/contribute.textile diff --git a/railties/guides/source/contribute.textile b/railties/guides/source/contribute.textile deleted file mode 100644 index f9bb80861c..0000000000 --- a/railties/guides/source/contribute.textile +++ /dev/null @@ -1,70 +0,0 @@ -h2. Contribute to the Rails Guides - -Rails Guides aim to improve the Rails documentation and to make the barrier to entry as low as possible. A reasonably experienced developer should be able to use the guides to come up to speed on Rails quickly. Our sponsors have contributed prizes for those who write an entire guide, but there are many other ways to contribute. - -endprologue. - -h3. How to Contribute? - -* We have an open commit policy: anyone is welcome to contribute and to review contributions. -* "docrails is hosted on GitHub":https://github.com/lifo/docrails and has public write access. -* Guides are written in Textile, and reside at +railties/guides/source+ in the docrails project. -* Follow the "Rails Guides Conventions":https://wiki.github.com/lifo/docrails/rails-guides-conventions. -* Assets are stored in the +railties/guides/assets+ directory. -* Sample format : "Active Record Associations":https://github.com/lifo/docrails/blob/3e56a3832415476fdd1cb963980d0ae390ac1ed3/railties/guides/source/association_basics.textile. -* Sample output : "Active Record Associations":association_basics.html. -* You can build the Guides during testing by running +bundle exec rake generate_guides+ in the +railties+ directory. -* You're encouraged to validate XHTML for the generated guides before committing your changes by running +bundle exec rake validate_guides+ in the +railties+ directory. -* Edge guides "can be consulted online":http://edgeguides.rubyonrails.org/. That website is generated periodically from docrails. - -h3. What to Contribute? - -* We need authors, editors, proofreaders, and translators. Adding a single paragraph of quality content to a guide is a good way to get started. -* The easiest way to start is by improving an existing guide: -** Improve the structure to make it more coherent. -** Add missing information. -** Correct any factual errors. -** Fix typos or improve style. -** Bring it up to date with the latest Edge Rails. -* We're also open to suggestions for entire new guides: -** Contact lifo or fxn to get your idea approved. See the Contact section below. -** If you're the main author on a significant guide, you're eligible for the prizes. - -h3. How is the process? - -* The preferred way to contribute is to commit to docrails directly. -* A new guide is only edited by its author until finished though. -* If you are writing a new guide freely commit to docrails partial work and ping lifo or fxn when done with a first draft. -* Guides reviewers will then provide feedback, some of it possibly in form of direct commits to agilize the process. -* Eventually the guide will be approved and added to the index. - -h3. Prizes - -For each completed guide, the lead contributor will receive all of the following prizes: - -* $200 from Caboose Rails Documentation Project. -* 1 year of GitHub Micro account worth $84. -* 1 year of RPM Basic (Production performance management) for up to 10 hosts worth 12 months x $40 per host x 10 hosts = $4800. And also, savings of $45 per host per month over list price to upgrade to advanced product. - -h3. Rules - -* Guides are licensed under a Creative Commons Attribution-Share Alike 3.0 License. -* If you're not sure whether a guide is actively being worked on, stop by IRC and ask. -* If the same guide writer wants to write multiple guides, that's ideally the situation we'd love to be in! However, that guide writer will only receive the cash prize for all the subsequent guides (and not the GitHub or RPM prizes). -* Our review team will have the final say on whether the guide is complete and of good enough quality. - -All authors should read and follow the "Rails Guides Conventions":ruby_on_rails_guides_guidelines.html and the "Rails API Documentation Conventions":api_documentation_guidelines.html. - -h3. Translations - -The translation effort for the Rails Guides is just getting underway. We know about projects to translate the Guides into Spanish, Portuguese, Polish, and French. For more details or to get involved see the "Translating Rails Guides":https://wiki.github.com/lifo/docrails/translating-rails-guides page. - -h3. Mailing List - -"Ruby on Rails: Documentation":http://groups.google.com/group/rubyonrails-docs is the mailing list for all the guides/documentation related discussions. - -h3. Contact - -* IRC : #docrails channel in irc.freenode.net -* Twitter: "@docrails":http://twitter.com/docrails, "@lifo":http://twitter.com/lifo, "@fxn":http://twitter.com/fxn -* Email : pratiknaik aT gmail, fxn aT hashref dot com -- cgit v1.2.3 From 21eaba4c39773af3e7b279325fb8d6b5ab474ef0 Mon Sep 17 00:00:00 2001 From: kennyj Date: Tue, 13 Sep 2011 02:59:57 +0900 Subject: fix https://github.com/rails/rails/issues/2947 (with testcase) --- actionpack/lib/sprockets/assets.rake | 3 +++ railties/test/application/rake_test.rb | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 2e415bf6cc..7e0c7cac52 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -16,6 +16,9 @@ namespace :assets do # Always compile files Rails.application.config.assets.compile = true + # Always ignore asset host + Rails.application.config.action_controller.asset_host = nil + config = Rails.application.config env = Rails.application.assets target = Pathname.new(File.join(Rails.public_path, config.assets.prefix)) diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 9b1b24fca1..721a8c978f 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -260,5 +260,21 @@ module ApplicationTests end end + def test_assets_precompile_ignore_asset_host + add_to_config <<-RUBY + config.action_controller.asset_host = Proc.new { |source, request| "http://www.example.com/" } + RUBY + + app_file "app/assets/javascripts/test.js.erb", <<-RUBY + alert("<%= asset_path "rails.png" %>"); + RUBY + + Dir.chdir(app_path) do + `rake assets:precompile` + open("public/assets/application.js") do |f| + assert_match(/\"\/assets\/rails.png\"/, f.read) + end + end + end end end -- cgit v1.2.3 From f74692788914a95794e823d2ec40815319447131 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Mon, 12 Sep 2011 13:16:55 -0500 Subject: Remove odd asignation --- actionpack/lib/action_view/asset_paths.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb index 73f4f8ee5f..1d968fc798 100644 --- a/actionpack/lib/action_view/asset_paths.rb +++ b/actionpack/lib/action_view/asset_paths.rb @@ -121,7 +121,6 @@ module ActionView def relative_url_root config = controller.config if controller.respond_to?(:config) config ||= config.action_controller if config.action_controller.present? - config ||= config config.relative_url_root end -- cgit v1.2.3 From 7d235b972b29659d94e2b290be6e0ad3bc6a2668 Mon Sep 17 00:00:00 2001 From: dharmatech Date: Mon, 12 Sep 2011 15:55:01 -0500 Subject: getting_started.textile: Fix typo and split up a sentence in section "Building a Multi-Model Form" --- railties/guides/source/getting_started.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 37aabcda83..b8dd4be73b 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1719,8 +1719,8 @@ This example shows another option of the render helper, being able to pass in local variables, in this case, we want the local variable +form+ in the partial to refer to the +post_form+ object. -We also add a @post.tags.build at the top of this form, this is to make -sure there is a new tag ready to have it's name filled in by the user. If you do +We also add a @post.tags.build at the top of this form. This is to make +sure there is a new tag ready to have its name filled in by the user. If you do not build the new tag, then the form will not appear as there is no new Tag object ready to create. -- cgit v1.2.3 From 8d59e0b2633c26f9de8942a2d676afe39b0ee3f8 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 4 Sep 2011 22:05:53 +0100 Subject: Alias id= if necessary, rather than relying on method_missing --- activerecord/lib/active_record/attribute_methods/write.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index c77a3ac145..5621b44c8c 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -17,6 +17,10 @@ module ActiveRecord write_attribute(attr_name, new_value) end end + + if attr_name == primary_key && attr_name != "id" + generated_attribute_methods.module_eval("alias :id= :'#{primary_key}='") + end end end -- cgit v1.2.3 From 8b8b7143efe2e0bac5bcfe90264e4baa66bdb532 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 4 Sep 2011 22:07:07 +0100 Subject: Use an empty AttributeMethodMatcher by default. This means that attribute methods which don't exist will get generated when define_attribute_methods is called, so we don't have to use hacks like `attribute_method_suffix ''`. --- activemodel/lib/active_model/attribute_methods.rb | 11 +++++++++-- activemodel/test/cases/attribute_methods_test.rb | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index bdc0eb4a0d..f058d3aa79 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -60,7 +60,7 @@ module ActiveModel included do class_attribute :attribute_method_matchers, :instance_writer => false - self.attribute_method_matchers = [] + self.attribute_method_matchers = [ClassMethods::AttributeMethodMatcher.new] end module ClassMethods @@ -357,8 +357,11 @@ module ActiveModel if attribute_method_matchers_cache.key?(method_name) attribute_method_matchers_cache[method_name] else + # Must try to match prefixes/suffixes first, or else the matcher with no prefix/suffix + # will match every time. + matchers = attribute_method_matchers.partition(&:plain?).reverse.flatten(1) match = nil - attribute_method_matchers.detect { |method| match = method.match(method_name) } + matchers.detect { |method| match = method.match(method_name) } attribute_method_matchers_cache[method_name] = match end end @@ -387,6 +390,10 @@ module ActiveModel def method_name(attr_name) @method_name % attr_name end + + def plain? + prefix.empty? && suffix.empty? + end end end diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb index 9840e3364c..95a7098ba4 100644 --- a/activemodel/test/cases/attribute_methods_test.rb +++ b/activemodel/test/cases/attribute_methods_test.rb @@ -24,7 +24,16 @@ end class ModelWithAttributes2 include ActiveModel::AttributeMethods + attr_accessor :attributes + attribute_method_suffix '_test' + +private + def attribute(name) + attributes[name.to_s] + end + + alias attribute_test attribute end class ModelWithAttributesWithSpaces @@ -129,4 +138,12 @@ class AttributeMethodsTest < ActiveModel::TestCase assert !ModelWithAttributes.new.respond_to?(:foo) assert_raises(NoMethodError) { ModelWithAttributes.new.foo } end + + test 'acessing a suffixed attribute' do + m = ModelWithAttributes2.new + m.attributes = { 'foo' => 'bar' } + + assert_equal 'bar', m.foo + assert_equal 'bar', m.foo_test + end end -- cgit v1.2.3 From 93d574c9627ade0b0bdf4ff05471dabe18cafedc Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 9 Sep 2011 09:02:40 +0100 Subject: refactoring --- activemodel/lib/active_model/attribute_methods.rb | 30 +++++++++-------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index f058d3aa79..b1724c277a 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -284,33 +284,25 @@ module ActiveModel def define_attribute_method(attr_name) attribute_method_matchers.each do |matcher| - unless instance_method_already_implemented?(matcher.method_name(attr_name)) - generate_method = "define_method_#{matcher.prefix}attribute#{matcher.suffix}" + method_name = matcher.method_name(attr_name) + + unless instance_method_already_implemented?(method_name) + generate_method = "define_method_#{matcher.method_missing_target}" if respond_to?(generate_method) send(generate_method, attr_name) else - method_name = matcher.method_name(attr_name) + if method_name =~ COMPILABLE_REGEXP + defn = "def #{method_name}(*args)" + else + defn = "define_method(:'#{method_name}') do |*args|" + end generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1 - if method_defined?('#{method_name}') - undef :'#{method_name}' + #{defn} + send(:#{matcher.method_missing_target}, '#{attr_name}', *args) end RUBY - - if method_name.to_s =~ COMPILABLE_REGEXP - generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{method_name}(*args) - send(:#{matcher.method_missing_target}, '#{attr_name}', *args) - end - RUBY - else - generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1 - define_method('#{method_name}') do |*args| - send('#{matcher.method_missing_target}', '#{attr_name}', *args) - end - RUBY - end end end end -- cgit v1.2.3 From 99bd6b53da9555450afb1e050324007868e0768c Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 9 Sep 2011 09:08:27 +0100 Subject: Add deprecation for doing `attribute_method_suffix ''` --- activemodel/lib/active_model/attribute_methods.rb | 11 +++++++++++ activemodel/test/cases/attribute_methods_test.rb | 17 +++++++++++------ .../lib/active_record/attribute_methods/read.rb | 2 -- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index b1724c277a..c5f7a21d3f 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/class/attribute' +require 'active_support/deprecation' module ActiveModel class MissingAttributeError < NoMethodError @@ -365,6 +366,16 @@ module ActiveModel def initialize(options = {}) options.symbolize_keys! + + if options[:prefix] == '' || options[:suffix] == '' + ActiveSupport::Deprecation.warn( + "Specifying an empty prefix/suffix for an attribute method is no longer " \ + "necessary. If the un-prefixed/suffixed version of the method has not been " \ + "defined when `define_attribute_methods` is called, it will be defined " \ + "automatically." + ) + end + @prefix, @suffix = options[:prefix] || '', options[:suffix] || '' @regex = /^(#{Regexp.escape(@prefix)})(.+?)(#{Regexp.escape(@suffix)})$/ @method_missing_target = "#{@prefix}attribute#{@suffix}" diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb index 95a7098ba4..61ff5fca7a 100644 --- a/activemodel/test/cases/attribute_methods_test.rb +++ b/activemodel/test/cases/attribute_methods_test.rb @@ -3,8 +3,6 @@ require 'cases/helper' class ModelWithAttributes include ActiveModel::AttributeMethods - attribute_method_suffix '' - class << self define_method(:bar) do 'original bar' @@ -39,8 +37,6 @@ end class ModelWithAttributesWithSpaces include ActiveModel::AttributeMethods - attribute_method_suffix '' - def attributes { :'foo bar' => 'value of foo bar'} end @@ -54,8 +50,6 @@ end class ModelWithWeirdNamesAttributes include ActiveModel::AttributeMethods - attribute_method_suffix '' - class << self define_method(:'c?d') do 'original c?d' @@ -146,4 +140,15 @@ class AttributeMethodsTest < ActiveModel::TestCase assert_equal 'bar', m.foo assert_equal 'bar', m.foo_test end + + test 'explicitly specifying an empty prefix/suffix is deprecated' do + klass = Class.new(ModelWithAttributes) + + assert_deprecated { klass.attribute_method_suffix '' } + assert_deprecated { klass.attribute_method_prefix '' } + + klass.define_attribute_methods([:foo]) + + assert_equal 'value of foo', klass.new.foo + end end diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 9a50a20fbc..4174e4da09 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -6,8 +6,6 @@ module ActiveRecord ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date] included do - attribute_method_suffix "" - cattr_accessor :attribute_types_cached_by_default, :instance_writer => false self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT -- cgit v1.2.3 From 3386a089eff05a8a990ca56909c9a427f4f2fe25 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sat, 10 Sep 2011 09:36:27 +0100 Subject: Fix warnings. Make sure we don't redefine an already-defined attribute method. --- activerecord/lib/active_record/attribute_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index d0687ed0b6..1937ac4272 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -36,7 +36,7 @@ module ActiveRecord @@_defined_activerecord_methods ||= defined_activerecord_methods raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" if @@_defined_activerecord_methods.include?(method_name) - @_defined_class_methods.include?(method_name) + @_defined_class_methods.include?(method_name) || generated_attribute_methods.method_defined?(method_name) end def defined_activerecord_methods -- cgit v1.2.3 From 8667d3aeb64dd8dba463ace364534326411bb46c Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sat, 10 Sep 2011 09:41:42 +0100 Subject: Make protected method public so we avoid method_missing. --- activerecord/test/models/topic.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 6440dbe8ab..fe424e61b2 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -78,11 +78,12 @@ class Topic < ActiveRecord::Base after_initialize :set_email_address + def approved=(val) + @custom_approved = val + write_attribute(:approved, val) + end + protected - def approved=(val) - @custom_approved = val - write_attribute(:approved, val) - end def default_written_on self.written_on = Time.now unless attribute_present?("written_on") -- cgit v1.2.3 From 50d395f96ea05da1e02459688e94bff5872c307b Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sat, 10 Sep 2011 21:10:01 +0100 Subject: Raise error when using write_attribute with a non-existent attribute. Previously we would just silently write the attribute. This can lead to subtle bugs (for example, see the change in AutosaveAssociation where a through association would wrongly gain an attribute. Also, ensuring that we never gain any new attributes after initialization will allow me to reduce our dependence on method_missing. --- .../lib/active_record/attribute_methods/write.rb | 10 +++++++--- activerecord/lib/active_record/autosave_association.rb | 5 ++++- activerecord/lib/active_record/persistence.rb | 2 +- activerecord/lib/active_record/timestamp.rb | 4 +++- activerecord/test/cases/persistence_test.rb | 17 +++++++++++------ activerecord/test/cases/serialization_test.rb | 13 +++++++------ activerecord/test/models/contact.rb | 13 +++++++------ activerecord/test/schema/schema.rb | 8 +++++++- 8 files changed, 47 insertions(+), 25 deletions(-) diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index 5621b44c8c..e9cdb130db 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -28,12 +28,16 @@ module ActiveRecord # for fixnum and float columns are turned into +nil+. def write_attribute(attr_name, value) attr_name = attr_name.to_s - attr_name = self.class.primary_key if attr_name == 'id' + attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key @attributes_cache.delete(attr_name) - if (column = column_for_attribute(attr_name)) && column.number? + column = column_for_attribute(attr_name) + + if column && column.number? @attributes[attr_name] = convert_number_column_value(value) - else + elsif column || @attributes.has_key?(attr_name) @attributes[attr_name] = value + else + raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'" end end alias_method :raw_write_attribute, :write_attribute diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 085fdba639..056170d82a 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -370,7 +370,10 @@ module ActiveRecord else key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id if autosave != false && (new_record? || record.new_record? || record[reflection.foreign_key] != key || autosave) - record[reflection.foreign_key] = key + unless reflection.through_reflection + record[reflection.foreign_key] = key + end + saved = record.save(:validate => !autosave) raise ActiveRecord::Rollback if !saved && autosave saved diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 2dac9ea0fb..5e65e46a7d 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -314,7 +314,7 @@ module ActiveRecord new_id = self.class.unscoped.insert attributes_values - self.id ||= new_id + self.id ||= new_id if self.class.primary_key IdentityMap.add(self) if IdentityMap.enabled? @new_record = false diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index cccac6ffd7..4d5e469a7f 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -48,7 +48,9 @@ module ActiveRecord current_time = current_time_from_proper_timezone all_timestamp_attributes.each do |column| - write_attribute(column.to_s, current_time) if respond_to?(column) && self.send(column).nil? + if respond_to?(column) && respond_to?("#{column}=") && self.send(column).nil? + write_attribute(column.to_s, current_time) + end end end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 9cd07fa8a5..adfd8e83a1 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -202,9 +202,12 @@ class PersistencesTest < ActiveRecord::TestCase end def test_create_columns_not_equal_attributes - topic = Topic.new - topic.title = 'Another New Topic' - topic.send :write_attribute, 'does_not_exist', 'test' + topic = Topic.allocate.init_with( + 'attributes' => { + 'title' => 'Another New Topic', + 'does_not_exist' => 'test' + } + ) assert_nothing_raised { topic.save } end @@ -249,9 +252,11 @@ class PersistencesTest < ActiveRecord::TestCase topic.title = "Still another topic" topic.save - topicReloaded = Topic.find(topic.id) - topicReloaded.title = "A New Topic" - topicReloaded.send :write_attribute, 'does_not_exist', 'test' + topicReloaded = Topic.allocate + topicReloaded.init_with( + 'attributes' => topic.attributes.merge('does_not_exist' => 'test') + ) + topicReloaded.title = 'A New Topic' assert_nothing_raised { topicReloaded.save } end diff --git a/activerecord/test/cases/serialization_test.rb b/activerecord/test/cases/serialization_test.rb index 382d659289..61b04b3e37 100644 --- a/activerecord/test/cases/serialization_test.rb +++ b/activerecord/test/cases/serialization_test.rb @@ -7,12 +7,13 @@ class SerializationTest < ActiveRecord::TestCase def setup @contact_attributes = { - :name => 'aaron stack', - :age => 25, - :avatar => 'binarydata', - :created_at => Time.utc(2006, 8, 1), - :awesome => false, - :preferences => { :gem => 'ruby' } + :name => 'aaron stack', + :age => 25, + :avatar => 'binarydata', + :created_at => Time.utc(2006, 8, 1), + :awesome => false, + :preferences => { :gem => 'ruby' }, + :alternative_id => nil } end diff --git a/activerecord/test/models/contact.rb b/activerecord/test/models/contact.rb index e081eee661..3d15c7fbed 100644 --- a/activerecord/test/models/contact.rb +++ b/activerecord/test/models/contact.rb @@ -11,12 +11,13 @@ class Contact < ActiveRecord::Base connection.merge_column('contacts', name, sql_type, options) end - column :name, :string - column :age, :integer - column :avatar, :binary - column :created_at, :datetime - column :awesome, :boolean - column :preferences, :string + column :name, :string + column :age, :integer + column :avatar, :binary + column :created_at, :datetime + column :awesome, :boolean + column :preferences, :string + column :alternative_id, :integer serialize :preferences diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 64e0452100..9d5ad16a3c 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -47,6 +47,7 @@ ActiveRecord::Schema.define do create_table :audit_logs, :force => true do |t| t.column :message, :string, :null=>false t.column :developer_id, :integer, :null=>false + t.integer :unvalidated_developer_id end create_table :authors, :force => true do |t| @@ -156,6 +157,7 @@ ActiveRecord::Schema.define do t.string :type t.integer :taggings_count, :default => 0 t.integer :children_count, :default => 0 + t.integer :parent_id end create_table :companies, :force => true do |t| @@ -461,6 +463,7 @@ ActiveRecord::Schema.define do create_table :pirates, :force => true do |t| t.column :catchphrase, :string t.column :parrot_id, :integer + t.integer :non_validated_parrot_id t.column :created_on, :datetime t.column :updated_on, :datetime end @@ -529,6 +532,7 @@ ActiveRecord::Schema.define do create_table :ships, :force => true do |t| t.string :name t.integer :pirate_id + t.integer :update_only_pirate_id t.datetime :created_at t.datetime :created_on t.datetime :updated_at @@ -663,7 +667,9 @@ ActiveRecord::Schema.define do t.string :description t.integer :man_id t.integer :polymorphic_man_id - t.string :polymorphic_man_type + t.string :polymorphic_man_type + t.integer :horrible_polymorphic_man_id + t.string :horrible_polymorphic_man_type end create_table :interests, :force => true do |t| -- cgit v1.2.3 From eecfa84a9065da2b1bd1e02f37e8653a2825c624 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 11 Sep 2011 14:48:40 +0100 Subject: Always generate attribute methods on the base class. This fixes a situation I encountered where a subclass would cache the name of a generated attribute method in @_defined_class_methods. Then, when the superclass has it's attribute methods undefined, the subclass would always have to dispatch through method_missing, because the presence of the attribute in @_defined_class_methods would mean that it is never generated again, even if undefine_attribute_methods is called on the subclass. There various other confusing edge cases like this. STI classes share columns, so let's just keep all the attribute method generation state isolated to the base class. --- .../lib/active_record/attribute_methods.rb | 23 +++++++++++++++++----- activerecord/lib/active_record/base.rb | 2 +- .../test/cases/attribute_methods/read_test.rb | 1 + activerecord/test/cases/attribute_methods_test.rb | 16 +++++++++++++++ 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 1937ac4272..a8cb89fb65 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -11,17 +11,30 @@ module ActiveRecord # accessors, mutators and query methods. def define_attribute_methods return if attribute_methods_generated? - super(column_names) - @attribute_methods_generated = true + + if base_class == self + super(column_names) + @attribute_methods_generated = true + else + base_class.define_attribute_methods + end end def attribute_methods_generated? - @attribute_methods_generated ||= false + if base_class == self + @attribute_methods_generated ||= false + else + base_class.attribute_methods_generated? + end end def undefine_attribute_methods(*args) - super - @attribute_methods_generated = false + if base_class == self + super + @attribute_methods_generated = false + else + base_class.undefine_attribute_methods(*args) + end end # Checks whether the method is defined in the model or any of its subclasses diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 2979ad1cb3..92f80c6eaa 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1332,7 +1332,7 @@ MSG # Returns the class descending directly from ActiveRecord::Base or an # abstract class, if any, in the inheritance hierarchy. def class_of_active_record_descendant(klass) - if klass.superclass == Base || klass.superclass.abstract_class? + if klass == Base || klass.superclass == Base || klass.superclass.abstract_class? klass elsif klass.superclass.nil? raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord" diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb index 3641031d12..e03ed33591 100644 --- a/activerecord/test/cases/attribute_methods/read_test.rb +++ b/activerecord/test/cases/attribute_methods/read_test.rb @@ -35,6 +35,7 @@ module ActiveRecord end def self.serialized_attributes; {}; end + def self.base_class; self; end end end diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index dbf5a1ba76..9815c4ba87 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -659,6 +659,22 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert_equal %w(preferences), Contact.serialized_attributes.keys end + def test_instance_method_should_be_defined_on_the_base_class + subklass = Class.new(Topic) + + Topic.define_attribute_methods + + instance = subklass.new + instance.id = 5 + assert_equal 5, instance.id + assert subklass.method_defined?(:id), "subklass is missing id method" + + Topic.undefine_attribute_methods + + assert_equal 5, instance.id + assert subklass.method_defined?(:id), "subklass is missing id method" + end + private def cached_columns @cached_columns ||= (time_related_columns_on_topic + serialized_columns_on_topic).map(&:name) -- cgit v1.2.3 From cf115d2f8ef48764e095aa453f729b60705088f1 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 11 Sep 2011 16:07:24 +0100 Subject: Reset column info when messing with columns. We are subclassing Session here, but messing with the columns will affect the attribute methods defined on the Session superclass, and therefore other tests, unless we properly isolate it by resetting column info before and after the test run. --- activerecord/test/cases/session_store/session_test.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/activerecord/test/cases/session_store/session_test.rb b/activerecord/test/cases/session_store/session_test.rb index 669c0b7b4d..258cee7aba 100644 --- a/activerecord/test/cases/session_store/session_test.rb +++ b/activerecord/test/cases/session_store/session_test.rb @@ -36,6 +36,7 @@ module ActiveRecord end def test_find_by_sess_id_compat + Session.reset_column_information klass = Class.new(Session) do def self.session_id_column 'sessid' @@ -53,6 +54,7 @@ module ActiveRecord assert_equal session.sessid, found.session_id ensure klass.drop_table! + Session.reset_column_information end def test_find_by_session_id -- cgit v1.2.3 From ac687ed651773fccecbc22cd6d8b07d5439ceb76 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 12 Sep 2011 22:12:12 +0100 Subject: Let Ruby deal with method visibility. Check respond_to_without_attributes? in method_missing. If there is any method that responds (even private), let super handle it and raise NoMethodError if necessary. --- activemodel/lib/active_model/attribute_methods.rb | 24 +++++++-------- activemodel/test/cases/attribute_methods_test.rb | 36 ++++++++++++++++++++++ .../lib/active_record/attribute_methods.rb | 17 +++++----- activerecord/test/cases/attribute_methods_test.rb | 6 ++-- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index c5f7a21d3f..baebc91192 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -411,13 +411,18 @@ module ActiveModel # It's also possible to instantiate related objects, so a Client class # belonging to the clients table with a +master_id+ foreign key can # instantiate master through Client#master. - def method_missing(method_id, *args, &block) - method_name = method_id.to_s - if match = match_attribute_method?(method_name) - guard_private_attribute_method!(method_name, args) - return __send__(match.target, match.attr_name, *args, &block) + def method_missing(method, *args, &block) + if respond_to_without_attributes?(method, true) + super + else + match = match_attribute_method?(method.to_s) + + if match + __send__(match.target, match.attr_name, *args, &block) + else + super + end end - super end # A Person object with a name attribute can ask person.respond_to?(:name), @@ -450,13 +455,6 @@ module ActiveModel match && attribute_method?(match.attr_name) ? match : nil end - # prevent method_missing from calling private methods with #send - def guard_private_attribute_method!(method_name, args) - if self.class.private_method_defined?(method_name) - raise NoMethodError.new("Attempt to call private method `#{method_name}'", method_name, args) - end - end - def missing_attribute(attr_name, stack) raise ActiveModel::MissingAttributeError, "missing attribute: #{attr_name}", stack end diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb index 61ff5fca7a..198e4c3c06 100644 --- a/activemodel/test/cases/attribute_methods_test.rb +++ b/activemodel/test/cases/attribute_methods_test.rb @@ -32,6 +32,16 @@ private end alias attribute_test attribute + + def private_method + "<3 <3" + end + +protected + + def protected_method + "O_o O_o" + end end class ModelWithAttributesWithSpaces @@ -151,4 +161,30 @@ class AttributeMethodsTest < ActiveModel::TestCase assert_equal 'value of foo', klass.new.foo end + + test 'should not interfere with method_missing if the attr has a private/protected method' do + m = ModelWithAttributes2.new + m.attributes = { 'private_method' => '<3', 'protected_method' => 'O_o' } + + # dispatches to the *method*, not the attribute + assert_equal '<3 <3', m.send(:private_method) + assert_equal 'O_o O_o', m.send(:protected_method) + + # sees that a method is already defined, so doesn't intervene + assert_raises(NoMethodError) { m.private_method } + assert_raises(NoMethodError) { m.protected_method } + end + + test 'should not interfere with respond_to? if the attribute has a private/protected method' do + m = ModelWithAttributes2.new + m.attributes = { 'private_method' => '<3', 'protected_method' => 'O_o' } + + assert !m.respond_to?(:private_method) + assert m.respond_to?(:private_method, true) + + # This is messed up, but it's how Ruby works at the moment. Apparently it will be changed + # in the future. + assert m.respond_to?(:protected_method) + assert m.respond_to?(:protected_method, true) + end end diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index a8cb89fb65..8d7eb4a48d 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -61,14 +61,17 @@ module ActiveRecord end end - def method_missing(method_id, *args, &block) - # If we haven't generated any methods yet, generate them, then - # see if we've created the method we're looking for. - if !self.class.attribute_methods_generated? + # If we haven't generated any methods yet, generate them, then + # see if we've created the method we're looking for. + def method_missing(method, *args, &block) + unless self.class.attribute_methods_generated? self.class.define_attribute_methods - method_name = method_id.to_s - guard_private_attribute_method!(method_name, args) - send(method_id, *args, &block) + + if respond_to_without_attributes?(method) + send(method, *args, &block) + else + super + end else super end diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 9815c4ba87..5ae3713e73 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -608,7 +608,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase topic = @target.new(:title => "The pros and cons of programming naked.") assert !topic.respond_to?(:title) exception = assert_raise(NoMethodError) { topic.title } - assert_match %r(^Attempt to call private method), exception.message + assert exception.message.include?("private method") assert_equal "I'm private", topic.send(:title) end @@ -618,7 +618,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase topic = @target.new assert !topic.respond_to?(:title=) exception = assert_raise(NoMethodError) { topic.title = "Pants"} - assert_match %r(^Attempt to call private method), exception.message + assert exception.message.include?("private method") topic.send(:title=, "Very large pants") end @@ -628,7 +628,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase topic = @target.new(:title => "Isaac Newton's pants") assert !topic.respond_to?(:title?) exception = assert_raise(NoMethodError) { topic.title? } - assert_match %r(^Attempt to call private method), exception.message + assert exception.message.include?("private method") assert topic.send(:title?) end -- cgit v1.2.3 From 6d8dbeca6b0e676145ecdbba38f2fe56b74b4f8f Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 12 Sep 2011 22:29:45 +0100 Subject: Avoid double super call in some cases. If super was false earlier, it is still going to be false, so we don't need to call it again at the end of the method. --- activemodel/lib/active_model/attribute_methods.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index baebc91192..39ece6d3b3 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -431,15 +431,14 @@ module ActiveModel alias :respond_to_without_attributes? :respond_to? def respond_to?(method, include_private_methods = false) if super - return true + true elsif !include_private_methods && super(method, true) # If we're here then we haven't found among non-private methods # but found among all methods. Which means that the given method is private. - return false - elsif match_attribute_method?(method.to_s) - return true + false + else + !match_attribute_method?(method.to_s).nil? end - super end protected -- cgit v1.2.3 From c89e1c7bdefa2489f6ebd04862a426b7200bf494 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 12 Sep 2011 23:58:20 +0100 Subject: Add an attribute_missing method to ActiveModel::AttributeMethods. This can be overloaded by implementors if necessary. --- activemodel/lib/active_model/attribute_methods.rb | 19 +++++++++++-------- activemodel/test/cases/attribute_methods_test.rb | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 39ece6d3b3..539e0bbdda 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -362,7 +362,7 @@ module ActiveModel class AttributeMethodMatcher attr_reader :prefix, :suffix, :method_missing_target - AttributeMethodMatch = Struct.new(:target, :attr_name) + AttributeMethodMatch = Struct.new(:target, :attr_name, :method_name) def initialize(options = {}) options.symbolize_keys! @@ -384,7 +384,7 @@ module ActiveModel def match(method_name) if @regex =~ method_name - AttributeMethodMatch.new(method_missing_target, $2) + AttributeMethodMatch.new(method_missing_target, $2, method_name) else nil end @@ -416,15 +416,18 @@ module ActiveModel super else match = match_attribute_method?(method.to_s) - - if match - __send__(match.target, match.attr_name, *args, &block) - else - super - end + match ? attribute_missing(match, *args, &block) : super end end + # attribute_missing is like method_missing, but for attributes. When method_missing is + # called we check to see if there is a matching attribute method. If so, we call + # attribute_missing to dispatch the attribute. This method can be overloaded to + # customise the behaviour. + def attribute_missing(match, *args, &block) + __send__(match.target, match.attr_name, *args, &block) + end + # A Person object with a name attribute can ask person.respond_to?(:name), # person.respond_to?(:name=), and person.respond_to?(:name?) # which will all return +true+. diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb index 198e4c3c06..e655c7a1af 100644 --- a/activemodel/test/cases/attribute_methods_test.rb +++ b/activemodel/test/cases/attribute_methods_test.rb @@ -187,4 +187,19 @@ class AttributeMethodsTest < ActiveModel::TestCase assert m.respond_to?(:protected_method) assert m.respond_to?(:protected_method, true) end + + test 'should use attribute_missing to dispatch a missing attribute' do + m = ModelWithAttributes2.new + m.attributes = { 'foo' => 'bar' } + + def m.attribute_missing(match, *args, &block) + match + end + + match = m.foo_test + + assert_equal 'foo', match.attr_name + assert_equal 'attribute_test', match.target + assert_equal 'foo_test', match.method_name + end end -- cgit v1.2.3 From 1a421ceccb25b15c87e97567fff573c941aa3ab3 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 12 Sep 2011 23:58:37 +0100 Subject: Deprecate using method_missing for attributes that are columns. This shouldn't ever happen unless people are doing something particularly weird, but adding a deprecation in case there are bugs not caught by our tests. --- activerecord/lib/active_record/attribute_methods.rb | 15 +++++++++++++++ activerecord/test/cases/attribute_methods_test.rb | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 8d7eb4a48d..dc6dc2e63a 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/enumerable' +require 'active_support/deprecation' module ActiveRecord # = Active Record Attribute Methods @@ -77,6 +78,20 @@ module ActiveRecord end end + def attribute_missing(match, *args, &block) + if self.class.columns_hash[match.attr_name] + ActiveSupport::Deprecation.warn( + "The method `#{match.method_name}', matching the attribute `#{match.attr_name}' has " \ + "dispatched through method_missing. This shouldn't happen, because `#{match.attr_name}' " \ + "is a column of the table. If this error has happened through normal usage of Active " \ + "Record (rather than through your own code or external libraries), please report it as " \ + "a bug." + ) + end + + super + end + def respond_to?(name, include_private = false) self.class.define_attribute_methods unless self.class.attribute_methods_generated? super diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 5ae3713e73..e324a252dd 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -675,6 +675,21 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert subklass.method_defined?(:id), "subklass is missing id method" end + def test_dispatching_column_attributes_through_method_missing_deprecated + Topic.define_attribute_methods + + topic = Topic.new(:id => 5) + topic.id = 5 + + topic.method(:id).owner.send(:remove_method, :id) + + assert_deprecated do + assert_equal 5, topic.id + end + ensure + Topic.undefine_attribute_methods + end + private def cached_columns @cached_columns ||= (time_related_columns_on_topic + serialized_columns_on_topic).map(&:name) -- cgit v1.2.3 From 5f0b37c486dcc735b5817852932e761f5ff60152 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 8 Sep 2011 10:51:23 -0700 Subject: Switching rack-mount to journey. --- Gemfile | 7 +++++++ actionpack/actionpack.gemspec | 2 +- actionpack/lib/action_dispatch/routing/route_set.rb | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 54e171b0db..5ce420c3a3 100644 --- a/Gemfile +++ b/Gemfile @@ -8,6 +8,13 @@ end gem "bcrypt-ruby", "~> 3.0.0" gem "jquery-rails" + +if ENV['JOURNEY'] + gem "journey", :path => ENV['JOURNEY'] +else + gem "journey", :git => "git://github.com/rails/journey" +end + # This needs to be with require false to avoid # it being automatically loaded by sprockets gem "uglifier", ">= 1.0.3", :require => false diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 65b364f872..f1b7966b9c 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -23,7 +23,7 @@ Gem::Specification.new do |s| s.add_dependency('i18n', '~> 0.6') s.add_dependency('rack', '~> 1.3.2') s.add_dependency('rack-test', '~> 0.6.1') - s.add_dependency('rack-mount', '~> 0.8.2') + s.add_dependency('journey', '~> 1.0.0') s.add_dependency('sprockets', '~> 2.0.0') s.add_dependency('erubis', '~> 2.7.0') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 11228c597d..2067c187e7 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -1,4 +1,5 @@ -require 'rack/mount' +require 'journey/router' +require 'journey/backwards' require 'forwardable' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/to_query' -- cgit v1.2.3 From a05a9ff1cab1d90424a7d5eca2ade4ea800994ba Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 8 Sep 2011 10:52:04 -0700 Subject: stop using a hash for parameterizing --- actionpack/lib/action_dispatch/routing/route_set.rb | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 2067c187e7..66db1c629f 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -350,18 +350,16 @@ module ActionDispatch end class Generator #:nodoc: - PARAMETERIZE = { - :parameterize => lambda do |name, value| - if name == :controller - value - elsif value.is_a?(Array) - value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/') - else - return nil unless param = value.to_param - param.split('/').map { |v| Rack::Mount::Utils.escape_uri(v) }.join("/") - end + PARAMETERIZE = lambda do |name, value| + if name == :controller + value + elsif value.is_a?(Array) + value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/') + else + return nil unless param = value.to_param + param.split('/').map { |v| Rack::Mount::Utils.escape_uri(v) }.join("/") end - } + end attr_reader :options, :recall, :set, :named_route -- cgit v1.2.3 From 537ed6eb2f38f41da34bcecc51d2c25b961b53ef Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 8 Sep 2011 13:53:10 -0700 Subject: stop freezing the routes --- actionpack/lib/action_dispatch/routing/route_set.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 66db1c629f..ebefd0ecd4 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -264,7 +264,6 @@ module ActionDispatch return if @finalized @append.each { |blk| eval_block(blk) } @finalized = true - @set.freeze end def clear! -- cgit v1.2.3 From 4ffe667ab7713a7cd926803655719b2a399615ce Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 8 Sep 2011 14:09:33 -0700 Subject: Instantiate each part of our routing system: * A collection of Routes * The Router, which consults the collection of routes * A formatter that consults the collection of routes --- actionpack/lib/action_dispatch/routing/route_set.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index ebefd0ecd4..3883ac7c60 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -206,7 +206,7 @@ module ActionDispatch end end - attr_accessor :set, :routes, :named_routes, :default_scope + attr_accessor :formatter, :set, :routes, :named_routes, :default_scope, :router attr_accessor :disable_clear_and_finalize, :resources_path_names attr_accessor :default_url_options, :request_class, :valid_conditions @@ -270,10 +270,11 @@ module ActionDispatch @finalized = false routes.clear named_routes.clear - @set = ::Rack::Mount::RouteSet.new( + @set = Journey::Routes.new + @router = Journey::Router.new(@set, { :parameters_key => PARAMETERS_KEY, - :request_class => request_class - ) + :request_class => request_class}) + @formatter = Journey::Formatter.new @set @prepend.each { |blk| eval_block(blk) } end @@ -448,7 +449,7 @@ module ActionDispatch end def generate - path, params = @set.set.generate(:path_info, named_route, options, recall, PARAMETERIZE) + path, params = @set.formatter.generate(:path_info, named_route, options, recall, PARAMETERIZE) raise_routing_error unless path @@ -527,7 +528,7 @@ module ActionDispatch def call(env) finalize! - @set.call(env) + @router.call(env) end def recognize_path(path, environment = {}) @@ -541,7 +542,7 @@ module ActionDispatch end req = @request_class.new(env) - @set.recognize(req) do |route, matches, params| + @router.recognize(req) do |route, matches, params| params.each do |key, value| if value.is_a?(String) value = value.dup.force_encoding(Encoding::BINARY) if value.encoding_aware? -- cgit v1.2.3 From 59b9fe961d2195b35f3934dc6228a248897656e6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 8 Sep 2011 14:38:46 -0700 Subject: reuse the route collection and formatter by clearing them --- actionpack/lib/action_dispatch/routing/route_set.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 3883ac7c60..2419e09ee0 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -228,6 +228,13 @@ module ActionDispatch @append = [] @prepend = [] @disable_clear_and_finalize = false + + @set = Journey::Routes.new + @router = Journey::Router.new(@set, { + :parameters_key => PARAMETERS_KEY, + :request_class => request_class}) + @formatter = Journey::Formatter.new @set + clear! end @@ -270,11 +277,8 @@ module ActionDispatch @finalized = false routes.clear named_routes.clear - @set = Journey::Routes.new - @router = Journey::Router.new(@set, { - :parameters_key => PARAMETERS_KEY, - :request_class => request_class}) - @formatter = Journey::Formatter.new @set + set.clear + formatter.clear @prepend.each { |blk| eval_block(blk) } end @@ -343,7 +347,7 @@ module ActionDispatch def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true) raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i) route = Route.new(self, app, conditions, requirements, defaults, name, anchor) - @set.add_route(route.app, route.conditions, route.defaults, route.name) + @set.add_route(app, route.conditions, defaults, name) named_routes[name] = route if name routes << route route -- cgit v1.2.3 From b7ccfa96d2f5b95ec4544716571c1e90f0b89464 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 8 Sep 2011 14:41:12 -0700 Subject: clear! does not need to be called from initialize --- actionpack/lib/action_dispatch/routing/route_set.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 2419e09ee0..000b2a252f 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -225,17 +225,16 @@ module ActionDispatch self.valid_conditions.delete(:id) self.valid_conditions.push(:controller, :action) - @append = [] - @prepend = [] + @append = [] + @prepend = [] @disable_clear_and_finalize = false + @finalized = false @set = Journey::Routes.new @router = Journey::Router.new(@set, { :parameters_key => PARAMETERS_KEY, :request_class => request_class}) @formatter = Journey::Formatter.new @set - - clear! end def draw(&block) -- cgit v1.2.3 From a08bee784125d569f63ddd9fa875ae9c5d18b342 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 11 Sep 2011 17:14:29 -0700 Subject: all routes can be stored in the Journey Routes object --- actionpack/lib/action_dispatch/routing/route_set.rb | 9 ++++----- actionpack/test/controller/resources_test.rb | 2 +- actionpack/test/dispatch/mapper_test.rb | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 000b2a252f..2947eb3f09 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -206,16 +206,17 @@ module ActionDispatch end end - attr_accessor :formatter, :set, :routes, :named_routes, :default_scope, :router + attr_accessor :formatter, :set, :named_routes, :default_scope, :router attr_accessor :disable_clear_and_finalize, :resources_path_names attr_accessor :default_url_options, :request_class, :valid_conditions + alias :routes :set + def self.default_resources_path_names { :new => 'new', :edit => 'edit' } end def initialize(request_class = ActionDispatch::Request) - self.routes = [] self.named_routes = NamedRouteCollection.new self.resources_path_names = self.class.default_resources_path_names.dup self.default_url_options = {} @@ -274,7 +275,6 @@ module ActionDispatch def clear! @finalized = false - routes.clear named_routes.clear set.clear formatter.clear @@ -346,9 +346,8 @@ module ActionDispatch def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true) raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i) route = Route.new(self, app, conditions, requirements, defaults, name, anchor) - @set.add_route(app, route.conditions, defaults, name) + route = @set.add_route(app, route.conditions, defaults, name) named_routes[name] = route if name - routes << route route end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index b9cd15708b..6b8a8f6161 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -532,7 +532,7 @@ class ResourcesTest < ActionController::TestCase routes.each do |route| routes.each do |r| next if route === r # skip the comparison instance - assert_not_equal route.conditions, r.conditions + assert_not_equal [route.conditions, route.path.spec.to_s], [r.conditions, r.path.spec.to_s] end end end diff --git a/actionpack/test/dispatch/mapper_test.rb b/actionpack/test/dispatch/mapper_test.rb index 3316dd03aa..d3465589c1 100644 --- a/actionpack/test/dispatch/mapper_test.rb +++ b/actionpack/test/dispatch/mapper_test.rb @@ -5,6 +5,7 @@ module ActionDispatch class MapperTest < ActiveSupport::TestCase class FakeSet attr_reader :routes + alias :set :routes def initialize @routes = [] -- cgit v1.2.3 From d21e0e2af3d9b21399244c3f3f73378d75cd4697 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 11 Sep 2011 17:14:42 -0700 Subject: adjust route inspection to work with Journey --- railties/lib/rails/application/route_inspector.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/application/route_inspector.rb b/railties/lib/rails/application/route_inspector.rb index 15c6d035e5..8c6911e6bb 100644 --- a/railties/lib/rails/application/route_inspector.rb +++ b/railties/lib/rails/application/route_inspector.rb @@ -23,7 +23,8 @@ module Rails reqs = reqs.empty? ? constraints.inspect : "#{reqs} #{constraints.inspect}" end - {:name => route.name.to_s, :verb => route.verb.to_s, :path => route.path, :reqs => reqs} + verb = route.verb.source.gsub(/[$^]/, '') + {:name => route.name.to_s, :verb => verb, :path => route.path.spec.to_s, :reqs => reqs} end # Skip the route if it's internal info route -- cgit v1.2.3 From f5ab6805edbd72f752069d94d88003314e2a8a0a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 11 Sep 2011 17:52:19 -0700 Subject: delete unused code, pass path explicitly to journey --- actionpack/lib/action_dispatch/routing/route.rb | 32 ++++------------------ .../lib/action_dispatch/routing/route_set.rb | 3 +- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route.rb b/actionpack/lib/action_dispatch/routing/route.rb index 10b3d38346..563adb02c4 100644 --- a/actionpack/lib/action_dispatch/routing/route.rb +++ b/actionpack/lib/action_dispatch/routing/route.rb @@ -1,27 +1,12 @@ module ActionDispatch module Routing class Route #:nodoc: - attr_reader :app, :conditions, :defaults, :name - attr_reader :path, :requirements, :set + attr_reader :conditions, :path def initialize(set, app, conditions, requirements, defaults, name, anchor) @set = set - @app = app - @defaults = defaults - @name = name - - # FIXME: we should not be doing this much work in a constructor. - - @requirements = requirements.merge(defaults) - @requirements.delete(:controller) if @requirements[:controller].is_a?(Regexp) - @requirements.delete_if { |k, v| - v == Regexp.compile("[^#{SEPARATORS.join}]+") - } - - if path = conditions[:path_info] - @path = path - conditions[:path_info] = ::Rack::Mount::Strexp.compile(path, requirements, SEPARATORS, anchor) - end + path = ::Rack::Mount::Strexp.new( + conditions[:path_info], requirements, SEPARATORS, anchor) @verbs = conditions[:request_method] || [] @@ -32,9 +17,8 @@ module ActionDispatch # # Here we munge values before they get sent on to rack-mount. @conditions[:request_method] = %r[^#{verb}$] unless @verbs.empty? - @conditions[:path_info] = Rack::Mount::RegexpWithNamedGroups.new(@conditions[:path_info]) if @conditions[:path_info] + @conditions[:path_info] = Rack::Mount::RegexpWithNamedGroups.new(path) @conditions.delete_if{ |k,v| k != :path_info && !valid_condition?(k) } - @requirements.delete_if{ |k,v| !valid_condition?(k) } end def verb @@ -45,15 +29,9 @@ module ActionDispatch @segment_keys ||= conditions[:path_info].names.compact.map { |key| key.to_sym } end - def to_s - @to_s ||= begin - "%-6s %-40s %s" % [(verb || :any).to_s.upcase, path, requirements.inspect] - end - end - private def valid_condition?(method) - segment_keys.include?(method) || set.valid_conditions.include?(method) + segment_keys.include?(method) || @set.valid_conditions.include?(method) end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 2947eb3f09..21b720806c 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -346,7 +346,8 @@ module ActionDispatch def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true) raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i) route = Route.new(self, app, conditions, requirements, defaults, name, anchor) - route = @set.add_route(app, route.conditions, defaults, name) + path = route.conditions[:path_info] + route = @set.add_route(app, path, route.conditions, defaults, name) named_routes[name] = route if name route end -- cgit v1.2.3 From 943aa826a48c7db682e24f13cc93ed3298aa7e1a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 12 Sep 2011 15:48:03 -0700 Subject: reduce dependencies of external objects in the Route class --- actionpack/lib/action_dispatch/routing/route.rb | 28 ++++++++++++---------- .../lib/action_dispatch/routing/route_set.rb | 6 ++--- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route.rb b/actionpack/lib/action_dispatch/routing/route.rb index 563adb02c4..76d18e4dd5 100644 --- a/actionpack/lib/action_dispatch/routing/route.rb +++ b/actionpack/lib/action_dispatch/routing/route.rb @@ -3,10 +3,15 @@ module ActionDispatch class Route #:nodoc: attr_reader :conditions, :path - def initialize(set, app, conditions, requirements, defaults, name, anchor) - @set = set - path = ::Rack::Mount::Strexp.new( - conditions[:path_info], requirements, SEPARATORS, anchor) + def initialize(valid_conditions, app, conditions, requirements, defaults, name, anchor) + @valid_conditions = valid_conditions + strexp = Journey::Router::Strexp.new( + conditions.delete(:path_info), + requirements, + SEPARATORS, + anchor) + + @path = Journey::Path::Pattern.new(strexp) @verbs = conditions[:request_method] || [] @@ -16,22 +21,19 @@ module ActionDispatch # :request_method represents the HTTP verb that matches this route. # # Here we munge values before they get sent on to rack-mount. - @conditions[:request_method] = %r[^#{verb}$] unless @verbs.empty? - @conditions[:path_info] = Rack::Mount::RegexpWithNamedGroups.new(path) - @conditions.delete_if{ |k,v| k != :path_info && !valid_condition?(k) } - end - - def verb - @verbs.join '|' + unless @verbs.empty? + @conditions[:request_method] = %r[^#{@verbs.join('|')}$] + end + @conditions.delete_if{ |k,v| !valid_condition?(k) } end def segment_keys - @segment_keys ||= conditions[:path_info].names.compact.map { |key| key.to_sym } + @segment_keys ||= path.names.compact.map { |key| key.to_sym } end private def valid_condition?(method) - segment_keys.include?(method) || @set.valid_conditions.include?(method) + segment_keys.include?(method) || @valid_conditions.include?(method) end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 21b720806c..dad4ecb27f 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -345,9 +345,9 @@ module ActionDispatch def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true) raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i) - route = Route.new(self, app, conditions, requirements, defaults, name, anchor) - path = route.conditions[:path_info] - route = @set.add_route(app, path, route.conditions, defaults, name) + foo = Route.new(valid_conditions, app, conditions, requirements, defaults, name, anchor) + path = foo.path + route = @set.add_route(app, path, foo.conditions, defaults, name) named_routes[name] = route if name route end -- cgit v1.2.3 From ad1a89164927e1d87062a350ce259b3713c9e898 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 12 Sep 2011 16:11:55 -0700 Subject: unfactor the Route class to private factory methods --- actionpack/lib/action_dispatch/routing/route.rb | 40 ------------------ .../lib/action_dispatch/routing/route_set.rb | 47 +++++++++++++++++++--- 2 files changed, 42 insertions(+), 45 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/routing/route.rb diff --git a/actionpack/lib/action_dispatch/routing/route.rb b/actionpack/lib/action_dispatch/routing/route.rb deleted file mode 100644 index 76d18e4dd5..0000000000 --- a/actionpack/lib/action_dispatch/routing/route.rb +++ /dev/null @@ -1,40 +0,0 @@ -module ActionDispatch - module Routing - class Route #:nodoc: - attr_reader :conditions, :path - - def initialize(valid_conditions, app, conditions, requirements, defaults, name, anchor) - @valid_conditions = valid_conditions - strexp = Journey::Router::Strexp.new( - conditions.delete(:path_info), - requirements, - SEPARATORS, - anchor) - - @path = Journey::Path::Pattern.new(strexp) - - @verbs = conditions[:request_method] || [] - - @conditions = conditions.dup - - # Rack-Mount requires that :request_method be a regular expression. - # :request_method represents the HTTP verb that matches this route. - # - # Here we munge values before they get sent on to rack-mount. - unless @verbs.empty? - @conditions[:request_method] = %r[^#{@verbs.join('|')}$] - end - @conditions.delete_if{ |k,v| !valid_condition?(k) } - end - - def segment_keys - @segment_keys ||= path.names.compact.map { |key| key.to_sym } - end - - private - def valid_condition?(method) - segment_keys.include?(method) || @valid_conditions.include?(method) - end - end - end -end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index dad4ecb27f..26e6d68b1e 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -222,9 +222,15 @@ module ActionDispatch self.default_url_options = {} self.request_class = request_class - self.valid_conditions = request_class.public_instance_methods.map { |m| m.to_sym } + @valid_conditions = {} + + request_class.public_instance_methods.each { |m| + @valid_conditions[m.to_sym] = true + } + @valid_conditions[:controller] = true + @valid_conditions[:action] = true + self.valid_conditions.delete(:id) - self.valid_conditions.push(:controller, :action) @append = [] @prepend = [] @@ -345,13 +351,44 @@ module ActionDispatch def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true) raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i) - foo = Route.new(valid_conditions, app, conditions, requirements, defaults, name, anchor) - path = foo.path - route = @set.add_route(app, path, foo.conditions, defaults, name) + + path = build_path(conditions.delete(:path_info), requirements, SEPARATORS, anchor) + conditions = build_conditions(conditions, valid_conditions, path.names.map { |x| x.to_sym }) + + route = @set.add_route(app, path, conditions, defaults, name) named_routes[name] = route if name route end + def build_path(path, requirements, separators, anchor) + strexp = Journey::Router::Strexp.new( + path, + requirements, + SEPARATORS, + anchor) + + Journey::Path::Pattern.new(strexp) + end + private :build_path + + def build_conditions(current_conditions, req_predicates, path_values) + conditions = current_conditions.dup + + verbs = conditions[:request_method] || [] + + # Rack-Mount requires that :request_method be a regular expression. + # :request_method represents the HTTP verb that matches this route. + # + # Here we munge values before they get sent on to rack-mount. + unless verbs.empty? + conditions[:request_method] = %r[^#{verbs.join('|')}$] + end + conditions.delete_if { |k,v| !(req_predicates.include?(k) || path_values.include?(k)) } + + conditions + end + private :build_conditions + class Generator #:nodoc: PARAMETERIZE = lambda do |name, value| if name == :controller -- cgit v1.2.3 From ea7ef9597edf9b0579b6c91290348956a705e6b4 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 12 Sep 2011 16:30:54 -0700 Subject: partially expand the parameters to `match` --- actionpack/lib/action_dispatch/routing/mapper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 4d65173f61..c9fa96facf 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1465,9 +1465,9 @@ module ActionDispatch end module Shorthand #:nodoc: - def match(*args) - if args.size == 1 && args.last.is_a?(Hash) - options = args.pop + def match(path, *rest) + if rest.empty? && Hash === path + options = path path, to = options.find { |name, value| name.is_a?(String) } options.merge!(:to => to).delete(path) super(path, options) -- cgit v1.2.3 From 68ec26c70c38c388822a7acd8682ac97d0d43b5e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 12 Sep 2011 16:49:36 -0700 Subject: point rails at Journey for dev and edge --- railties/lib/rails/generators/app_base.rb | 2 ++ railties/lib/rails/generators/rails/app/app_generator.rb | 1 + 2 files changed, 3 insertions(+) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 93f5023a7a..294563ad06 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -138,10 +138,12 @@ module Rails if options.dev? <<-GEMFILE.strip_heredoc gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}' + gem 'journey', :path => '#{Rails::Generators::JOURNEY_DEV_PATH}' GEMFILE elsif options.edge? <<-GEMFILE.strip_heredoc gem 'rails', :git => 'git://github.com/rails/rails.git' + gem 'journey', :git => 'git://github.com/rails/journey.git' GEMFILE else <<-GEMFILE.strip_heredoc diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index d9dd33518a..9cbda6649d 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -139,6 +139,7 @@ module Rails # We need to store the RAILS_DEV_PATH in a constant, otherwise the path # can change in Ruby 1.8.7 when we FileUtils.cd. RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__)) + JOURNEY_DEV_PATH = File.expand_path("../../../../../../../journey", File.dirname(__FILE__)) RESERVED_NAMES = %w[application destroy benchmarker profiler plugin runner test] -- cgit v1.2.3 From f65b2215cd5ab54d3aca2095f51429b7e503431f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 12 Sep 2011 16:50:25 -0700 Subject: removing backwards compatibility module --- actionpack/lib/action_dispatch/http/url.rb | 2 +- actionpack/lib/action_dispatch/routing/mapper.rb | 6 +++--- actionpack/lib/action_dispatch/routing/route_set.rb | 9 ++++----- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 8487b0fc8c..caa1decb9e 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -45,7 +45,7 @@ module ActionDispatch rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) rewritten_url << "?#{params.to_query}" unless params.empty? - rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor] + rewritten_url << "##{Journey::Router::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor] rewritten_url end diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index c9fa96facf..cd59b13c42 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -213,8 +213,8 @@ module ActionDispatch end def segment_keys - @segment_keys ||= Rack::Mount::RegexpWithNamedGroups.new( - Rack::Mount::Strexp.compile(@path, requirements, SEPARATORS) + @segment_keys ||= Journey::Path::Pattern.new( + Journey::Router::Strexp.compile(@path, requirements, SEPARATORS) ).names end @@ -235,7 +235,7 @@ module ActionDispatch # (:locale) becomes (/:locale) instead of /(:locale). Except # for root cases, where the latter is the correct one. def self.normalize_path(path) - path = Rack::Mount::Utils.normalize_path(path) + path = Journey::Router::Utils.normalize_path(path) path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/\(+[^/]+\)$} path end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 26e6d68b1e..46a68a32ae 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -1,5 +1,4 @@ require 'journey/router' -require 'journey/backwards' require 'forwardable' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/to_query' @@ -394,10 +393,10 @@ module ActionDispatch if name == :controller value elsif value.is_a?(Array) - value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/') + value.map { |v| Journey::Router::Utils.escape_uri(v.to_param) }.join('/') else return nil unless param = value.to_param - param.split('/').map { |v| Rack::Mount::Utils.escape_uri(v) }.join("/") + param.split('/').map { |v| Journey::Router::Utils.escape_uri(v) }.join("/") end end @@ -496,7 +495,7 @@ module ActionDispatch return [path, params.keys] if @extras [path, params] - rescue Rack::Mount::RoutingError + rescue Journey::Router::RoutingError raise_routing_error end @@ -573,7 +572,7 @@ module ActionDispatch def recognize_path(path, environment = {}) method = (environment[:method] || "GET").to_s.upcase - path = Rack::Mount::Utils.normalize_path(path) unless path =~ %r{://} + path = Journey::Router::Utils.normalize_path(path) unless path =~ %r{://} begin env = Rack::MockRequest.env_for(path, {:method => method}) -- cgit v1.2.3 From 9279d1102c7d96810813cad0d0a666db0a549b1f Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Sun, 11 Sep 2011 01:38:55 -0500 Subject: Set relative url root in assets when controller isn't available for Sprockets. Fix #2435 See https://github.com/rails/sass-rails/issues/42 for details --- actionpack/CHANGELOG | 2 ++ actionpack/lib/sprockets/helpers/rails_helper.rb | 16 +++++++++++++--- actionpack/test/template/sprockets_helper_test.rb | 7 +++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index b757df6f22..d55064bf6d 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -48,6 +48,8 @@ *Rails 3.1.1 (unreleased)* +* Set relative url root in assets when controller isn't available for Sprockets (eg. Sass files using asset_path). Fixes #2435 [Guillermo Iguaran] + * Fixed the behavior of asset pipeline when config.assets.digest and config.assets.compile are false and requested asset isn't precompiled. Before the requested asset were compiled anyway ignoring that the config.assets.compile flag is false. [Guillermo Iguaran] diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 3987e6e17f..7d9296fa90 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -17,6 +17,7 @@ module Sprockets paths.asset_digests = asset_digests paths.compile_assets = compile_assets? paths.digest_assets = digest_assets? + paths.relative_url_root = config.action_controller.relative_url_root paths end end @@ -96,12 +97,17 @@ module Sprockets end class AssetPaths < ::ActionView::AssetPaths #:nodoc: - attr_accessor :asset_environment, :asset_prefix, :asset_digests, :compile_assets, :digest_assets + attr_accessor :asset_environment, :asset_prefix, :asset_digests, :compile_assets, + :digest_assets, :relative_url_root class AssetNotPrecompiledError < StandardError; end - def compute_public_path(source, dir, ext=nil, include_host=true, protocol=nil) - super(source, asset_prefix, ext, include_host, protocol) + def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil) + public_path = super(source, asset_prefix, ext, include_host, protocol) + if !is_uri?(public_path) && relative_url_root + public_path = rewrite_relative_url_root(public_path, relative_url_root) + end + public_path end # Return the filesystem path for the source @@ -149,6 +155,10 @@ module Sprockets source end end + + def relative_url_root + has_request? ? super : @relative_url_root + end end end end diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb index ae4cb1f0aa..105c641712 100644 --- a/actionpack/test/template/sprockets_helper_test.rb +++ b/actionpack/test/template/sprockets_helper_test.rb @@ -124,6 +124,13 @@ class SprocketsHelperTest < ActionView::TestCase asset_path("/images/logo.gif") end + test "asset path with relative url root when controller isn't present but relative_url_root is" do + @controller = nil + @config.action_controller.relative_url_root = "/collaboration/hieraki" + assert_equal "/collaboration/hieraki/images/logo.gif", + asset_path("/images/logo.gif") + end + test "javascript path" do assert_match %r{/assets/application-[0-9a-f]+.js}, asset_path(:application, "js") -- cgit v1.2.3 From 73e8dd189be11aa1440af7add3f044b12fb26565 Mon Sep 17 00:00:00 2001 From: Deepak Prasanna Date: Tue, 13 Sep 2011 11:59:40 +0530 Subject: fixed the failing generators_test --- railties/test/railties/generators_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/railties/generators_test.rb b/railties/test/railties/generators_test.rb index 1d4ba0e5b6..f8540d69d9 100644 --- a/railties/test/railties/generators_test.rb +++ b/railties/test/railties/generators_test.rb @@ -28,7 +28,7 @@ module RailtiesTests if File.exist?("#{environment}.rb") require_environment = "-r #{environment}" end - `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/bin/rails #{cmd}` + `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails #{cmd}` end def build_engine(is_mountable=false) -- cgit v1.2.3 From 5bad79d93011faae839a57edaa20195398ab5764 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 13 Sep 2011 00:27:29 -0700 Subject: always rewrite_relative_url_root --- actionpack/lib/action_view/asset_paths.rb | 2 +- actionpack/lib/sprockets/helpers/rails_helper.rb | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb index 1d968fc798..9c1c821f8f 100644 --- a/actionpack/lib/action_view/asset_paths.rb +++ b/actionpack/lib/action_view/asset_paths.rb @@ -27,7 +27,7 @@ module ActionView source = rewrite_extension(source, dir, ext) if ext source = rewrite_asset_path(source, dir) - source = rewrite_relative_url_root(source, relative_url_root) if has_request? + source = rewrite_relative_url_root(source, relative_url_root) source = rewrite_host_and_protocol(source, protocol) if include_host source end diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 7d9296fa90..f9135d43d2 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -103,11 +103,7 @@ module Sprockets class AssetNotPrecompiledError < StandardError; end def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil) - public_path = super(source, asset_prefix, ext, include_host, protocol) - if !is_uri?(public_path) && relative_url_root - public_path = rewrite_relative_url_root(public_path, relative_url_root) - end - public_path + super(source, asset_prefix, ext, include_host, protocol) end # Return the filesystem path for the source -- cgit v1.2.3 From e767cda6ea171cf888c8e46b0c62e3c7df801a38 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 13 Sep 2011 03:19:02 -0500 Subject: Move asset tests to assets_test file --- railties/test/application/assets_test.rb | 31 +++++++++++++++++++++++++++++++ railties/test/application/rake_test.rb | 31 ------------------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index b8a8665b3e..95fcb4a3dd 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require 'isolation/abstract_unit' require 'active_support/core_ext/kernel/reporting' require 'rack/test' @@ -268,6 +269,36 @@ module ApplicationTests assert_match(/\/assets\/rails-([0-z]+)\.png/, File.read(file)) end + test "precompile ignore asset_host" do + app_file "app/assets/javascripts/application.css.erb", "<%= asset_path 'rails.png' %>" + add_to_config "config.action_controller.asset_host = Proc.new { |source, request| 'http://www.example.com/' }" + + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + + file = Dir["#{app_path}/public/assets/application.css"].first + content = File.read(file) + assert_match(/\/assets\/rails-([0-z]+)\.png/, content) + assert_no_match(/www\.example\.com/, content) + end + + test "precompile should handle utf8 filenames" do + app_file "app/assets/images/レイルズ.png", "not a image really" + add_to_config "config.assets.precompile = [ /\.png$$/, /application.(css|js)$/ ]" + + capture(:stdout) do + Dir.chdir(app_path){ `bundle exec rake assets:precompile` } + end + + assert File.exists?("#{app_path}/public/assets/レイルズ.png") + + manifest = "#{app_path}/public/assets/manifest.yml" + + assets = YAML.load_file(manifest) + assert_equal "レイルズ.png", assets["レイルズ.png"] + end + test "assets are cleaned up properly" do app_file "public/assets/application.js", "alert();" app_file "public/assets/application.css", "a { color: green; }" diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 80fd65cd9f..c76bc3d526 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -201,36 +201,5 @@ module ApplicationTests assert_match(/7 tests, 10 assertions, 0 failures, 0 errors/, content) end - - def test_assets_precompile_with_utf8_filename - add_to_config <<-RUBY - config.assets.precompile = [ /\.png$$/, /application.(css|js)$/ ] - RUBY - - Dir.chdir(app_path) do - `cp app/assets/images/rails.png app/assets/images/レイルズ.png` - `rake assets:precompile` - open("public/assets/manifest.yml") do |f| - assert_match(/レイルズ.png/, f.read) - end - end - end - - def test_assets_precompile_ignore_asset_host - add_to_config <<-RUBY - config.action_controller.asset_host = Proc.new { |source, request| "http://www.example.com/" } - RUBY - - app_file "app/assets/javascripts/test.js.erb", <<-RUBY - alert("<%= asset_path "rails.png" %>"); - RUBY - - Dir.chdir(app_path) do - `rake assets:precompile` - open("public/assets/application.js") do |f| - assert_match(/\"\/assets\/rails.png\"/, f.read) - end - end - end end end -- cgit v1.2.3 From f509b6988b8902a83b9ae5c559d8860c87f2a4df Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 13 Sep 2011 04:27:30 -0500 Subject: Fix for relative url root in assets --- actionpack/lib/sprockets/helpers/rails_helper.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index f9135d43d2..5785da5124 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -17,7 +17,6 @@ module Sprockets paths.asset_digests = asset_digests paths.compile_assets = compile_assets? paths.digest_assets = digest_assets? - paths.relative_url_root = config.action_controller.relative_url_root paths end end @@ -97,8 +96,7 @@ module Sprockets end class AssetPaths < ::ActionView::AssetPaths #:nodoc: - attr_accessor :asset_environment, :asset_prefix, :asset_digests, :compile_assets, - :digest_assets, :relative_url_root + attr_accessor :asset_environment, :asset_prefix, :asset_digests, :compile_assets, :digest_assets class AssetNotPrecompiledError < StandardError; end @@ -153,7 +151,7 @@ module Sprockets end def relative_url_root - has_request? ? super : @relative_url_root + has_request? ? super : config.action_controller.relative_url_root end end end -- cgit v1.2.3 From a65010fddb00ceb9356f8ccb797405a86a1d8b9f Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 13 Sep 2011 04:35:12 -0500 Subject: Fix precompile asset_host test --- railties/test/application/assets_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 95fcb4a3dd..0901c6df3d 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -279,7 +279,7 @@ module ApplicationTests file = Dir["#{app_path}/public/assets/application.css"].first content = File.read(file) - assert_match(/\/assets\/rails-([0-z]+)\.png/, content) + assert_match(/\/assets\/rails.png/, content) assert_no_match(/www\.example\.com/, content) end -- cgit v1.2.3 From ae04fbfee961a7e6b90a3373dc305f100e50614f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 13 Sep 2011 02:45:05 -0700 Subject: Fix asset_path relative_url_root method --- actionpack/lib/action_view/asset_paths.rb | 8 +++++--- actionpack/lib/sprockets/helpers/rails_helper.rb | 4 ---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb index 9c1c821f8f..75164b8134 100644 --- a/actionpack/lib/action_view/asset_paths.rb +++ b/actionpack/lib/action_view/asset_paths.rb @@ -119,9 +119,11 @@ module ActionView end def relative_url_root - config = controller.config if controller.respond_to?(:config) - config ||= config.action_controller if config.action_controller.present? - config.relative_url_root + if config.action_controller.present? + config.action_controller.relative_url_root + else + config.relative_url_root + end end def asset_host_config diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 5785da5124..998f0bceb7 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -149,10 +149,6 @@ module Sprockets source end end - - def relative_url_root - has_request? ? super : config.action_controller.relative_url_root - end end end end -- cgit v1.2.3 From 317ad8cb62d10f77cf0692f0a123b4a3358629a5 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Tue, 13 Sep 2011 06:47:13 -0500 Subject: Fix typo --- railties/guides/source/rails_on_rack.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile index 818df0ffaf..735438b155 100644 --- a/railties/guides/source/rails_on_rack.textile +++ b/railties/guides/source/rails_on_rack.textile @@ -216,7 +216,7 @@ config.middleware.clear # config.ru -use MyOwnStackFromStratch +use MyOwnStackFromScratch run ActionController::Dispatcher.new -- cgit v1.2.3 From 7b22b0193002de14a4915f064acb4a7715c24059 Mon Sep 17 00:00:00 2001 From: 45north Date: Tue, 13 Sep 2011 15:25:46 +0300 Subject: Fixed markup error. --- railties/guides/source/initialization.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 9cc4dd5f04..8aabc3ae91 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -454,7 +454,7 @@ app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", TOPLEVEL_BINDING, config -The initialize method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run: +The +initialize+ method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run: require ::File.expand_path('../config/environment', __FILE__) -- cgit v1.2.3 From d3baa928312a13ddd550a527caa554a49267ce88 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Tue, 13 Sep 2011 18:46:34 +0530 Subject: delete stray backup files from guides sample app --- .../getting_started/app/views/home/index.html.erb~ | 2 - .../guides/code/getting_started/config/routes.rb~ | 60 ---------------------- 2 files changed, 62 deletions(-) delete mode 100644 railties/guides/code/getting_started/app/views/home/index.html.erb~ delete mode 100644 railties/guides/code/getting_started/config/routes.rb~ diff --git a/railties/guides/code/getting_started/app/views/home/index.html.erb~ b/railties/guides/code/getting_started/app/views/home/index.html.erb~ deleted file mode 100644 index 2085730c72..0000000000 --- a/railties/guides/code/getting_started/app/views/home/index.html.erb~ +++ /dev/null @@ -1,2 +0,0 @@ -

    Home#index

    -

    Find me in app/views/home/index.html.erb

    diff --git a/railties/guides/code/getting_started/config/routes.rb~ b/railties/guides/code/getting_started/config/routes.rb~ deleted file mode 100644 index 3d9628b55e..0000000000 --- a/railties/guides/code/getting_started/config/routes.rb~ +++ /dev/null @@ -1,60 +0,0 @@ -Blog::Application.routes.draw do - get "home/index" - - # The priority is based upon order of creation: - # first created -> highest priority. - - # Sample of regular route: - # match 'products/:id' => 'catalog#view' - # Keep in mind you can assign values other than :controller and :action - - # Sample of named route: - # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase - # This route can be invoked with purchase_url(:id => product.id) - - # Sample resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Sample resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Sample resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Sample resource route with more complex sub-resources - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', :on => :collection - # end - # end - - # Sample resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end - - # You can have the root of your site routed with "root" - # just remember to delete public/index.html. - # root :to => 'welcome#index' - - # See how all your routes lay out with "rake routes" - - # This is a legacy wild controller route that's not recommended for RESTful applications. - # Note: This route will make all actions in every controller accessible via GET requests. - # match ':controller(/:action(/:id(.:format)))' -end -- cgit v1.2.3 From 11870117c6d9231b79e8125218728423e9dff207 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 13 Sep 2011 19:09:01 +0100 Subject: Rename first_or_new to first_or_initialize. For consistency with find_or_initialize_by. Also remove first_or_build alias. --- activerecord/CHANGELOG | 8 +++++--- activerecord/lib/active_record/base.rb | 2 +- activerecord/lib/active_record/relation.rb | 3 +-- activerecord/test/cases/base_test.rb | 12 ++---------- activerecord/test/cases/relations_test.rb | 18 ++++++------------ 5 files changed, 15 insertions(+), 28 deletions(-) diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index e82906186e..563260dfd0 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -4,10 +4,12 @@ Wed Sep 7 15:25:02 2011 Aaron Patterson keys are per process id. * lib/active_record/connection_adapters/sqlite_adapter.rb: ditto -* Add first_or_create, first_or_create!, first_or_build and first_or_new methods to Active Record. This is a better approach over the old find_or_create_by dynamic methods because it's clearer which arguments are used to find the record and which are used to create it: +* Add first_or_create, first_or_create!, first_or_initialize methods to Active Record. This is a + better approach over the old find_or_create_by dynamic methods because it's clearer which + arguments are used to find the record and which are used to create it: + + User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson") - User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson", :hot => true) - [Andrés Mejía] * Support bulk change_table in mysql2 adapter, as well as the mysql one. [Jon Leighton] diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 92f80c6eaa..558b341c06 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -442,7 +442,7 @@ module ActiveRecord #:nodoc: class << self # Class methods delegate :find, :first, :first!, :last, :last!, :all, :exists?, :any?, :many?, :to => :scoped - delegate :first_or_create, :first_or_create!, :first_or_new, :first_or_build, :to => :scoped + delegate :first_or_create, :first_or_create!, :first_or_initialize, :to => :scoped delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, :to => :scoped delegate :find_each, :find_in_batches, :to => :scoped delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index d3f1347e03..ecefaa633c 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -132,10 +132,9 @@ module ActiveRecord # Like first_or_create but calls new instead of create. # # Expects arguments in the same format as Base.new. - def first_or_new(attributes = nil, options = {}, &block) + def first_or_initialize(attributes = nil, options = {}, &block) first || new(attributes, options, &block) end - alias :first_or_build :first_or_new def respond_to?(method, include_private = false) arel.respond_to?(method, include_private) || diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index cb92f79e0e..12c1cfb30e 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -294,16 +294,8 @@ class BasicsTest < ActiveRecord::TestCase assert_equal parrot, the_same_parrot end - def test_first_or_new - parrot = Bird.first_or_new(:color => 'green', :name => 'parrot') - assert_kind_of Bird, parrot - assert !parrot.persisted? - assert parrot.new_record? - assert parrot.valid? - end - - def test_first_or_build - parrot = Bird.first_or_build(:color => 'green', :name => 'parrot') + def test_first_or_initialize + parrot = Bird.first_or_initialize(:color => 'green', :name => 'parrot') assert_kind_of Bird, parrot assert !parrot.persisted? assert parrot.new_record? diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 0f50ac9a2b..95408a5f29 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -956,8 +956,8 @@ class RelationTest < ActiveRecord::TestCase assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!([ {:name => 'parrot'}, {:pirate_id => 1} ]) } end - def test_first_or_new - parrot = Bird.where(:color => 'green').first_or_new(:name => 'parrot') + def test_first_or_initialize + parrot = Bird.where(:color => 'green').first_or_initialize(:name => 'parrot') assert_kind_of Bird, parrot assert !parrot.persisted? assert parrot.valid? @@ -966,8 +966,8 @@ class RelationTest < ActiveRecord::TestCase assert_equal 'green', parrot.color end - def test_first_or_new_with_no_parameters - parrot = Bird.where(:color => 'green').first_or_new + def test_first_or_initialize_with_no_parameters + parrot = Bird.where(:color => 'green').first_or_initialize assert_kind_of Bird, parrot assert !parrot.persisted? assert !parrot.valid? @@ -975,8 +975,8 @@ class RelationTest < ActiveRecord::TestCase assert_equal 'green', parrot.color end - def test_first_or_new_with_block - parrot = Bird.where(:color => 'green').first_or_new { |bird| bird.name = 'parrot' } + def test_first_or_initialize_with_block + parrot = Bird.where(:color => 'green').first_or_initialize { |bird| bird.name = 'parrot' } assert_kind_of Bird, parrot assert !parrot.persisted? assert parrot.valid? @@ -985,12 +985,6 @@ class RelationTest < ActiveRecord::TestCase assert_equal 'parrot', parrot.name end - def test_first_or_build_is_alias_for_first_or_new - birds = Bird.scoped - assert birds.respond_to?(:first_or_build) - assert_equal birds.method(:first_or_new), birds.method(:first_or_build) - end - def test_explicit_create_scope hens = Bird.where(:name => 'hen') assert_equal 'hen', hens.new.name -- cgit v1.2.3 From 3777d4217b58bbb20a7301521f5451b5f55af78d Mon Sep 17 00:00:00 2001 From: Erik Behrends Date: Tue, 13 Sep 2011 22:42:39 +0300 Subject: [:class_name] option in belongs_to should mention belongs_to and not has_one --- activerecord/lib/active_record/associations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 8d755b6848..9e7d609d19 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1329,7 +1329,7 @@ module ActiveRecord # # [:class_name] # Specify the class name of the association. Use it only if that name can't be inferred - # from the association name. So has_one :author will by default be linked to the Author class, but + # from the association name. So belongs_to :author will by default be linked to the Author class, but # if the real class name is Person, you'll have to specify it with this option. # [:conditions] # Specify the conditions that the associated object must meet in order to be included as a +WHERE+ -- cgit v1.2.3 From bde113a82e792ef3480d686a1e66fea56c76c46d Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Wed, 14 Sep 2011 00:09:59 +0200 Subject: Fix typos and broken link on asset pipeline guide --- railties/guides/source/asset_pipeline.textile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 211b02b94b..31a1aeee15 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -63,7 +63,7 @@ This has several disadvantages:
    1. Not all caches will cache content with a query string
      - "Steve Souders recommends":http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/, "...avoiding a querystring for cacheable resources". He found that in these case 5-20% of requests will not be cached. + "Steve Souders recommends":http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/, "...avoiding a querystring for cacheable resources". He found that in this case 5-20% of requests will not be cached.
    2. The file name can change between nodes in multi-server environments.
      @@ -132,7 +132,7 @@ In regular views you can access images in the +assets/images+ directory like thi Provided that the pipeline is enabled within your application (and not disabled in the current environment context), this file is served by Sprockets. If a file exists at +public/assets/rails.png+ it is served by the webserver. -Alternatively, a request for a file with an MD5 hash such as +public/assets/rails-af27b6a414e6da00003503148be9b409.png+ is treated the same way. How these hashes are generated is covered in the "Production Assets":#production_assets section later on in this guide. +Alternatively, a request for a file with an MD5 hash such as +public/assets/rails-af27b6a414e6da00003503148be9b409.png+ is treated the same way. How these hashes are generated is covered in the "In Production":#in-production section later on in this guide. Sprockets will also look through the paths specified in +config.assets.paths+ which includes the standard application paths and any path added by Rails engines. @@ -537,7 +537,7 @@ WARNING: If you are upgrading an existing application and intend to use this opt h3. How Caching Works -Sprockets uses the default rails cache store to cache assets in development and production. +Sprockets uses the default Rails cache store to cache assets in development and production. TODO: Add more about changing the default store. -- cgit v1.2.3 From 82afaa06861d03f6a2887d40e40c0ded76db88db Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 13 Sep 2011 15:16:53 -0700 Subject: Provide a way to access to assets without using the digest, useful for static files and emails --- actionpack/lib/sprockets/assets.rake | 1 + railties/CHANGELOG | 3 +++ railties/test/application/assets_test.rb | 2 ++ 3 files changed, 6 insertions(+) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 0531b1509b..ee8ca1b3dd 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -43,6 +43,7 @@ namespace :assets do mkdir_p filename.dirname asset.write_to(filename) asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/ + asset.write_to(target.join(logical_path)) end end end diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 6ed76974b4..9ba93d6130 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -12,6 +12,9 @@ *Rails 3.1.0 (unreleased)* +* Provide a way to access to assets without using the digest, useful for +static files and emails. [Santiago Pastorino] + * The default database schema file is written as UTF-8. [Aaron Patterson] * Generated apps with --dev or --edge flags depend on git versions of diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 0901c6df3d..9245532e17 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -58,7 +58,9 @@ module ApplicationTests Dir.chdir(app_path){ `bundle exec rake assets:precompile` } end files = Dir["#{app_path}/public/assets/application-*.js"] + files << Dir["#{app_path}/public/assets/application.js"].first files << Dir["#{app_path}/public/assets/foo/application-*.js"].first + files << Dir["#{app_path}/public/assets/foo/application.js"].first files.each do |file| assert_not_nil file, "Expected application.js asset to be generated, but none found" assert_equal "alert()", File.read(file) -- cgit v1.2.3 From 55da28dd2fa734de256a13fb09469eaa3ab15599 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 13 Sep 2011 23:23:29 +0100 Subject: We don't need to build a set for DangerousAttributeError. We can just use method_defined? and private_method_defined? --- activerecord/lib/active_record/attribute_methods.rb | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index dc6dc2e63a..0b074da0a5 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -42,23 +42,29 @@ module ActiveRecord # that also derive from Active Record. Raises DangerousAttributeError if the # method is defined by Active Record though. def instance_method_already_implemented?(method_name) + if dangerous_attribute_method?(method_name) + raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" + end + method_name = method_name.to_s index = ancestors.index(ActiveRecord::Base) || ancestors.length @_defined_class_methods ||= ancestors.first(index).map { |m| m.instance_methods(false) | m.private_instance_methods(false) }.flatten.map {|m| m.to_s }.to_set - @@_defined_activerecord_methods ||= defined_activerecord_methods - raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" if @@_defined_activerecord_methods.include?(method_name) @_defined_class_methods.include?(method_name) || generated_attribute_methods.method_defined?(method_name) end - def defined_activerecord_methods + # A method name is 'dangerous' if it is already defined by Active Record, but + # not by any ancestors. (So 'puts' is not dangerous but 'save' is.) + def dangerous_attribute_method?(method_name) active_record = ActiveRecord::Base - super_klass = ActiveRecord::Base.superclass - methods = (active_record.instance_methods - super_klass.instance_methods) + - (active_record.private_instance_methods - super_klass.private_instance_methods) - methods.map {|m| m.to_s }.to_set + superclass = ActiveRecord::Base.superclass + + (active_record.method_defined?(method_name) || + active_record.private_method_defined?(method_name)) && + !superclass.method_defined?(method_name) && + !superclass.private_method_defined?(method_name) end end -- cgit v1.2.3 From 778c82bea69eb15908a8bb77999ceac0a749242d Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 13 Sep 2011 23:46:43 +0100 Subject: Generate attribute method unless it's already in the module. There's no harm in generating a method name that's already defined on the host class, since we're generating the attribute methods in a module that gets included. In fact, this is desirable as it allows the host class to call super. --- activemodel/lib/active_model/attribute_methods.rb | 2 +- activemodel/test/cases/attribute_methods_test.rb | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 539e0bbdda..a201e983cd 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -329,7 +329,7 @@ module ActiveModel protected def instance_method_already_implemented?(method_name) - method_defined?(method_name) + generated_attribute_methods.method_defined?(method_name) end private diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb index e655c7a1af..67471ed497 100644 --- a/activemodel/test/cases/attribute_methods_test.rb +++ b/activemodel/test/cases/attribute_methods_test.rb @@ -89,6 +89,29 @@ class AttributeMethodsTest < ActiveModel::TestCase assert_equal "value of foo", ModelWithAttributes.new.foo end + test '#define_attribute_method does not generate attribute method if already defined in attribute module' do + klass = Class.new(ModelWithAttributes) + klass.generated_attribute_methods.module_eval do + def foo + '<3' + end + end + klass.define_attribute_method(:foo) + + assert_equal '<3', klass.new.foo + end + + test '#define_attribute_method generates a method that is already defined on the host' do + klass = Class.new(ModelWithAttributes) do + def foo + super + end + end + klass.define_attribute_method(:foo) + + assert_equal 'value of foo', klass.new.foo + end + test '#define_attribute_method generates attribute method with invalid identifier characters' do ModelWithWeirdNamesAttributes.define_attribute_method(:'a?b') -- cgit v1.2.3 From 3b8a7cf2a7b2ffce671ca7f655de736c1054edbc Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 13 Sep 2011 23:52:38 +0100 Subject: Stop trying to be clever about when to define attribute methods. There is no meaningful performance penalty in defining attribute methods, since it only happens once. There is also no reason *not* to define them, since they get thrown in an included module, so they will not 'overwrite' anything. In fact, this is desirable, since it allows us to call super. --- .../lib/active_record/attribute_methods.rb | 11 +--------- activerecord/test/cases/attribute_methods_test.rb | 24 ---------------------- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 0b074da0a5..d7bfaa5655 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -38,21 +38,12 @@ module ActiveRecord end end - # Checks whether the method is defined in the model or any of its subclasses - # that also derive from Active Record. Raises DangerousAttributeError if the - # method is defined by Active Record though. def instance_method_already_implemented?(method_name) if dangerous_attribute_method?(method_name) raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" end - method_name = method_name.to_s - index = ancestors.index(ActiveRecord::Base) || ancestors.length - @_defined_class_methods ||= ancestors.first(index).map { |m| - m.instance_methods(false) | m.private_instance_methods(false) - }.flatten.map {|m| m.to_s }.to_set - - @_defined_class_methods.include?(method_name) || generated_attribute_methods.method_defined?(method_name) + super end # A method name is 'dangerous' if it is already defined by Active Record, but diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index e324a252dd..b1b41fed0d 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -431,30 +431,6 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert topic.is_test? end - def test_kernel_methods_not_implemented_in_activerecord - %w(test name display y).each do |method| - assert !ActiveRecord::Base.instance_method_already_implemented?(method), "##{method} is defined" - end - end - - def test_defined_kernel_methods_implemented_in_model - %w(test name display y).each do |method| - klass = Class.new ActiveRecord::Base - klass.class_eval "def #{method}() 'defined #{method}' end" - assert klass.instance_method_already_implemented?(method), "##{method} is not defined" - end - end - - def test_defined_kernel_methods_implemented_in_model_abstract_subclass - %w(test name display y).each do |method| - abstract = Class.new ActiveRecord::Base - abstract.class_eval "def #{method}() 'defined #{method}' end" - abstract.abstract_class = true - klass = Class.new abstract - assert klass.instance_method_already_implemented?(method), "##{method} is not defined" - end - end - def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model %w(save create_or_update).each do |method| klass = Class.new ActiveRecord::Base -- cgit v1.2.3 From f22407dd34024886edd8a8f618dc0b19152776a0 Mon Sep 17 00:00:00 2001 From: "Mark J. Titorenko" Date: Tue, 6 Sep 2011 10:34:24 +0100 Subject: Don't mount Sprockets at config.assets.prefix if config.assets.compile is false. --- actionpack/lib/sprockets/railtie.rb | 6 ++++-- railties/test/application/assets_test.rb | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb index dc991636a1..f05d835554 100644 --- a/actionpack/lib/sprockets/railtie.rb +++ b/actionpack/lib/sprockets/railtie.rb @@ -67,8 +67,10 @@ module Sprockets end end - app.routes.prepend do - mount app.assets => config.assets.prefix + if config.assets.compile + app.routes.prepend do + mount app.assets => config.assets.prefix + end end if config.assets.digest diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 9245532e17..0c40b88cf9 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -178,6 +178,7 @@ module ApplicationTests test "assets do not require any assets group gem when manifest file is present" do app_file "app/assets/javascripts/application.js", "alert();" + app_file "config/initializers/serve_static_assets.rb", "Rails.application.config.serve_static_assets = true" ENV["RAILS_ENV"] = "production" capture(:stdout) do @@ -314,6 +315,17 @@ module ApplicationTests assert_equal 0, files.length, "Expected no assets, but found #{files.join(', ')}" end + test "assets routes are not drawn when compilation is disabled" do + app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" + app_file "config/initializers/compile.rb", "Rails.application.config.assets.compile = false" + + ENV["RAILS_ENV"] = "production" + require "#{app_path}/config/environment" + + get "/assets/demo.js" + assert_equal 404, last_response.status + end + test "does not stream session cookies back" do app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" -- cgit v1.2.3 From a89d39ec889c2658120e508bd182de7be3ccdcc9 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 13 Sep 2011 18:36:38 -0500 Subject: Fix broken asset test --- railties/test/application/assets_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 0c40b88cf9..9b141ccbac 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -38,7 +38,7 @@ module ApplicationTests test "assets do not require compressors until it is used" do app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" - add_to_config "config.assets.compile = true" + app_file "config/initializers/compile.rb", "Rails.application.config.assets.compile = true" ENV["RAILS_ENV"] = "production" require "#{app_path}/config/environment" @@ -317,7 +317,7 @@ module ApplicationTests test "assets routes are not drawn when compilation is disabled" do app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" - app_file "config/initializers/compile.rb", "Rails.application.config.assets.compile = false" + add_to_config "config.assets.compile = false" ENV["RAILS_ENV"] = "production" require "#{app_path}/config/environment" -- cgit v1.2.3 From 681c4dbb0222ac403de8ea0bfcf8ad77c5430585 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 14 Sep 2011 09:43:31 +1000 Subject: Add documentation for the extending method in ActiveRecord:QueryMethods --- .../lib/active_record/relation/query_methods.rb | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 7eda9ad8e8..8dc59583c1 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -147,6 +147,42 @@ module ActiveRecord relation end + # Used to extend a scope with additional methods, either through + # a module or through a block provided. + # + # The object returned is a relation, which can be further extended. + # + # === Using a module + # + # module Pagination + # def page(number) + # # pagination code goes here + # end + # end + # + # scope = Model.scoped.extending(Pagination) + # scope.page(params[:page]) + # + # This can also take a list of modules also: + # + # scope = Model.scoped.extending(Pagination, SomethingElse) + # + # === Using a block + # + # scope = Model.scoped.extending do + # def page(number) + # # pagination code goes here + # end + # end + # scope.page(params[:page]) + # + # You can also use a block and a module list: + # + # scope = Model.scoped.extending(Pagination) do + # def per_page(number) + # # pagination code goes here + # end + # end def extending(*modules) modules << Module.new(&Proc.new) if block_given? -- cgit v1.2.3 From fae70cb6bcfa3fbe7c850c7aeab2b40435926793 Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 13 Sep 2011 19:40:47 -0500 Subject: Add missing changelog entries for actionpack --- actionpack/CHANGELOG | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index d55064bf6d..d01422b314 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -48,8 +48,12 @@ *Rails 3.1.1 (unreleased)* +* Don't mount Sprockets server at config.assets.prefix if config.assets.compile is false. [Mark J. Titorenko] + * Set relative url root in assets when controller isn't available for Sprockets (eg. Sass files using asset_path). Fixes #2435 [Guillermo Iguaran] +* Fix basic auth credential generation to not make newlines. GH #2882 + * Fixed the behavior of asset pipeline when config.assets.digest and config.assets.compile are false and requested asset isn't precompiled. Before the requested asset were compiled anyway ignoring that the config.assets.compile flag is false. [Guillermo Iguaran] -- cgit v1.2.3 From 9c7e8850073fdefa17367b8fec256257c31559bc Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 13 Sep 2011 22:05:46 -0500 Subject: Clear cache before of each precompile to avoid inconsistencies. Fixes #3014 --- actionpack/lib/sprockets/assets.rake | 1 + 1 file changed, 1 insertion(+) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index ee8ca1b3dd..b7e8f39b43 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -9,6 +9,7 @@ namespace :assets do Kernel.exec $0, *ARGV else Rake::Task["environment"].invoke + Rake::Task["tmp:cache:clear"].invoke # Ensure that action view is loaded and the appropriate sprockets hooks get executed ActionView::Base -- cgit v1.2.3 From b3ff720567b41ca5db9e6956c37cc0792b7a3f4e Mon Sep 17 00:00:00 2001 From: Ben Walding Date: Wed, 14 Sep 2011 15:27:38 +1000 Subject: Add equivalent nginx configuration --- railties/guides/source/asset_pipeline.textile | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 31a1aeee15..ce4eafb97c 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -403,7 +403,21 @@ For Apache: -TODO: nginx instructions +For nginx: + + +location ~ ^/assets/ { + expires 1y; + add_header Cache-Control public; + + # Some browsers still send conditional-GET requests if there's a + # Last-Modified header or an ETag header even if they haven't + # reached the expiry date sent in the Expires header. + add_header Last-Modified ""; + add_header ETag ""; + break; +} + When files are precompiled, Sprockets also creates a "Gzip":http://en.wikipedia.org/wiki/Gzip (.gz) version of your assets. This avoids the server having to do this for any requests; it can simply read the compressed files from disk. You must configure your server to use gzip compression and serve the compressed assets that will be stored in the +public/assets+ folder. The following configuration options can be used: -- cgit v1.2.3 From 0d48b3afa98375cf71ea0ad731eaac6c309fbb57 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 14 Sep 2011 00:29:03 -0700 Subject: Revert "Provide a way to access to assets without using the digest, useful for static files and emails" This reverts commit 82afaa06861d03f6a2887d40e40c0ded76db88db. --- actionpack/lib/sprockets/assets.rake | 1 - railties/CHANGELOG | 3 --- railties/test/application/assets_test.rb | 2 -- 3 files changed, 6 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index ee8ca1b3dd..0531b1509b 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -43,7 +43,6 @@ namespace :assets do mkdir_p filename.dirname asset.write_to(filename) asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/ - asset.write_to(target.join(logical_path)) end end end diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 9ba93d6130..6ed76974b4 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -12,9 +12,6 @@ *Rails 3.1.0 (unreleased)* -* Provide a way to access to assets without using the digest, useful for -static files and emails. [Santiago Pastorino] - * The default database schema file is written as UTF-8. [Aaron Patterson] * Generated apps with --dev or --edge flags depend on git versions of diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 9b141ccbac..959914bcea 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -58,9 +58,7 @@ module ApplicationTests Dir.chdir(app_path){ `bundle exec rake assets:precompile` } end files = Dir["#{app_path}/public/assets/application-*.js"] - files << Dir["#{app_path}/public/assets/application.js"].first files << Dir["#{app_path}/public/assets/foo/application-*.js"].first - files << Dir["#{app_path}/public/assets/foo/application.js"].first files.each do |file| assert_not_nil file, "Expected application.js asset to be generated, but none found" assert_equal "alert()", File.read(file) -- cgit v1.2.3 From 7302e1cdf22951db1a4cbad45bf116db1be0eebb Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 14 Sep 2011 19:02:08 +0530 Subject: remove info about guides hackfest --- railties/guides/source/index.html.erb | 1 - 1 file changed, 1 deletion(-) diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb index 214155c088..c9a8c4fa5c 100644 --- a/railties/guides/source/index.html.erb +++ b/railties/guides/source/index.html.erb @@ -30,7 +30,6 @@ Ruby on Rails Guides <% content_for :index_section do %>
      -
      Rails Guides are a result of the ongoing Guides hackfest, and a work in progress.
      Guides marked with this icon are currently being worked on. While they might still be useful to you, they may contain incomplete information and even errors. You can help by reviewing them and posting your comments and corrections to the author.
      -- cgit v1.2.3 From c7835c51618a6a46d1b5ec63dfaf2d99e157da42 Mon Sep 17 00:00:00 2001 From: Dallas Reedy Date: Tue, 13 Sep 2011 16:32:43 -0700 Subject: Removed mention of deprecated proxy methods in favor of using proxy_association. --- railties/guides/source/association_basics.textile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile index ce4ff0389d..0439b6ac4d 100644 --- a/railties/guides/source/association_basics.textile +++ b/railties/guides/source/association_basics.textile @@ -1855,14 +1855,15 @@ class Customer < ActiveRecord::Base end -Extensions can refer to the internals of the association proxy using these three accessors: +Extensions can refer to the internals of the association proxy using these three attributes of the +proxy_association+ accessor: -* +proxy_owner+ returns the object that the association is a part of. -* +proxy_reflection+ returns the reflection object that describes the association. -* +proxy_target+ returns the associated object for +belongs_to+ or +has_one+, or the collection of associated objects for +has_many+ or +has_and_belongs_to_many+. +* +proxy_association.owner+ returns the object that the association is a part of. +* +proxy_association.reflection+ returns the reflection object that describes the association. +* +proxy_association.target+ returns the associated object for +belongs_to+ or +has_one+, or the collection of associated objects for +has_many+ or +has_and_belongs_to_many+. h3. Changelog +* September 13, 2011: Removed mention of deprecated proxy methods in favor of using +proxy_association+. * April 7, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com * April 19, 2009: Added +:touch+ option to +belongs_to+ associations by "Mike Gunderloy":credits.html#mgunderloy * February 1, 2009: Added +:autosave+ option "Mike Gunderloy":credits.html#mgunderloy -- cgit v1.2.3 From bc058509a884e81b9099072073e372e1ad9b932b Mon Sep 17 00:00:00 2001 From: Dallas Reedy Date: Wed, 14 Sep 2011 09:32:27 -0700 Subject: forgot to sign my name to the Changelog --- railties/guides/source/association_basics.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile index 0439b6ac4d..479693dbf8 100644 --- a/railties/guides/source/association_basics.textile +++ b/railties/guides/source/association_basics.textile @@ -1863,7 +1863,7 @@ Extensions can refer to the internals of the association proxy using these three h3. Changelog -* September 13, 2011: Removed mention of deprecated proxy methods in favor of using +proxy_association+. +* September 13, 2011: Removed mention of deprecated proxy methods in favor of using +proxy_association+. "Dallas Reedy":https://github.com/dallas * April 7, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com * April 19, 2009: Added +:touch+ option to +belongs_to+ associations by "Mike Gunderloy":credits.html#mgunderloy * February 1, 2009: Added +:autosave+ option "Mike Gunderloy":credits.html#mgunderloy -- cgit v1.2.3 From 823e16f57cb64c8557aa8e06b07e361d625a6e2e Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 14 Sep 2011 22:46:12 +0530 Subject: update 3.1 release date in changelogs --- actionmailer/CHANGELOG | 2 +- activemodel/CHANGELOG | 2 +- activerecord/CHANGELOG | 2 +- activeresource/CHANGELOG | 2 +- activesupport/CHANGELOG | 2 +- railties/CHANGELOG | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/actionmailer/CHANGELOG b/actionmailer/CHANGELOG index d4475bc951..14c887eb53 100644 --- a/actionmailer/CHANGELOG +++ b/actionmailer/CHANGELOG @@ -1,4 +1,4 @@ -*Rails 3.1.0 (unreleased)* +*Rails 3.1.0 (August 30, 2011)* * No changes diff --git a/activemodel/CHANGELOG b/activemodel/CHANGELOG index 20e5816532..3d26d646b0 100644 --- a/activemodel/CHANGELOG +++ b/activemodel/CHANGELOG @@ -4,7 +4,7 @@ * Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior [Bogdan Gusiev] -*Rails 3.1.0 (unreleased)* +*Rails 3.1.0 (August 30, 2011)* * Alternate I18n namespace lookup is no longer supported. Instead of "activerecord.models.admins.post", do "activerecord.models.admins/post" instead [José Valim] diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 563260dfd0..a54526dd41 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -36,7 +36,7 @@ a URI that specifies the connection configuration. For example: [Prem Sichanugrist] -*Rails 3.1.0 (unreleased)* +*Rails 3.1.0 (August 30, 2011)* * Add a proxy_association method to association proxies, which can be called by association extensions to access information about the association. This replaces proxy_owner etc with diff --git a/activeresource/CHANGELOG b/activeresource/CHANGELOG index 25f9242b98..fe356d7691 100644 --- a/activeresource/CHANGELOG +++ b/activeresource/CHANGELOG @@ -1,4 +1,4 @@ -*Rails 3.1.0 (unreleased)* +*Rails 3.1.0 (August 30, 2011)* * The default format has been changed to JSON for all requests. If you want to continue to use XML you will need to set `self.format = :xml` in the class. eg. diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 18164234a5..537980d6a1 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -20,7 +20,7 @@ Also, in 1.8 the ideographic space U+3000 is considered to be whitespace. [Akira * ActiveSupport::OrderedHash now has different behavior for #each and #each_pair when given a block accepting its parameters with a splat. [Andrew Radev] -*Rails 3.1.0 (unreleased)* +*Rails 3.1.0 (August 30, 2011)* * ActiveSupport::Dependencies#load and ActiveSupport::Dependencies#require now return the value from `super` [Aaron Patterson] diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 6ed76974b4..72e5921d6d 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -10,7 +10,7 @@ * Removed old 'config.paths.app.controller' API in favor of 'config.paths["app/controller"]' API. [Guillermo Iguaran] -*Rails 3.1.0 (unreleased)* +*Rails 3.1.0 (August 30, 2011)* * The default database schema file is written as UTF-8. [Aaron Patterson] -- cgit v1.2.3 From 5e1285dfb3148f89ae644bdf4522115ae4c8144f Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 14 Sep 2011 23:05:29 +0530 Subject: change first_or_new to first_or_initialize as per 11870117, and some edits --- .../guides/source/active_record_querying.textile | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 7a853db813..ac8c15f60d 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -1042,20 +1042,26 @@ INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) V COMMIT -+first_or_create+ returns either the record that already existed or the new record. In our case, we didn't already have a client named Andy so the record was created an returned. ++first_or_create+ returns either the record that already exists or the new record. In our case, we didn't already have a client named Andy so the record is created and returned. The new record might not be saved to the database; that depends on whether validations passed or not (just like +create+). It's also worth noting that +first_or_create+ takes into account the arguments of the +where+ method. In the example above we didn't explicitly pass a +:first_name => 'Andy'+ argument to +first_or_create+. However, that was used when creating the new record because it was already passed before to the +where+ method. -NOTE: On previous versions of Rails you could do a similar thing with the +find_or_create_by+ method. Following our example, you could also run something like +Client.find_or_create_by_first_name(:first_name => "Andy", :locked => false)+. This method still works, but it's encouraged to use +first_or_create+ because it's more explicit on what arguments are used to _find_ the record and what arguments are used to _create_ it, resulting in less confusion overall. +You can do the same with the +find_or_create_by+ method: + + +Client.find_or_create_by_first_name(:first_name => "Andy", :locked => false) + + +This method still works, but it's encouraged to use +first_or_create+ because it's more explicit on which arguments are used to _find_ the record and which are used to _create_, resulting in less confusion overall. h4. +first_or_create!+ You can also use +first_or_create!+ to raise an exception if the new record is invalid. Validations are not covered on this guide, but let's assume for a moment that you temporarily add - validates :orders_count, :presence => true +validates :orders_count, :presence => true to your +Client+ model. If you try to create a new +Client+ without passing an +orders_count+, the record will be invalid and an exception will be raised: @@ -1065,14 +1071,12 @@ Client.where(:first_name => 'Andy').first_or_create!(:locked => false) # => ActiveRecord::RecordInvalid: Validation failed: Orders count can't be blank -NOTE: Be sure to check the extensive *Active Record Validations and Callbacks Guide* for more information about validations. - -h4. +first_or_new+ +h4. +first_or_initialize+ -The +first_or_new+ method will work just like +first_or_create+ but it will not call +create+ but +new+. This means that a new model instance will be created in memory but won't be saved to the database. Continuing with the +first_or_create+ example, we now want the client named 'Nick': +The +first_or_initialize+ method will work just like +first_or_create+ but it will not call +create+ but +new+. This means that a new model instance will be created in memory but won't be saved to the database. Continuing with the +first_or_create+ example, we now want the client named 'Nick': -nick = Client.where(:first_name => 'Nick').first_or_new(:locked => false) +nick = Client.where(:first_name => 'Nick').first_or_initialize(:locked => false) # => nick.persisted? @@ -1095,8 +1099,6 @@ nick.save # => true -Just like you can use *+build+* instead of *+new+*, you can use *+first_or_build+* instead of *+first_or_new+*. - h3. Finding by SQL If you'd like to use your own SQL to find records in a table you can use +find_by_sql+. The +find_by_sql+ method will return an array of objects even if the underlying query returns just a single record. For example you could run this query: -- cgit v1.2.3 From dcd70773fc66f84555cf55de0c0c2b8cd8ae8cc1 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 14 Sep 2011 23:15:18 +0530 Subject: minor edit --- activerecord/lib/active_record/relation/query_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 8dc59583c1..a11b7a3864 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -163,7 +163,7 @@ module ActiveRecord # scope = Model.scoped.extending(Pagination) # scope.page(params[:page]) # - # This can also take a list of modules also: + # You can also pass a list of modules: # # scope = Model.scoped.extending(Pagination, SomethingElse) # -- cgit v1.2.3 From 5f2a35604e8180c916796abc93189bd1e0f7987f Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 14 Sep 2011 23:39:55 +0530 Subject: Mention that old fixes are to be done on 3-0-stable --- railties/guides/source/contributing_to_ruby_on_rails.textile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile index 90eab150a1..86e31d79ee 100644 --- a/railties/guides/source/contributing_to_ruby_on_rails.textile +++ b/railties/guides/source/contributing_to_ruby_on_rails.textile @@ -200,11 +200,11 @@ You can also invoke +test_jdbcmysql+, +test_jdbcsqlite3+ or +test_jdbcpostgresql h4. Older versions of Ruby on Rails -If you want to add a fix to older versions of Ruby on Rails, you'll need to set up and switch to your own local tracking branch. Here is an example to switch to the 2-3-stable branch: +If you want to add a fix to older versions of Ruby on Rails, you'll need to set up and switch to your own local tracking branch. Here is an example to switch to the 3-0-stable branch: -$ git branch --track 2-3-stable origin/2-3-stable -$ git checkout 2-3-stable +$ git branch --track 3-0-stable origin/3-0-stable +$ git checkout 3-0-stable TIP: You may want to "put your git branch name in your shell prompt":http://qugstart.com/blog/git-and-svn/add-colored-git-branch-name-to-your-shell-prompt/ to make it easier to remember which version of the code you're working with. -- cgit v1.2.3 From 9980f46ca2d250d1d3e2fac84c5dc9ca6cbab1ea Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Thu, 15 Sep 2011 00:13:29 +0530 Subject: No more changelogs inside guides --- .../source/action_controller_overview.textile | 6 ------ railties/guides/source/action_mailer_basics.textile | 5 ----- railties/guides/source/action_view_overview.textile | 7 ------- railties/guides/source/active_model_basics.textile | 5 ----- .../guides/source/active_record_querying.textile | 9 --------- .../active_record_validations_callbacks.textile | 11 ----------- .../guides/source/active_resource_basics.textile | 4 ---- .../source/active_support_core_extensions.textile | 5 ----- .../source/api_documentation_guidelines.textile | 4 ---- railties/guides/source/association_basics.textile | 10 ---------- railties/guides/source/caching_with_rails.textile | 11 ----------- railties/guides/source/configuring.textile | 8 -------- .../source/contributing_to_ruby_on_rails.textile | 10 ---------- .../source/debugging_rails_applications.textile | 7 ------- railties/guides/source/form_helpers.textile | 10 ---------- railties/guides/source/generators.textile | 11 ----------- railties/guides/source/getting_started.textile | 21 --------------------- .../guides/source/layouts_and_rendering.textile | 12 ------------ railties/guides/source/migrations.textile | 6 ------ railties/guides/source/performance_testing.textile | 6 ------ railties/guides/source/plugins.textile | 8 -------- .../source/rails_application_templates.textile | 4 ---- railties/guides/source/rails_on_rack.textile | 5 ----- railties/guides/source/routing.textile | 9 --------- .../source/ruby_on_rails_guides_guidelines.textile | 5 ----- railties/guides/source/security.textile | 4 ---- railties/guides/source/testing.textile | 8 -------- 27 files changed, 211 deletions(-) diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile index 4e47712636..d8d66302fe 100644 --- a/railties/guides/source/action_controller_overview.textile +++ b/railties/guides/source/action_controller_overview.textile @@ -815,9 +815,3 @@ end Please note that if you found yourself adding +force_ssl+ to many controllers, you may found yourself wanting to force the whole application to use HTTPS instead. In that case, you can set the +config.force_ssl+ in your environment file. - -h3. Changelog - -* February 17, 2009: Yet another proofread by Xavier Noria. - -* November 4, 2008: First release version by Tore Darell diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile index 67761645fa..ad5b848d2c 100644 --- a/railties/guides/source/action_mailer_basics.textile +++ b/railties/guides/source/action_mailer_basics.textile @@ -521,8 +521,3 @@ end In the test we send the email and store the returned object in the +email+ variable. We then ensure that it was sent (the first assert), then, in the second batch of assertions, we ensure that the email does indeed contain what we expect. - -h3. Changelog - -* September 1, 2011: Changed the lines that said config/environments/env.rb to config/environments/$RAILS_ENV.rb. People were mis-interpreting the filename to literally be env.rb. "Andy Leeper":http://mochaleaf.com -* September 30, 2010: Fixed typos and reformatted Action Mailer configuration table for better understanding. "Jaime Iniesta":http://jaimeiniesta.com diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index edaaeb8543..87250c684b 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -1495,10 +1495,3 @@ end Then you could create special views like +app/views/posts/show.expert.html.erb+ that would only be displayed to expert users. You can read more about the Rails Internationalization (I18n) API "here":i18n.html. - -h3. Changelog - -* May 29, 2011: Removed references to remote_* helpers - Vijay Dev -* April 16, 2011: Added 'Using Action View with Rails', 'Templates' and 'Partials' sections. "Sebastian Martinez":http://wyeworks.com -* September 3, 2009: Continuing work by Trevor Turk, leveraging the Action Pack docs and "What's new in Edge Rails":http://ryandaigle.com/articles/2007/8/3/what-s-new-in-edge-rails-partials-get-layouts -* April 5, 2009: Starting work by Trevor Turk, leveraging Mike Gunderloy's docs diff --git a/railties/guides/source/active_model_basics.textile b/railties/guides/source/active_model_basics.textile index 73df567579..9c8ad24cee 100644 --- a/railties/guides/source/active_model_basics.textile +++ b/railties/guides/source/active_model_basics.textile @@ -203,8 +203,3 @@ person.valid? #=> true person.token = nil person.valid? #=> raises ActiveModel::StrictValidationFailed - -h3. Changelog - -* August 24, 2011: Add strict validation usage example. "Bogdan Gusiev":http://gusiev.com -* August 5, 2011: Initial version by "Arun Agrawal":http://github.com/arunagw diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index ac8c15f60d..96f91cfef6 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -1248,12 +1248,3 @@ Client.sum("orders_count") For options, please see the parent section, "Calculations":#calculations. - -h3. Changelog - -* June 26 2011: Added documentation for the +scoped+, +unscoped+ and +default+ methods. "Ryan Bigg":credits.html#radar -* December 23 2010: Add documentation for the +scope+ method. "Ryan Bigg":credits.html#radar -* April 7, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* February 3, 2010: Update to Rails 3 by "James Miller":credits.html#bensie -* February 7, 2009: Second version by "Pratik":credits.html#lifo -* December 29 2008: Initial version by "Ryan Bigg":credits.html#radar diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile index aba3224ba7..20f5e52891 100644 --- a/railties/guides/source/active_record_validations_callbacks.textile +++ b/railties/guides/source/active_record_validations_callbacks.textile @@ -1267,14 +1267,3 @@ end The +after_commit+ and +after_rollback+ callbacks are guaranteed to be called for all models created, updated, or destroyed within a transaction block. If any exceptions are raised within one of these callbacks, they will be ignored so that they don't interfere with the other callbacks. As such, if your callback code could raise an exception, you'll need to rescue it and handle it appropriately within the callback. - -h3. Changelog - -* February 17, 2011: Add description of transaction callbacks. -* July 20, 2010: Fixed typos and rephrased some paragraphs for clarity. "Jaime Iniesta":http://jaimeiniesta.com -* May 24, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* May 15, 2010: Validation Errors section updated by "Emili Parreño":http://www.eparreno.com -* March 7, 2009: Callbacks revision by Trevor Turk -* February 10, 2009: Observers revision by Trevor Turk -* February 5, 2009: Initial revision by Trevor Turk -* January 9, 2009: Initial version by "Cássio Marques":credits.html#cmarques diff --git a/railties/guides/source/active_resource_basics.textile b/railties/guides/source/active_resource_basics.textile index 3294227f7b..851aac1a3f 100644 --- a/railties/guides/source/active_resource_basics.textile +++ b/railties/guides/source/active_resource_basics.textile @@ -118,7 +118,3 @@ This validates the resource with any local validations written in base class and h5. valid? Runs all the local validations and will return true if no errors. - -h3. Changelog - -* July 30, 2011: Initial version by "Vishnu Atrai":http://github.com/vatrai \ No newline at end of file diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 9e2fe2c694..d006cc9214 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -3599,8 +3599,3 @@ end NOTE: Defined in +active_support/core_ext/load_error.rb+. - -h3. Changelog - -* August 10, 2010: Starts to take shape, added to the index. -* April 18, 2009: Initial version by "Xavier Noria":credits.html#fxn diff --git a/railties/guides/source/api_documentation_guidelines.textile b/railties/guides/source/api_documentation_guidelines.textile index 3ebf0e10f1..c0f709eda8 100644 --- a/railties/guides/source/api_documentation_guidelines.textile +++ b/railties/guides/source/api_documentation_guidelines.textile @@ -183,7 +183,3 @@ self.class_eval %{ end } - -h3. Changelog - -* July 17, 2010: ported from the docrails wiki and revised by "Xavier Noria":credits.html#fxn diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile index 479693dbf8..f5f0f9340c 100644 --- a/railties/guides/source/association_basics.textile +++ b/railties/guides/source/association_basics.textile @@ -1860,13 +1860,3 @@ Extensions can refer to the internals of the association proxy using these three * +proxy_association.owner+ returns the object that the association is a part of. * +proxy_association.reflection+ returns the reflection object that describes the association. * +proxy_association.target+ returns the associated object for +belongs_to+ or +has_one+, or the collection of associated objects for +has_many+ or +has_and_belongs_to_many+. - -h3. Changelog - -* September 13, 2011: Removed mention of deprecated proxy methods in favor of using +proxy_association+. "Dallas Reedy":https://github.com/dallas -* April 7, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* April 19, 2009: Added +:touch+ option to +belongs_to+ associations by "Mike Gunderloy":credits.html#mgunderloy -* February 1, 2009: Added +:autosave+ option "Mike Gunderloy":credits.html#mgunderloy -* September 28, 2008: Corrected +has_many :through+ diagram, added polymorphic diagram, some reorganization by "Mike Gunderloy":credits.html#mgunderloy . First release version. -* September 22, 2008: Added diagrams, misc. cleanup by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication) -* September 14, 2008: initial version by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication) diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile index 693303950d..19378d63ce 100644 --- a/railties/guides/source/caching_with_rails.textile +++ b/railties/guides/source/caching_with_rails.textile @@ -403,14 +403,3 @@ end h3. Further reading * "Scaling Rails Screencasts":http://railslab.newrelic.com/scaling-rails - -h3. Changelog - -* Feb 17, 2011: Document 3.0.0 changes to ActiveSupport::Cache -* May 02, 2009: Formatting cleanups -* April 26, 2009: Clean up typos in submitted patch -* April 1, 2009: Made a bunch of small fixes -* February 22, 2009: Beefed up the section on cache_stores -* December 27, 2008: Typo fixes -* November 23, 2008: Incremental updates with various suggested changes and formatting cleanup -* September 15, 2008: Initial version by Aditya Chadha diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index ae84bb5b92..cad2d03c23 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -604,11 +604,3 @@ The error occurred while evaluating nil.each *+set_routes_reloader+* Configures Action Dispatch to reload the routes file using +ActionDispatch::Callbacks.to_prepare+. *+disable_dependency_loading+* Disables the automatic dependency loading if the +config.cache_classes+ is set to true and +config.dependency_loading+ is set to false. - -h3. Changelog - -* December 3, 2010: Added initialization events for Rails 3 ("Ryan Bigg":http://ryanbigg.com) -* November 26, 2010: Removed all config settings not available in Rails 3 ("Ryan Bigg":http://ryanbigg.com) -* August 13, 2009: Updated with config syntax and added general configuration options by "John Pignata" -* January 3, 2009: First reasonably complete draft by "Mike Gunderloy":credits.html#mgunderloy -* November 5, 2008: Rough outline by "Mike Gunderloy":credits.html#mgunderloy diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile index 86e31d79ee..30714e7e18 100644 --- a/railties/guides/source/contributing_to_ruby_on_rails.textile +++ b/railties/guides/source/contributing_to_ruby_on_rails.textile @@ -383,13 +383,3 @@ And then...think about your next contribution! h3. Rails Contributors All contributions, either via master or docrails, get credit in "Rails Contributors":http://contributors.rubyonrails.org. - -h3. Changelog - -* May 12, 2011: Modified to prefer topic branches instead of master branch for users contributions by "Guillermo Iguaran":http://quillarb.org -* April 29, 2011: Reflect GitHub Issues and Pull Request workflow by "Dan Pickett":http://www.enlightsolutions.com -* April 14, 2011: Modified Contributing to the Rails Code section to add '[#ticket_number state:commited]' on patches commit messages by "Sebastian Martinez":http://wyeworks.com -* December 28, 2010: Complete revision by "Xavier Noria":credits.html#fxn -* April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* August 1, 2009: Updates/amplifications by "Mike Gunderloy":credits.html#mgunderloy -* March 2, 2009: Initial draft by "Mike Gunderloy":credits.html#mgunderloy diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile index f5bee52b5a..3552c68418 100644 --- a/railties/guides/source/debugging_rails_applications.textile +++ b/railties/guides/source/debugging_rails_applications.textile @@ -712,10 +712,3 @@ h3. References * "ruby-debug cheat sheet":http://cheat.errtheblog.com/s/rdebug/ * "Ruby on Rails Wiki: How to Configure Logging":http://wiki.rubyonrails.org/rails/pages/HowtoConfigureLogging * "Bleak House Documentation":http://blog.evanweaver.com/files/doc/fauna/bleak_house/files/README.html - -h3. Changelog - -* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* November 3, 2008: Accepted for publication. Added RJS, memory leaks and plugins chapters by "Emilio Tagua":credits.html#miloops -* October 19, 2008: Copy editing pass by "Mike Gunderloy":credits.html#mgunderloy -* September 16, 2008: initial version by "Emilio Tagua":credits.html#miloops diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index c277f5723a..821bb305f6 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -796,13 +796,3 @@ Many apps grow beyond simple forms editing a single object. For example when cre * Eloy Duran's "complex-forms-examples":https://github.com/alloy/complex-form-examples/ application * Lance Ivy's "nested_assignment":https://github.com/cainlevy/nested_assignment/tree/master plugin and "sample application":https://github.com/cainlevy/complex-form-examples/tree/cainlevy * James Golick's "attribute_fu":https://github.com/jamesgolick/attribute_fu plugin - -h3. Changelog - -* February 5, 2011: Added 'Forms to external resources' section. Timothy N. Tsvetkov -* April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com - -h3. Authors - -* Mislav Marohnić -* "Frederick Cheung":credits.html#fcheung diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile index 3f990ef54b..7a863ccbc7 100644 --- a/railties/guides/source/generators.textile +++ b/railties/guides/source/generators.textile @@ -619,14 +619,3 @@ Output the contents of a file in the template's +source_path+, usually a README. readme("README") - -h3. Changelog - -* December 1, 2010: Documenting the available methods and options for generators and templates by "Ryan Bigg":http://ryanbigg.com -* December 1, 2010: Addition of Rails application templates by "Ryan Bigg":http://ryanbigg.com - -* August 23, 2010: Edit pass by "Xavier Noria":credits.html#fxn - -* April 30, 2010: Reviewed by José Valim - -* November 20, 2009: First version by José Valim diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 95324d4da4..33f383f173 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1888,24 +1888,3 @@ Two very common sources of data that are not UTF-8: is using Latin-1 internally, and your user enters a Russian, Hebrew, or Japanese character, the data will be lost forever once it enters the database. If possible, use UTF-8 as the internal storage of your database. - -h3. Changelog - -* April 26, 2011: Change migration code from +up+, +down+ pair to +change+ method by "Prem Sichanugrist":http://sikachu.com -* April 11, 2011: Change scaffold_controller generator to create format block for JSON instead of XML by "Sebastian Martinez":http://www.wyeworks.com -* August 30, 2010: Minor editing after Rails 3 release by Joost Baaij -* July 12, 2010: Fixes, editing and updating of code samples by "Jaime Iniesta":http://jaimeiniesta.com -* May 16, 2010: Added a section on configuration gotchas to address common encoding problems that people might have by "Yehuda Katz":http://www.yehudakatz.com -* April 30, 2010: Fixes, editing and updating of code samples by "Rohit Arondekar":http://rohitarondekar.com -* April 25, 2010: Couple of more minor fixups by "Mikel Lindsaar":credits.html#raasdnil -* April 1, 2010: Fixed document to validate XHTML 1.0 Strict by "Jaime Iniesta":http://jaimeiniesta.com -* February 8, 2010: Full re-write for Rails 3.0-beta, added helpers and before_filters, refactored code by "Mikel Lindsaar":credits.html#raasdnil -* January 24, 2010: Re-write for Rails 3.0 by "Mikel Lindsaar":credits.html#raasdnil -* July 18, 2009: Minor cleanup in anticipation of Rails 2.3.3 by "Mike Gunderloy":credits.html#mgunderloy -* February 1, 2009: Updated for Rails 2.3 by "Mike Gunderloy":credits.html#mgunderloy -* November 3, 2008: Formatting patch from Dave Rothlisberger -* November 1, 2008: First approved version by "Mike Gunderloy":credits.html#mgunderloy -* October 16, 2008: Revised based on feedback from Pratik Naik by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication) -* October 13, 2008: First complete draft by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication) -* October 12, 2008: More detail, rearrangement, editing by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication) -* September 8, 2008: initial version by "James Miller":credits.html#bensie (not yet approved for publication) diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index f49c2000ee..69ef05104c 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -1194,15 +1194,3 @@ On pages generated by +NewsController+, you want to hide the top menu and add a That's it. The News views will use the new layout, hiding the top menu and adding a new right menu inside the "content" div. There are several ways of getting similar results with different sub-templating schemes using this technique. Note that there is no limit in nesting levels. One can use the +ActionView::render+ method via +render :template => 'layouts/news'+ to base a new layout on the News layout. If you are sure you will not subtemplate the +News+ layout, you can replace the +content_for?(:news_content) ? yield(:news_content) : yield+ with simply +yield+. - -h3. Changelog - -* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* January 25, 2010: Rails 3.0 Update by "Mikel Lindsaar":credits.html#raasdnil -* December 27, 2008: Merge patch from Rodrigo Rosenfeld Rosas covering subtemplates -* December 27, 2008: Information on new rendering defaults by "Mike Gunderloy":credits.html#mgunderloy -* November 9, 2008: Added partial collection counter by "Mike Gunderloy":credits.html#mgunderloy -* November 1, 2008: Added +:js+ option for +render+ by "Mike Gunderloy":credits.html#mgunderloy -* October 16, 2008: Ready for publication by "Mike Gunderloy":credits.html#mgunderloy -* October 4, 2008: Additional info on partials (+:object+, +:as+, and +:spacer_template+) by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication) -* September 28, 2008: First draft by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication) diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile index 6fcc3cf4a2..7faa18e888 100644 --- a/railties/guides/source/migrations.textile +++ b/railties/guides/source/migrations.textile @@ -673,9 +673,3 @@ The Active Record way claims that intelligence belongs in your models, not in th Validations such as +validates :foreign_key, :uniqueness => true+ are one way in which models can enforce data integrity. The +:dependent+ option on associations allows models to automatically destroy child objects when the parent is destroyed. Like anything which operates at the application level these cannot guarantee referential integrity and so some people augment them with foreign key constraints. Although Active Record does not provide any tools for working directly with such features, the +execute+ method can be used to execute arbitrary SQL. There are also a number of plugins such as "foreign_key_migrations":https://github.com/harukizaemon/redhillonrails/tree/master/foreign_key_migrations/ which add foreign key support to Active Record (including support for dumping foreign keys in +db/schema.rb+). - -h3. Changelog - -* April 26, 2011: change generated +up+ and +down+ methods to +change+ method, and describe detail about +change+ method by "Prem Sichanugrist":http://sikachu.com -* July 15, 2010: minor typos corrected by "Jaime Iniesta":http://jaimeiniesta.com -* September 14, 2008: initial version by "Frederick Cheung":credits.html#fcheung diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile index 5947735deb..f3ea7e38bc 100644 --- a/railties/guides/source/performance_testing.textile +++ b/railties/guides/source/performance_testing.textile @@ -595,9 +595,3 @@ Rails has been lucky to have a few companies dedicated to Rails-specific perform * "New Relic":http://www.newrelic.com * "Scout":http://scoutapp.com - -h3. Changelog - -* March 30, 2011: Documented the recent improvements (multiple interpreters, options, etc) and necessary adjustments. Other minor improvements. "Gonçalo Silva":http://goncalossilva.com. -* January 9, 2009: Complete rewrite by "Pratik":credits.html#lifo -* September 6, 2008: Initial version by Matthew Bergman diff --git a/railties/guides/source/plugins.textile b/railties/guides/source/plugins.textile index e8bdfa7f1c..5cfd336d1e 100644 --- a/railties/guides/source/plugins.textile +++ b/railties/guides/source/plugins.textile @@ -462,11 +462,3 @@ h4. References * "Gemspec Reference":http://docs.rubygems.org/read/chapter/20 * "GemPlugins":http://www.mbleigh.com/2008/06/11/gemplugins-a-brief-introduction-to-the-future-of-rails-plugins * "Keeping init.rb thin":http://daddy.platte.name/2007/05/rails-plugins-keep-initrb-thin.html - -h3. Changelog - -* March 10, 2011: Minor formatting tweaks. -* February 13, 2011: Get guide in synch with Rails 3.0.3. Remove information not compatible with Rails 3. Send reader elsewhere -for information that is covered elsewhere. -* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* November 17, 2008: Major revision by Jeff Dean diff --git a/railties/guides/source/rails_application_templates.textile b/railties/guides/source/rails_application_templates.textile index c3c8af4d3a..3b51a52733 100644 --- a/railties/guides/source/rails_application_templates.textile +++ b/railties/guides/source/rails_application_templates.textile @@ -238,7 +238,3 @@ git :init git :add => "." git :commit => "-a -m 'Initial commit'" - -h3. Changelog - -* April 29, 2009: Initial version by "Pratik":credits.html#lifo diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile index 735438b155..57c03b54dc 100644 --- a/railties/guides/source/rails_on_rack.textile +++ b/railties/guides/source/rails_on_rack.textile @@ -232,8 +232,3 @@ h4. Learning Rack h4. Understanding Middlewares * "Railscast on Rack Middlewares":http://railscasts.com/episodes/151-rack-middleware - -h3. Changelog - -* February 7, 2009: Second version by "Pratik":credits.html#lifo -* January 11, 2009: First version by "Pratik":credits.html#lifo diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index 99dd9a1cd2..0a9f1e8388 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -881,12 +881,3 @@ The +assert_routing+ assertion checks the route both ways: it tests that the pat assert_routing({ :path => "photos", :method => :post }, { :controller => "photos", :action => "create" }) - -h3. Changelog - -* April 10, 2010: Updated guide to remove outdated and superfluous information, and to provide information about new features, by "Yehuda Katz":http://www.yehudakatz.com -* April 2, 2010: Updated guide to match new Routing DSL in Rails 3, by "Rizwan Reza":http://www.rizwanreza.com/ -* February 1, 2010: Modifies the routing documentation to match new routing DSL in Rails 3, by Prem Sichanugrist -* October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes, by "Mike Gunderloy":credits.html#mgunderloy -* September 23, 2008: Added section on namespaced controllers and routing, by "Mike Gunderloy":credits.html#mgunderloy -* September 10, 2008: initial version by "Mike Gunderloy":credits.html#mgunderloy diff --git a/railties/guides/source/ruby_on_rails_guides_guidelines.textile b/railties/guides/source/ruby_on_rails_guides_guidelines.textile index 5989191b5c..e63f564c83 100644 --- a/railties/guides/source/ruby_on_rails_guides_guidelines.textile +++ b/railties/guides/source/ruby_on_rails_guides_guidelines.textile @@ -77,8 +77,3 @@ bundle exec rake validate_guides Particularly, titles get an ID generated from their content and this often leads to duplicates. Please set +WARNINGS=1+ when generating guides to detect them. The warning messages suggest a way to fix them. - -h3. Changelog - -* March 31, 2011: grammar tweaks by "Josiah Ivey":http://twitter.com/josiahivey -* October 5, 2010: ported from the docrails wiki and revised by "Xavier Noria":credits.html#fxn diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile index 04d1d0bda8..4cf9e2a7f3 100644 --- a/railties/guides/source/security.textile +++ b/railties/guides/source/security.textile @@ -1002,7 +1002,3 @@ The security landscape shifts and it is important to keep up to date, because mi * Subscribe to the Rails security "mailing list":http://groups.google.com/group/rubyonrails-security * "Keep up to date on the other application layers":http://secunia.com/ (they have a weekly newsletter, too) * A "good security blog":http://ha.ckers.org/blog/ including the "Cross-Site scripting Cheat Sheet":http://ha.ckers.org/xss.html - -h3. Changelog - -* November 1, 2008: First approved version by Heiko Webers diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile index caa0d91a83..2341a3522c 100644 --- a/railties/guides/source/testing.textile +++ b/railties/guides/source/testing.textile @@ -945,11 +945,3 @@ The built-in +test/unit+ based testing is not the only way to test Rails applica * "Machinist":https://github.com/notahat/machinist/tree/master, another replacement for fixtures. * "Shoulda":http://www.thoughtbot.com/projects/shoulda, an extension to +test/unit+ with additional helpers, macros, and assertions. * "RSpec":http://relishapp.com/rspec, a behavior-driven development framework - -h3. Changelog - -* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* November 13, 2008: Revised based on feedback from Pratik Naik by "Akshay Surve":credits.html#asurve (not yet approved for publication) -* October 14, 2008: Edit and formatting pass by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication) -* October 12, 2008: First draft by "Akshay Surve":credits.html#asurve (not yet approved for publication) - -- cgit v1.2.3 From da7f0426ec7b0aa053489633c2a8a3da6423654f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 14 Sep 2011 14:47:49 -0700 Subject: Allow asset tag helper methods to accept :digest => false option in order to completely avoid the digest generation. --- actionpack/CHANGELOG | 4 ++ actionpack/lib/action_view/asset_paths.rb | 9 +++-- .../helpers/asset_tag_helpers/asset_include_tag.rb | 4 +- .../helpers/asset_tag_helpers/asset_paths.rb | 2 +- .../asset_tag_helpers/javascript_tag_helpers.rb | 2 +- .../asset_tag_helpers/stylesheet_tag_helpers.rb | 4 +- actionpack/lib/sprockets/helpers/rails_helper.rb | 28 +++++++------- actionpack/test/template/sprockets_helper_test.rb | 44 ++++++++++++++-------- 8 files changed, 58 insertions(+), 39 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index d01422b314..5ee14dbdf1 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -48,6 +48,10 @@ *Rails 3.1.1 (unreleased)* +* Allow asset tag helper methods to accept :digest => false option in order to completely avoid the digest generation. +Useful for linking assets from static html files or from emails when the user +could probably look at an older html email with an older asset. [Santiago Pastorino] + * Don't mount Sprockets server at config.assets.prefix if config.assets.compile is false. [Mark J. Titorenko] * Set relative url root in assets when controller isn't available for Sprockets (eg. Sass files using asset_path). Fixes #2435 [Guillermo Iguaran] diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb index 75164b8134..cf30ad7e57 100644 --- a/actionpack/lib/action_view/asset_paths.rb +++ b/actionpack/lib/action_view/asset_paths.rb @@ -21,14 +21,15 @@ module ActionView # When :relative (default), the protocol will be determined by the client using current protocol # When :request, the protocol will be the request protocol # Otherwise, the protocol is used (E.g. :http, :https, etc) - def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil) + def compute_public_path(source, dir, options = {}) source = source.to_s return source if is_uri?(source) - source = rewrite_extension(source, dir, ext) if ext - source = rewrite_asset_path(source, dir) + options[:include_host] ||= true + source = rewrite_extension(source, dir, options[:ext]) if options[:ext] + source = rewrite_asset_path(source, dir, options) source = rewrite_relative_url_root(source, relative_url_root) - source = rewrite_host_and_protocol(source, protocol) if include_host + source = rewrite_host_and_protocol(source, options[:protocol]) if options[:include_host] source end diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb index 3c05173a1b..05d5f1870a 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb @@ -60,8 +60,8 @@ module ActionView private - def path_to_asset(source, include_host = true, protocol = nil) - asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension, include_host, protocol) + def path_to_asset(source, options = {}) + asset_paths.compute_public_path(source, asset_name.to_s.pluralize, options.merge(:ext => extension)) end def path_to_asset_source(source) diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb index 8b35aa8896..dd4e9ae4cc 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb @@ -41,7 +41,7 @@ module ActionView # Break out the asset path rewrite in case plugins wish to put the asset id # someplace other than the query string. - def rewrite_asset_path(source, dir) + def rewrite_asset_path(source, dir, options = nil) source = "/#{dir}/#{source}" unless source[0] == ?/ path = config.asset_path diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb index 25cc561608..09700bd0c5 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb @@ -83,7 +83,7 @@ module ActionView # javascript_path "http://www.example.com/js/xmlhr" # => http://www.example.com/js/xmlhr # javascript_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js def javascript_path(source) - asset_paths.compute_public_path(source, 'javascripts', 'js') + asset_paths.compute_public_path(source, 'javascripts', :ext => 'js') end alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb index 8c25d38bbd..2eb3eb31af 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb @@ -17,7 +17,7 @@ module ActionView def asset_tag(source, options) # We force the :request protocol here to avoid a double-download bug in IE7 and IE8 - tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source, true, :request)) }.merge(options), false, false) + tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source, :protocol => :request)) }.merge(options), false, false) end def custom_dir @@ -61,7 +61,7 @@ module ActionView # stylesheet_path "http://www.example.com/css/style" # => http://www.example.com/css/style # stylesheet_path "http://www.example.com/css/style.css" # => http://www.example.com/css/style.css def stylesheet_path(source) - asset_paths.compute_public_path(source, 'stylesheets', 'css', true, :request) + asset_paths.compute_public_path(source, 'stylesheets', :ext => 'css', :protocol => :request) end alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 998f0bceb7..457ab93ae3 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -25,38 +25,40 @@ module Sprockets options = sources.extract_options! debug = options.key?(:debug) ? options.delete(:debug) : debug_assets? body = options.key?(:body) ? options.delete(:body) : false + digest = options.key?(:digest) ? options.delete(:digest) : digest_assets? sources.collect do |source| if debug && asset = asset_paths.asset_for(source, 'js') asset.to_a.map { |dep| - super(dep.to_s, { :src => asset_path(dep, 'js', true) }.merge!(options)) + super(dep.to_s, { :src => asset_path(dep, :ext => 'js', :body => true, :digest => digest) }.merge!(options)) } else - super(source.to_s, { :src => asset_path(source, 'js', body) }.merge!(options)) + super(source.to_s, { :src => asset_path(source, :ext => 'js', :body => body, :digest => digest) }.merge!(options)) end end.join("\n").html_safe end def stylesheet_link_tag(*sources) options = sources.extract_options! - debug = options.key?(:debug) ? options.delete(:debug) : debug_assets? - body = options.key?(:body) ? options.delete(:body) : false + debug = options.key?(:debug) ? options.delete(:debug) : debug_assets? + body = options.key?(:body) ? options.delete(:body) : false + digest = options.key?(:digest) ? options.delete(:digest) : digest_assets? sources.collect do |source| if debug && asset = asset_paths.asset_for(source, 'css') asset.to_a.map { |dep| - super(dep.to_s, { :href => asset_path(dep, 'css', true, :request) }.merge!(options)) + super(dep.to_s, { :href => asset_path(dep, :ext => 'css', :body => true, :protocol => :request, :digest => digest) }.merge!(options)) } else - super(source.to_s, { :href => asset_path(source, 'css', body, :request) }.merge!(options)) + super(source.to_s, { :href => asset_path(source, :ext => 'css', :body => body, :protocol => :request, :digest => digest) }.merge!(options)) end end.join("\n").html_safe end - def asset_path(source, default_ext = nil, body = false, protocol = nil) + def asset_path(source, options = {}) source = source.logical_path if source.respond_to?(:logical_path) - path = asset_paths.compute_public_path(source, 'assets', default_ext, true, protocol) - body ? "#{path}?body=1" : path + path = asset_paths.compute_public_path(source, 'assets', options.merge(:body => true)) + options[:body] ? "#{path}?body=1" : path end private @@ -100,8 +102,8 @@ module Sprockets class AssetNotPrecompiledError < StandardError; end - def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil) - super(source, asset_prefix, ext, include_host, protocol) + def compute_public_path(source, dir, options = {}) + super(source, asset_prefix, options) end # Return the filesystem path for the source @@ -131,11 +133,11 @@ module Sprockets end end - def rewrite_asset_path(source, dir) + def rewrite_asset_path(source, dir, options = {}) if source[0] == ?/ source else - source = digest_for(source) + source = digest_for(source) unless options[:digest] == false source = File.join(dir, source) source = "/#{source}" unless source =~ /^\// source diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb index 105c641712..c0fb07a29b 100644 --- a/actionpack/test/template/sprockets_helper_test.rb +++ b/actionpack/test/template/sprockets_helper_test.rb @@ -41,6 +41,10 @@ class SprocketsHelperTest < ActionView::TestCase test "asset_path" do assert_match %r{/assets/logo-[0-9a-f]+.png}, asset_path("logo.png") + assert_match %r{/assets/logo-[0-9a-f]+.png}, + asset_path("logo.png", :digest => true) + assert_match %r{/assets/logo.png}, + asset_path("logo.png", :digest => false) end test "asset_path with root relative assets" do @@ -133,25 +137,29 @@ class SprocketsHelperTest < ActionView::TestCase test "javascript path" do assert_match %r{/assets/application-[0-9a-f]+.js}, - asset_path(:application, "js") + asset_path(:application, :ext => "js") assert_match %r{/assets/xmlhr-[0-9a-f]+.js}, - asset_path("xmlhr", "js") + asset_path("xmlhr", :ext => "js") assert_match %r{/assets/dir/xmlhr-[0-9a-f]+.js}, - asset_path("dir/xmlhr.js", "js") + asset_path("dir/xmlhr.js", :ext => "js") assert_equal "/dir/xmlhr.js", - asset_path("/dir/xmlhr", "js") + asset_path("/dir/xmlhr", :ext => "js") assert_equal "http://www.example.com/js/xmlhr", - asset_path("http://www.example.com/js/xmlhr", "js") + asset_path("http://www.example.com/js/xmlhr", :ext => "js") assert_equal "http://www.example.com/js/xmlhr.js", - asset_path("http://www.example.com/js/xmlhr.js", "js") + asset_path("http://www.example.com/js/xmlhr.js", :ext => "js") end test "javascript include tag" do assert_match %r{}, javascript_include_tag(:application) + assert_match %r{}, + javascript_include_tag(:application, :digest => true) + assert_match %r{}, + javascript_include_tag(:application, :digest => false) assert_match %r{}, javascript_include_tag("xmlhr") @@ -173,21 +181,25 @@ class SprocketsHelperTest < ActionView::TestCase end test "stylesheet path" do - assert_match %r{/assets/application-[0-9a-f]+.css}, asset_path(:application, "css") + assert_match %r{/assets/application-[0-9a-f]+.css}, asset_path(:application, :ext => "css") - assert_match %r{/assets/style-[0-9a-f]+.css}, asset_path("style", "css") - assert_match %r{/assets/dir/style-[0-9a-f]+.css}, asset_path("dir/style.css", "css") - assert_equal "/dir/style.css", asset_path("/dir/style.css", "css") + assert_match %r{/assets/style-[0-9a-f]+.css}, asset_path("style", :ext => "css") + assert_match %r{/assets/dir/style-[0-9a-f]+.css}, asset_path("dir/style.css", :ext => "css") + assert_equal "/dir/style.css", asset_path("/dir/style.css", :ext => "css") assert_equal "http://www.example.com/css/style", - asset_path("http://www.example.com/css/style", "css") + asset_path("http://www.example.com/css/style", :ext => "css") assert_equal "http://www.example.com/css/style.css", - asset_path("http://www.example.com/css/style.css", "css") + asset_path("http://www.example.com/css/style.css", :ext => "css") end test "stylesheet link tag" do assert_match %r{}, stylesheet_link_tag(:application) + assert_match %r{}, + stylesheet_link_tag(:application, :digest => true) + assert_match %r{}, + stylesheet_link_tag(:application, :digest => false) assert_match %r{}, stylesheet_link_tag("style") @@ -218,14 +230,14 @@ class SprocketsHelperTest < ActionView::TestCase test "alternate asset prefix" do stubs(:asset_prefix).returns("/themes/test") - assert_match %r{/themes/test/style-[0-9a-f]+.css}, asset_path("style", "css") + assert_match %r{/themes/test/style-[0-9a-f]+.css}, asset_path("style", :ext => "css") end test "alternate asset environment" do assets = Sprockets::Environment.new assets.append_path(FIXTURES.join("sprockets/alternate/stylesheets")) stubs(:asset_environment).returns(assets) - assert_match %r{/assets/style-[0-9a-f]+.css}, asset_path("style", "css") + assert_match %r{/assets/style-[0-9a-f]+.css}, asset_path("style", :ext => "css") end test "alternate hash based on environment" do @@ -233,10 +245,10 @@ class SprocketsHelperTest < ActionView::TestCase assets.version = 'development' assets.append_path(FIXTURES.join("sprockets/alternate/stylesheets")) stubs(:asset_environment).returns(assets) - dev_path = asset_path("style", "css") + dev_path = asset_path("style", :ext => "css") assets.version = 'production' - prod_path = asset_path("style", "css") + prod_path = asset_path("style", :ext => "css") assert_not_equal prod_path, dev_path end -- cgit v1.2.3 From 7531aa76417a5db337287c31c1b97ad53615c8e6 Mon Sep 17 00:00:00 2001 From: Alexey Vakhov Date: Thu, 15 Sep 2011 10:41:55 +0400 Subject: update guides, use html safe translations in i18n --- .../guides/assets/images/i18n/demo_html_safe.png | Bin 0 -> 11946 bytes railties/guides/source/i18n.textile | 22 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 railties/guides/assets/images/i18n/demo_html_safe.png diff --git a/railties/guides/assets/images/i18n/demo_html_safe.png b/railties/guides/assets/images/i18n/demo_html_safe.png new file mode 100644 index 0000000000..f881f60dac Binary files /dev/null and b/railties/guides/assets/images/i18n/demo_html_safe.png differ diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile index 4b6b08bcec..76cd14d479 100644 --- a/railties/guides/source/i18n.textile +++ b/railties/guides/source/i18n.textile @@ -448,6 +448,7 @@ Covered are features like these: * looking up translations * interpolating data into translations * pluralizing translations +* using safe HTML translations * localizing dates, numbers, currency, etc. h4. Looking up Translations @@ -599,6 +600,27 @@ The +I18n.locale+ defaults to +I18n.default_locale+ which defaults to :+en+. The I18n.default_locale = :de +h4. Using Safe HTML Translations + +Keys with a '_html' suffix and keys named 'html' are marked as HTML safe. Use them in views without escaping. + + +# config/locales/en.yml +en: + welcome: welcome! + hello_html: hello! + title: + html: title! + +# app/views/home/index.html.erb +
      <%= t('welcome') %>
      +
      <%= raw t('welcome') %>
      +
      <%= t('hello_html') %>
      +
      <%= t('title.html') %>
      +
      + +!images/i18n/demo_html_safe.png(i18n demo html safe)! + h3. How to Store your Custom Translations The Simple backend shipped with Active Support allows you to store translations in both plain Ruby and YAML format. [2] -- cgit v1.2.3 From bffaa888ac4a1ee60a9f93650b9184a9402eff09 Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 08:28:53 -0400 Subject: Custom serializers and deserializers in MessageVerifier and MessageEncryptor. By default, these classes use Marshal for serializing and deserializing messages. Unfortunately, the Marshal format is closely associated with Ruby internals and even changes between different interpreters. This makes the resulting message very hard to impossible to unserialize messages generated by these classes in other environments like node.js. This patch solves this by allowing you to set your own custom serializer and deserializer lambda functions. By default, it still uses Marshal to be backwards compatible. --- activesupport/lib/active_support/message_encryptor.rb | 8 ++++++-- activesupport/lib/active_support/message_verifier.rb | 8 ++++++-- activesupport/test/message_encryptor_test.rb | 10 +++++++++- activesupport/test/message_verifier_test.rb | 9 +++++++++ 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 4f7cd12d48..05d6790075 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -13,9 +13,13 @@ module ActiveSupport class InvalidMessage < StandardError; end OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError + attr_accessor :serializer, :deserializer + def initialize(secret, cipher = 'aes-256-cbc') @secret = secret @cipher = cipher + @serializer = lambda { |value| Marshal.dump(value) } + @deserializer = lambda { |value| Marshal.load(value) } end def encrypt(value) @@ -27,7 +31,7 @@ module ActiveSupport cipher.key = @secret cipher.iv = iv - encrypted_data = cipher.update(Marshal.dump(value)) + encrypted_data = cipher.update(serializer.call(value)) encrypted_data << cipher.final [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--") @@ -44,7 +48,7 @@ module ActiveSupport decrypted_data = cipher.update(encrypted_data) decrypted_data << cipher.final - Marshal.load(decrypted_data) + deserializer.call(decrypted_data) rescue OpenSSLCipherError, TypeError raise InvalidMessage end diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 8f3946325a..e38e242cfe 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -21,9 +21,13 @@ module ActiveSupport class MessageVerifier class InvalidSignature < StandardError; end + attr_accessor :serializer, :deserializer + def initialize(secret, digest = 'SHA1') @secret = secret @digest = digest + @serializer = lambda { |value| Marshal.dump(value) } + @deserializer = lambda { |value| Marshal.load(value) } end def verify(signed_message) @@ -31,14 +35,14 @@ module ActiveSupport data, digest = signed_message.split("--") if data.present? && digest.present? && secure_compare(digest, generate_digest(data)) - Marshal.load(ActiveSupport::Base64.decode64(data)) + deserializer.call(ActiveSupport::Base64.decode64(data)) else raise InvalidSignature end end def generate(value) - data = ActiveSupport::Base64.encode64s(Marshal.dump(value)) + data = ActiveSupport::Base64.encode64s(serializer.call(value)) "#{data}--#{generate_digest(data)}" end diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index e45d5ecd59..bd11b76e60 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -8,6 +8,7 @@ rescue LoadError, NameError else require 'active_support/time' +require 'active_support/json' class MessageEncryptorTest < Test::Unit::TestCase def setup @@ -38,7 +39,14 @@ class MessageEncryptorTest < Test::Unit::TestCase message = @encryptor.encrypt_and_sign(@data) assert_equal @data, @encryptor.decrypt_and_verify(message) end - + + def test_alternative_serialization_method + @encryptor.serializer = lambda { |value| ActiveSupport::JSON.encode(value) } + @encryptor.deserializer = lambda { |value| ActiveSupport::JSON.decode(value) } + + message = @encryptor.encrypt_and_sign({ :foo => 123, 'bar' => Time.local(2010) }) + assert_equal @encryptor.decrypt_and_verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00-05:00" } + end private def assert_not_decrypted(value) diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 4821311244..83f34ebc33 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -8,6 +8,7 @@ rescue LoadError, NameError else require 'active_support/time' +require 'active_support/json' class MessageVerifierTest < Test::Unit::TestCase def setup @@ -31,6 +32,14 @@ class MessageVerifierTest < Test::Unit::TestCase assert_not_verified("#{data}--#{hash.reverse}") assert_not_verified("purejunk") end + + def test_alternative_serialization_method + @verifier.serializer = lambda { |value| ActiveSupport::JSON.encode(value) } + @verifier.deserializer = lambda { |value| ActiveSupport::JSON.decode(value) } + + message = @verifier.generate({ :foo => 123, 'bar' => Time.local(2010) }) + assert_equal @verifier.verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00-05:00" } + end def assert_not_verified(message) assert_raise(ActiveSupport::MessageVerifier::InvalidSignature) do -- cgit v1.2.3 From a8aaef676217f53f2812cd56f71a6b00c5d22162 Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 09:50:39 -0400 Subject: Fixed tests so that they will also run properly in other timezones. --- activesupport/test/message_encryptor_test.rb | 4 ++-- activesupport/test/message_verifier_test.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index bd11b76e60..95e64fe6d1 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -44,8 +44,8 @@ class MessageEncryptorTest < Test::Unit::TestCase @encryptor.serializer = lambda { |value| ActiveSupport::JSON.encode(value) } @encryptor.deserializer = lambda { |value| ActiveSupport::JSON.decode(value) } - message = @encryptor.encrypt_and_sign({ :foo => 123, 'bar' => Time.local(2010) }) - assert_equal @encryptor.decrypt_and_verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00-05:00" } + message = @encryptor.encrypt_and_sign({ :foo => 123, 'bar' => Time.utc(2010) }) + assert_equal @encryptor.decrypt_and_verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } end private diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 83f34ebc33..224e38a52a 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -37,8 +37,8 @@ class MessageVerifierTest < Test::Unit::TestCase @verifier.serializer = lambda { |value| ActiveSupport::JSON.encode(value) } @verifier.deserializer = lambda { |value| ActiveSupport::JSON.decode(value) } - message = @verifier.generate({ :foo => 123, 'bar' => Time.local(2010) }) - assert_equal @verifier.verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00-05:00" } + message = @verifier.generate({ :foo => 123, 'bar' => Time.utc(2010) }) + assert_equal @verifier.verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } end def assert_not_verified(message) -- cgit v1.2.3 From db040cdf8ba832123bae68764189bbcb569d473a Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 13:15:21 -0400 Subject: Implement API suggestions of pull request. --- activesupport/lib/active_support/message_encryptor.rb | 11 +++++------ activesupport/lib/active_support/message_verifier.rb | 11 +++++------ activesupport/test/message_encryptor_test.rb | 15 ++++++++++++--- activesupport/test/message_verifier_test.rb | 15 ++++++++++++--- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 05d6790075..66e121be26 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -13,13 +13,12 @@ module ActiveSupport class InvalidMessage < StandardError; end OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError - attr_accessor :serializer, :deserializer + attr_accessor :serializer - def initialize(secret, cipher = 'aes-256-cbc') + def initialize(secret, cipher = 'aes-256-cbc', serializer = Marshal) @secret = secret @cipher = cipher - @serializer = lambda { |value| Marshal.dump(value) } - @deserializer = lambda { |value| Marshal.load(value) } + @serializer = serializer end def encrypt(value) @@ -31,7 +30,7 @@ module ActiveSupport cipher.key = @secret cipher.iv = iv - encrypted_data = cipher.update(serializer.call(value)) + encrypted_data = cipher.update(serializer.dump(value)) encrypted_data << cipher.final [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--") @@ -48,7 +47,7 @@ module ActiveSupport decrypted_data = cipher.update(encrypted_data) decrypted_data << cipher.final - deserializer.call(decrypted_data) + serializer.load(decrypted_data) rescue OpenSSLCipherError, TypeError raise InvalidMessage end diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index e38e242cfe..b3a087a596 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -21,13 +21,12 @@ module ActiveSupport class MessageVerifier class InvalidSignature < StandardError; end - attr_accessor :serializer, :deserializer + attr_accessor :serializer - def initialize(secret, digest = 'SHA1') + def initialize(secret, digest = 'SHA1', serializer = Marshal) @secret = secret @digest = digest - @serializer = lambda { |value| Marshal.dump(value) } - @deserializer = lambda { |value| Marshal.load(value) } + @serializer = serializer end def verify(signed_message) @@ -35,14 +34,14 @@ module ActiveSupport data, digest = signed_message.split("--") if data.present? && digest.present? && secure_compare(digest, generate_digest(data)) - deserializer.call(ActiveSupport::Base64.decode64(data)) + serializer.load(ActiveSupport::Base64.decode64(data)) else raise InvalidSignature end end def generate(value) - data = ActiveSupport::Base64.encode64s(serializer.call(value)) + data = ActiveSupport::Base64.encode64s(serializer.dump(value)) "#{data}--#{generate_digest(data)}" end diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index 95e64fe6d1..9c89512b42 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -11,6 +11,17 @@ require 'active_support/time' require 'active_support/json' class MessageEncryptorTest < Test::Unit::TestCase + + class JSONSerializer + def dump(value) + ActiveSupport::JSON.encode(value) + end + + def load(value) + ActiveSupport::JSON.decode(value) + end + end + def setup @encryptor = ActiveSupport::MessageEncryptor.new(SecureRandom.hex(64)) @data = { :some => "data", :now => Time.local(2010) } @@ -41,9 +52,7 @@ class MessageEncryptorTest < Test::Unit::TestCase end def test_alternative_serialization_method - @encryptor.serializer = lambda { |value| ActiveSupport::JSON.encode(value) } - @encryptor.deserializer = lambda { |value| ActiveSupport::JSON.decode(value) } - + @encryptor.serializer = JSONSerializer.new message = @encryptor.encrypt_and_sign({ :foo => 123, 'bar' => Time.utc(2010) }) assert_equal @encryptor.decrypt_and_verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } end diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 224e38a52a..10a1738786 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -11,6 +11,17 @@ require 'active_support/time' require 'active_support/json' class MessageVerifierTest < Test::Unit::TestCase + + class JSONSerializer + def dump(value) + ActiveSupport::JSON.encode(value) + end + + def load(value) + ActiveSupport::JSON.decode(value) + end + end + def setup @verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!") @data = { :some => "data", :now => Time.local(2010) } @@ -34,9 +45,7 @@ class MessageVerifierTest < Test::Unit::TestCase end def test_alternative_serialization_method - @verifier.serializer = lambda { |value| ActiveSupport::JSON.encode(value) } - @verifier.deserializer = lambda { |value| ActiveSupport::JSON.decode(value) } - + @verifier.serializer = JSONSerializer.new message = @verifier.generate({ :foo => 123, 'bar' => Time.utc(2010) }) assert_equal @verifier.verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } end -- cgit v1.2.3 From 2d30d4cb888e2da7c1f0a8828b467d2e21c90cfa Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 13:23:08 -0400 Subject: Add some documentation for the new serializer property of MessageVerifier and MessageEncryptor. --- activesupport/lib/active_support/message_verifier.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index b3a087a596..0181070479 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -18,6 +18,11 @@ module ActiveSupport # self.current_user = User.find(id) # end # + # By default it uses Marshal to serialize the message. If you want to use another + # serialization method, you can set the serializer attribute to something that responds + # to dump and load, e.g.: + # + # @verifier.serializer = YAML class MessageVerifier class InvalidSignature < StandardError; end -- cgit v1.2.3 From 41fea0334232824d5d509a6924e8c8487d53494b Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 14:27:12 -0400 Subject: Use an options hash to specify digest/cipher algorithm and a serializer for MessageVerifier and MessageEncryptor. --- activesupport/lib/active_support/message_encryptor.rb | 17 ++++++++++------- activesupport/lib/active_support/message_verifier.rb | 17 ++++++++++------- activesupport/test/message_encryptor_test.rb | 6 +++--- activesupport/test/message_verifier_test.rb | 6 +++--- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 66e121be26..7637cfe2b0 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -13,12 +13,15 @@ module ActiveSupport class InvalidMessage < StandardError; end OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError - attr_accessor :serializer - - def initialize(secret, cipher = 'aes-256-cbc', serializer = Marshal) + def initialize(secret, options = {}) + unless options.is_a?(Hash) + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to sepcify the cipher algorithm." + options = { :cipher => options } + end + @secret = secret - @cipher = cipher - @serializer = serializer + @cipher = options[:cipher] || 'aes-256-cbc' + @serializer = options[:serializer] || Marshal end def encrypt(value) @@ -30,7 +33,7 @@ module ActiveSupport cipher.key = @secret cipher.iv = iv - encrypted_data = cipher.update(serializer.dump(value)) + encrypted_data = cipher.update(@serializer.dump(value)) encrypted_data << cipher.final [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--") @@ -47,7 +50,7 @@ module ActiveSupport decrypted_data = cipher.update(encrypted_data) decrypted_data << cipher.final - serializer.load(decrypted_data) + @serializer.load(decrypted_data) rescue OpenSSLCipherError, TypeError raise InvalidMessage end diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 0181070479..57317028fc 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -26,12 +26,15 @@ module ActiveSupport class MessageVerifier class InvalidSignature < StandardError; end - attr_accessor :serializer - - def initialize(secret, digest = 'SHA1', serializer = Marshal) + def initialize(secret, options = {}) + unless options.is_a?(Hash) + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to sepcify the digest algorithm." + options = { :digest => options } + end + @secret = secret - @digest = digest - @serializer = serializer + @digest = options[:digest] || 'SHA1' + @serializer = options[:serializer] || Marshal end def verify(signed_message) @@ -39,14 +42,14 @@ module ActiveSupport data, digest = signed_message.split("--") if data.present? && digest.present? && secure_compare(digest, generate_digest(data)) - serializer.load(ActiveSupport::Base64.decode64(data)) + @serializer.load(ActiveSupport::Base64.decode64(data)) else raise InvalidSignature end end def generate(value) - data = ActiveSupport::Base64.encode64s(serializer.dump(value)) + data = ActiveSupport::Base64.encode64s(@serializer.dump(value)) "#{data}--#{generate_digest(data)}" end diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index 9c89512b42..58f94a7400 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -52,9 +52,9 @@ class MessageEncryptorTest < Test::Unit::TestCase end def test_alternative_serialization_method - @encryptor.serializer = JSONSerializer.new - message = @encryptor.encrypt_and_sign({ :foo => 123, 'bar' => Time.utc(2010) }) - assert_equal @encryptor.decrypt_and_verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } + encryptor = ActiveSupport::MessageEncryptor.new(SecureRandom.hex(64), :serializer => JSONSerializer.new) + message = encryptor.encrypt_and_sign({ :foo => 123, 'bar' => Time.utc(2010) }) + assert_equal encryptor.decrypt_and_verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } end private diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 10a1738786..3dc047c126 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -45,9 +45,9 @@ class MessageVerifierTest < Test::Unit::TestCase end def test_alternative_serialization_method - @verifier.serializer = JSONSerializer.new - message = @verifier.generate({ :foo => 123, 'bar' => Time.utc(2010) }) - assert_equal @verifier.verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } + verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!", :serializer => JSONSerializer.new) + message = verifier.generate({ :foo => 123, 'bar' => Time.utc(2010) }) + assert_equal verifier.verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } end def assert_not_verified(message) -- cgit v1.2.3 From 6d520803ee005d47c876662ba426083e823199ed Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 15:51:30 -0400 Subject: Test deprecation warning when not using an options hash as second parameter. --- activesupport/test/message_encryptor_test.rb | 8 +++++++- activesupport/test/message_verifier_test.rb | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index 58f94a7400..83a19f8106 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -10,7 +10,7 @@ else require 'active_support/time' require 'active_support/json' -class MessageEncryptorTest < Test::Unit::TestCase +class MessageEncryptorTest < ActiveSupport::TestCase class JSONSerializer def dump(value) @@ -57,6 +57,12 @@ class MessageEncryptorTest < Test::Unit::TestCase assert_equal encryptor.decrypt_and_verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } end + def test_digest_algorithm_as_second_parameter_deprecation + assert_deprecated(/options hash/) do + ActiveSupport::MessageEncryptor.new(SecureRandom.hex(64), 'aes-256-cbc') + end + end + private def assert_not_decrypted(value) assert_raise(ActiveSupport::MessageEncryptor::InvalidMessage) do diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 3dc047c126..35747abe5b 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -10,7 +10,7 @@ else require 'active_support/time' require 'active_support/json' -class MessageVerifierTest < Test::Unit::TestCase +class MessageVerifierTest < ActiveSupport::TestCase class JSONSerializer def dump(value) @@ -49,6 +49,12 @@ class MessageVerifierTest < Test::Unit::TestCase message = verifier.generate({ :foo => 123, 'bar' => Time.utc(2010) }) assert_equal verifier.verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } end + + def test_digest_algorithm_as_second_parameter_deprecation + assert_deprecated(/options hash/) do + ActiveSupport::MessageVerifier.new("secret", "SHA1") + end + end def assert_not_verified(message) assert_raise(ActiveSupport::MessageVerifier::InvalidSignature) do -- cgit v1.2.3 From b50394bf844d0520d5dca485b169bba87f6d009a Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Thu, 15 Sep 2011 19:55:52 -0500 Subject: config.action_controller.asset_host shouldn't set to nil during precompile --- actionpack/lib/sprockets/assets.rake | 3 --- railties/test/application/assets_test.rb | 14 -------------- 2 files changed, 17 deletions(-) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 9b2f3a3f94..81223b7ead 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -17,9 +17,6 @@ namespace :assets do # Always compile files Rails.application.config.assets.compile = true - # Always ignore asset host - Rails.application.config.action_controller.asset_host = nil - config = Rails.application.config env = Rails.application.assets target = Pathname.new(File.join(Rails.public_path, config.assets.prefix)) diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 959914bcea..dfd950aae3 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -270,20 +270,6 @@ module ApplicationTests assert_match(/\/assets\/rails-([0-z]+)\.png/, File.read(file)) end - test "precompile ignore asset_host" do - app_file "app/assets/javascripts/application.css.erb", "<%= asset_path 'rails.png' %>" - add_to_config "config.action_controller.asset_host = Proc.new { |source, request| 'http://www.example.com/' }" - - capture(:stdout) do - Dir.chdir(app_path){ `bundle exec rake assets:precompile` } - end - - file = Dir["#{app_path}/public/assets/application.css"].first - content = File.read(file) - assert_match(/\/assets\/rails.png/, content) - assert_no_match(/www\.example\.com/, content) - end - test "precompile should handle utf8 filenames" do app_file "app/assets/images/レイルズ.png", "not a image really" add_to_config "config.assets.precompile = [ /\.png$$/, /application.(css|js)$/ ]" -- cgit v1.2.3 From 28677014a4f8121272a17870246507e86e46837c Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Thu, 15 Sep 2011 20:07:01 -0500 Subject: Add reference about --skip-sprockets to Asset Pipeline Guide --- railties/guides/source/asset_pipeline.textile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index ce4eafb97c..74dfdfb540 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -25,6 +25,12 @@ In Rails 3.1, the asset pipeline is enabled by default. It can be disabled in +a config.assets.enabled = false +You can also disable it when you are creating a new application passing the --skip-sprockets parameter: + + +rails new appname --skip-sprockets + + It is recommended that you use the defaults for all new apps. -- cgit v1.2.3 From c9aac2a215d46d25556a6a0eaae1b9f85231a6b4 Mon Sep 17 00:00:00 2001 From: Peter Suschlik Date: Fri, 16 Sep 2011 09:08:53 +0300 Subject: Fix typo in deprecation warning. --- activesupport/lib/active_support/message_encryptor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 7637cfe2b0..e14386a85d 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -15,7 +15,7 @@ module ActiveSupport def initialize(secret, options = {}) unless options.is_a?(Hash) - ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to sepcify the cipher algorithm." + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to specify the cipher algorithm." options = { :cipher => options } end -- cgit v1.2.3 From 302e570777b1ca8f537c96628334dcbe8a94d83f Mon Sep 17 00:00:00 2001 From: Kir Shatrov Date: Fri, 16 Sep 2011 17:43:05 +0400 Subject: "Passing variables into the translation" section added --- railties/guides/source/i18n.textile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile index 76cd14d479..a35cd6c506 100644 --- a/railties/guides/source/i18n.textile +++ b/railties/guides/source/i18n.textile @@ -365,6 +365,20 @@ NOTE: You need to restart the server when you add new locale files. You may use YAML (+.yml+) or plain Ruby (+.rb+) files for storing your translations in SimpleStore. YAML is the preferred option among Rails developers. However, it has one big disadvantage. YAML is very sensitive to whitespace and special characters, so the application may not load your dictionary properly. Ruby files will crash your application on first request, so you may easily find what's wrong. (If you encounter any "weird issues" with YAML dictionaries, try putting the relevant portion of your dictionary into a Ruby file.) +h4. Passing variables into the translation + +You may use translation with parameters, if you want. + + +# app/views/home/index.html.erb +

      <%=t 'greet_username', :user => "Bill", :message => "Goodbye" %>

      +

      <%=t 'greet_username', :user => "DHH", :message => "Hello" %>

      + +# config/locales/en.yml +en: + greet_username: "%{message}, %{user}!" +
      + h4. Adding Date/Time Formats OK! Now let's add a timestamp to the view, so we can demo the *date/time localization* feature as well. To localize the time format you pass the Time object to +I18n.l+ or (preferably) use Rails' +#l+ helper. You can pick a format by passing the +:format+ option -- by default the +:default+ format is used. -- cgit v1.2.3 From b0ae34ad72ed8410e6f16c1d9ee4b04b2630208f Mon Sep 17 00:00:00 2001 From: Claudio Poli Date: Fri, 16 Sep 2011 19:54:48 +0300 Subject: Fix typo in deprecation notice --- activesupport/lib/active_support/message_verifier.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 57317028fc..9d7c81142a 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -28,7 +28,7 @@ module ActiveSupport def initialize(secret, options = {}) unless options.is_a?(Hash) - ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to sepcify the digest algorithm." + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to specify the digest algorithm." options = { :digest => options } end -- cgit v1.2.3 From 8411f631c42de7d6f51d10d997b037b9eff0d1f1 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Fri, 16 Sep 2011 23:22:03 +0530 Subject: minor edit --- railties/guides/source/asset_pipeline.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 74dfdfb540..bea5e494d5 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -25,7 +25,7 @@ In Rails 3.1, the asset pipeline is enabled by default. It can be disabled in +a config.assets.enabled = false -You can also disable it when you are creating a new application passing the --skip-sprockets parameter: +You can also disable it while creating a new application by passing the --skip-sprockets option. rails new appname --skip-sprockets -- cgit v1.2.3 From 27f1320fde03279c575693f504897f1a6171bc59 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Fri, 16 Sep 2011 22:12:41 +0530 Subject: Fixing incorrect notextile tags --- .../guides/source/action_view_overview.textile | 2 +- .../active_record_validations_callbacks.textile | 4 ++-- .../source/active_support_core_extensions.textile | 26 +++++++++++----------- railties/guides/source/ajax_on_rails.textile | 4 +++- .../source/api_documentation_guidelines.textile | 2 +- railties/guides/source/asset_pipeline.textile | 2 +- railties/guides/source/initialization.textile | 2 +- .../source/ruby_on_rails_guides_guidelines.textile | 2 +- railties/guides/source/security.textile | 6 ++--- 9 files changed, 26 insertions(+), 24 deletions(-) diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index 87250c684b..40cde6ad84 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -898,7 +898,7 @@ h5. select_year Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius can be changed using the +:start_year+ and +:end_year+ keys in the +options+. -# Generates a select field for five years on either side of +Date.today+ that defaults to the current year +# Generates a select field for five years on either side of Date.today that defaults to the current year select_year(Date.today) # Generates a select field from 1900 to 2009 that defaults to the current year diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile index 20f5e52891..5c3aae2955 100644 --- a/railties/guides/source/active_record_validations_callbacks.textile +++ b/railties/guides/source/active_record_validations_callbacks.textile @@ -328,7 +328,7 @@ This helper validates that your attributes have only numeric values. By default, If you set +:only_integer+ to +true+, then it will use the -/\A[+-]?\d+\Z/ +/\A[-]?\d\Z/ regular expression to validate the attribute's value. Otherwise, it will try to convert the value to a number using +Float+. @@ -597,7 +597,7 @@ The easiest way to add custom validators for validating individual attributes is class EmailValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) - unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i + unless value =~ /\A([^@\s])@((?:[-a-z0-9]\.)+[a-z]{2,})\z/i record.errors[attribute] << (options[:message] || "is not an email") end end diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index d006cc9214..b3d8760a73 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -296,7 +296,7 @@ This method escapes whatever is needed, both for the key and the value: account.to_query('company[name]') -# => "company%5Bname%5D=Johnson+%26+Johnson" +# => "company%5Bname%5D=Johnson%26Johnson" so its output is ready to be used in a query string. @@ -3385,11 +3385,11 @@ They are analogous. Please refer to their documentation above and take into acco Time.zone_default # => # -# In Barcelona, 2010/03/28 02:00 +0100 becomes 2010/03/28 03:00 +0200 due to DST. +# In Barcelona, 2010/03/28 02:00 0100 becomes 2010/03/28 03:00 0200 due to DST. t = Time.local_time(2010, 3, 28, 1, 59, 59) -# => Sun Mar 28 01:59:59 +0100 2010 +# => Sun Mar 28 01:59:59 0100 2010 t.advance(:seconds => 1) -# => Sun Mar 28 03:00:00 +0200 2010 +# => Sun Mar 28 03:00:00 0200 2010 * If +since+ or +ago+ jump to a time that can't be expressed with +Time+ a +DateTime+ object is returned instead. @@ -3406,24 +3406,24 @@ The method +all_day+ returns a range representing the whole day of the current t now = Time.current -# => Mon, 09 Aug 2010 23:20:05 UTC +00:00 +# => Mon, 09 Aug 2010 23:20:05 UTC 00:00 now.all_day -# => Mon, 09 Aug 2010 00:00:00 UTC +00:00..Mon, 09 Aug 2010 23:59:59 UTC +00:00 +# => Mon, 09 Aug 2010 00:00:00 UTC 00:00..Mon, 09 Aug 2010 23:59:59 UTC 00:00 Analogously, +all_week+, +all_month+, +all_quarter+ and +all_year+ all serve the purpose of generating time ranges. now = Time.current -# => Mon, 09 Aug 2010 23:20:05 UTC +00:00 +# => Mon, 09 Aug 2010 23:20:05 UTC 00:00 now.all_week -# => Mon, 09 Aug 2010 00:00:00 UTC +00:00..Sun, 15 Aug 2010 23:59:59 UTC +00:00 +# => Mon, 09 Aug 2010 00:00:00 UTC 00:00..Sun, 15 Aug 2010 23:59:59 UTC 00:00 now.all_month -# => Sat, 01 Aug 2010 00:00:00 UTC +00:00..Tue, 31 Aug 2010 23:59:59 UTC +00:00 +# => Sat, 01 Aug 2010 00:00:00 UTC 00:00..Tue, 31 Aug 2010 23:59:59 UTC 00:00 now.all_quarter -# => Thu, 01 Jul 2010 00:00:00 UTC +00:00..Thu, 30 Sep 2010 23:59:59 UTC +00:00 +# => Thu, 01 Jul 2010 00:00:00 UTC 00:00..Thu, 30 Sep 2010 23:59:59 UTC 00:00 now.all_year -# => Fri, 01 Jan 2010 00:00:00 UTC +00:00..Fri, 31 Dec 2010 23:59:59 UTC +00:00 +# => Fri, 01 Jan 2010 00:00:00 UTC 00:00..Fri, 31 Dec 2010 23:59:59 UTC 00:00 h4. Time Constructors @@ -3434,7 +3434,7 @@ Active Support defines +Time.current+ to be +Time.zone.now+ if there's a user ti Time.zone_default # => # Time.current -# => Fri, 06 Aug 2010 17:11:58 CEST +02:00 +# => Fri, 06 Aug 2010 17:11:58 CEST 02:00 Analogously to +DateTime+, the predicates +past?+, and +future?+ are relative to +Time.current+. @@ -3445,7 +3445,7 @@ Use the +local_time+ class method to create time objects honoring the user time Time.zone_default # => # Time.local_time(2010, 8, 15) -# => Sun Aug 15 00:00:00 +0200 2010 +# => Sun Aug 15 00:00:00 0200 2010 The +utc_time+ class method returns a time in UTC: diff --git a/railties/guides/source/ajax_on_rails.textile b/railties/guides/source/ajax_on_rails.textile index 77f7661deb..29d4fae888 100644 --- a/railties/guides/source/ajax_on_rails.textile +++ b/railties/guides/source/ajax_on_rails.textile @@ -104,7 +104,7 @@ Note that if we wouldn't override the default behavior (POST), the above snippet link_to_remote "Update record", :url => record_url(record), :method => :put, - :with => "'status=' + 'encodeURIComponent($('status').value) + '&completed=' + $('completed')" + :with => "'status=' 'encodeURIComponent($('status').value) '&completed=' $('completed')" This generates a remote link which adds 2 parameters to the standard URL generated by Rails, taken from the page (contained in the elements matched by the 'status' and 'completed' DOM id). @@ -124,6 +124,7 @@ link_to_remote "Add new item", 404 => "alert('Item not found!')" Let's see a typical example for the most frequent callbacks, +:success+, +:failure+ and +:complete+ in action: + link_to_remote "Add new item", :url => items_url, @@ -133,6 +134,7 @@ link_to_remote "Add new item", :success => "display_item_added(request)", :failure => "display_error(request)" + ** *:type* If you want to fire a synchronous request for some obscure reason (blocking the browser while the request is processed and doesn't return a status code), you can use the +:type+ option with the value of +:synchronous+. * Finally, using the +html_options+ parameter you can add HTML attributes to the generated tag. It works like the same parameter of the +link_to+ helper. There are interesting side effects for the +href+ and +onclick+ parameters though: ** If you specify the +href+ parameter, the AJAX link will degrade gracefully, i.e. the link will point to the URL even if JavaScript is disabled in the client browser diff --git a/railties/guides/source/api_documentation_guidelines.textile b/railties/guides/source/api_documentation_guidelines.textile index c0f709eda8..99eb668513 100644 --- a/railties/guides/source/api_documentation_guidelines.textile +++ b/railties/guides/source/api_documentation_guidelines.textile @@ -146,7 +146,7 @@ h3. Description Lists In lists of options, parameters, etc. use a hyphen between the item and its description (reads better than a colon because normally options are symbols): -# * :allow_nil - Skip validation if attribute is +nil+. +# * :allow_nil - Skip validation if attribute is nil. The description starts in upper case and ends with a full stop—it's standard English. diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index bea5e494d5..e03ae736a8 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -359,7 +359,7 @@ NOTE. If you are precompiling your assets locally, you can use +bundle install - The default matcher for compiling files includes +application.js+, +application.css+ and all files that do not end in +js+ or +css+: -[ /\w+\.(?!js|css).+/, /application.(css|js)$/ ] +[ /\w\.(?!js|css)./, /application.(css|js)$/ ] If you have other manifests or individual stylesheets and JavaScript files to include, you can add them to the +precompile+ array: diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 8aabc3ae91..32b41fdd2c 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -450,7 +450,7 @@ run YourApp::Application The +Rack::Builder.parse_file+ method here takes the content from this +config.ru+ file and parses it using this code: -app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", +app = eval "Rack::Builder.new {( " cfgfile "\n )}.to_app", TOPLEVEL_BINDING, config diff --git a/railties/guides/source/ruby_on_rails_guides_guidelines.textile b/railties/guides/source/ruby_on_rails_guides_guidelines.textile index e63f564c83..29aefd25f8 100644 --- a/railties/guides/source/ruby_on_rails_guides_guidelines.textile +++ b/railties/guides/source/ruby_on_rails_guides_guidelines.textile @@ -26,7 +26,7 @@ h5. When are Objects Saved? Use the same typography as in regular text: -h6. The +:content_type+ Option +h6. The :content_type Option h3. API Documentation Guidelines diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile index 4cf9e2a7f3..73c7a80ff6 100644 --- a/railties/guides/source/security.textile +++ b/railties/guides/source/security.textile @@ -582,7 +582,7 @@ Ruby uses a slightly different approach than many other languages to match the e class File < ActiveRecord::Base - validates :name, :format => /^[\w\.\-\+]+$/ + validates :name, :format => /^[\w\.\-\]$/ end @@ -595,7 +595,7 @@ file.txt%0A Whereas %0A is a line feed in URL encoding, so Rails automatically converts it to "file.txt\n<script>alert('hello')</script>". This file name passes the filter because the regular expression matches – up to the line end, the rest does not matter. The correct expression should read: -/\A[\w\.\-\+]+\z/ +/\A[\w\.\-\]\z/ h4. Privilege Escalation @@ -762,7 +762,7 @@ These examples don't do any harm so far, so let's see how an attacker can steal For an attacker, of course, this is not useful, as the victim will see his own cookie. The next example will try to load an image from the URL http://www.attacker.com/ plus the cookie. Of course this URL does not exist, so the browser displays nothing. But the attacker can review his web server's access log files to see the victim's cookie. - + The log files on www.attacker.com will read like this: -- cgit v1.2.3 From 3a04e370e4cc016bb7b59fe6bb704e4ca37d62f3 Mon Sep 17 00:00:00 2001 From: brainopia Date: Fri, 16 Sep 2011 22:59:16 +0400 Subject: Fix Hash#to_query edge case with html_safe string on 1.8 ruby --- activesupport/lib/active_support/core_ext/object/to_query.rb | 2 +- activesupport/test/core_ext/object/to_query_test.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/core_ext/object/to_query.rb b/activesupport/lib/active_support/core_ext/object/to_query.rb index 3f1540f685..5d5fcf00e0 100644 --- a/activesupport/lib/active_support/core_ext/object/to_query.rb +++ b/activesupport/lib/active_support/core_ext/object/to_query.rb @@ -7,7 +7,7 @@ class Object # Note: This method is defined as a default implementation for all Objects for Hash#to_query to work. def to_query(key) require 'cgi' unless defined?(CGI) && defined?(CGI::escape) - "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}" + "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}" end end diff --git a/activesupport/test/core_ext/object/to_query_test.rb b/activesupport/test/core_ext/object/to_query_test.rb index 84da52f4bf..c146f6cc9b 100644 --- a/activesupport/test/core_ext/object/to_query_test.rb +++ b/activesupport/test/core_ext/object/to_query_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'active_support/ordered_hash' require 'active_support/core_ext/object/to_query' +require 'active_support/core_ext/string/output_safety.rb' class ToQueryTest < Test::Unit::TestCase def test_simple_conversion @@ -11,6 +12,14 @@ class ToQueryTest < Test::Unit::TestCase assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d' end + def test_html_safe_parameter_key + assert_query_equal 'a%3Ab=c+d', 'a:b'.html_safe => 'c d' + end + + def test_html_safe_parameter_value + assert_query_equal 'a=%5B10%5D', 'a' => '[10]'.html_safe + end + def test_nil_parameter_value empty = Object.new def empty.to_param; nil end -- cgit v1.2.3 From 18116791d00d693643db3b4a99ae1d245c5a6c33 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 16 Sep 2011 17:25:40 -0700 Subject: Proper lines numbers for stack trace info --- activesupport/lib/active_support/core_ext/string/output_safety.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 05b39b89bf..3ae3d64fa4 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -142,7 +142,7 @@ module ActiveSupport #:nodoc: end UNSAFE_STRING_METHODS.each do |unsafe_method| - class_eval <<-EOT, __FILE__, __LINE__ + class_eval <<-EOT, __FILE__, __LINE__ + 1 def #{unsafe_method}(*args, &block) # def capitalize(*args, &block) to_str.#{unsafe_method}(*args, &block) # to_str.gsub(*args, &block) end # end -- cgit v1.2.3 From 6e63e029b335b1a5dfce43c20de27ca6fae29fa4 Mon Sep 17 00:00:00 2001 From: Alex Yakoubian Date: Wed, 14 Sep 2011 23:14:23 -0700 Subject: Default precompile regexp that properly matches application.js and application.css --- railties/lib/rails/application/configuration.rb | 2 +- railties/test/application/assets_test.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index a48db3b6d2..141b39fb4b 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -38,7 +38,7 @@ module Rails @assets.enabled = false @assets.paths = [] @assets.precompile = [ Proc.new{ |path| !File.extname(path).in?(['.js', '.css']) }, - /application.(css|js)$/ ] + /(?:\/|\\|\A)application\.(css|js)$/ ] @assets.prefix = "/assets" @assets.version = '' @assets.debug = false diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index dfd950aae3..a62ef1e70e 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -68,6 +68,10 @@ module ApplicationTests test "precompile application.js and application.css and all other files not ending with .js or .css by default" do app_file "app/assets/javascripts/application.js", "alert();" app_file "app/assets/stylesheets/application.css", "body{}" + + app_file "app/assets/javascripts/someapplication.js", "alert();" + app_file "app/assets/stylesheets/someapplication.css", "body{}" + app_file "app/assets/javascripts/something.min.js", "alert();" app_file "app/assets/stylesheets/something.min.css", "body{}" @@ -87,8 +91,13 @@ module ApplicationTests images_should_compile.each do |filename| assert File.exists?("#{app_path}/public/assets/#{filename}") end + assert File.exists?("#{app_path}/public/assets/application.js") assert File.exists?("#{app_path}/public/assets/application.css") + + assert !File.exists?("#{app_path}/public/assets/someapplication.js") + assert !File.exists?("#{app_path}/public/assets/someapplication.css") + assert !File.exists?("#{app_path}/public/assets/something.min.js") assert !File.exists?("#{app_path}/public/assets/something.min.css") end -- cgit v1.2.3 From 663031801cac577a88931cdfe6f062555112f370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?U=C4=A3is=20Ozols?= Date: Sat, 17 Sep 2011 10:00:53 +0300 Subject: sass-rails helpers - hyphenated in Sass, underscored in Ruby. --- railties/guides/source/asset_pipeline.textile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index e03ae736a8..586a9f46eb 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -170,15 +170,15 @@ Note that the closing tag cannot be of the style +-%>+. h5. CSS and Sass -When using the asset pipeline, paths to assets must be re-written and +sass-rails+ provides +_url+ and +_path+ helpers for the following asset classes: image, font, video, audio, JavaScript and stylesheet. +When using the asset pipeline, paths to assets must be re-written and +sass-rails+ provides +-url+ and +-path+ helpers (hyphenated in Sass, underscored in Ruby) for the following asset classes: image, font, video, audio, JavaScript and stylesheet. -* +image_url("rails.png")+ becomes +url(/assets/rails.png)+. -* +image_path("rails.png")+ becomes +"/assets/rails.png"+. +* +image-url("rails.png")+ becomes +url(/assets/rails.png)+ +* +image-path("rails.png")+ becomes +"/assets/rails.png"+. The more generic form can also be used but the asset path and class must both be specified: -* +asset_url("rails.png", image)+ becomes +url(/assets/rails.png)+. -* +asset_path("rails.png", image)+ becomes +"/assets/rails.png"+. +* +asset-url("rails.png", image)+ becomes +url(/assets/rails.png)+ +* +asset-path("rails.png", image)+ becomes +"/assets/rails.png"+ h5. JavaScript/CoffeeScript and ERB -- cgit v1.2.3 From b2bf725d795634fb2383f3a4fa5ab5e9c61c54f1 Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Sat, 17 Sep 2011 18:39:30 +0530 Subject: Bump AR-JDBC version. THis version is compatible with 3.1 and above --- Gemfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 5ce420c3a3..508d083fe6 100644 --- a/Gemfile +++ b/Gemfile @@ -75,7 +75,7 @@ end platforms :jruby do gem "ruby-debug", ">= 0.10.3" gem "json" - gem "activerecord-jdbcsqlite3-adapter" + gem "activerecord-jdbcsqlite3-adapter", ">= 1.2.0" # This is needed by now to let tests work on JRuby # TODO: When the JRuby guys merge jruby-openssl in @@ -83,8 +83,8 @@ platforms :jruby do gem "jruby-openssl" group :db do - gem "activerecord-jdbcmysql-adapter" - gem "activerecord-jdbcpostgresql-adapter" + gem "activerecord-jdbcmysql-adapter", ">= 1.2.0" + gem "activerecord-jdbcpostgresql-adapter", ">= 1.2.0" end end -- cgit v1.2.3 From afa78fe327e166a6aca10111a56101f74a6a6c8a Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Sun, 18 Sep 2011 00:23:48 +0530 Subject: Fixed test for JRuby. for Sqlite3 in AR-JDBC.It's Jdbc::SQLite3::VERSION --- activerecord/test/cases/query_cache_test.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index e3ad0cad90..cda30a773e 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -148,12 +148,13 @@ class QueryCacheTest < ActiveRecord::TestCase def test_cache_does_not_wrap_string_results_in_arrays require 'sqlite3/version' if current_adapter?(:SQLite3Adapter) + sqlite3_version = RUBY_PLATFORM =~ /java/ ? Jdbc::SQLite3::VERSION : SQLite3::VERSION Task.cache do # Oracle adapter returns count() as Fixnum or Float if current_adapter?(:OracleAdapter) assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") - elsif current_adapter?(:SQLite3Adapter) && SQLite3::VERSION > '1.2.5' || current_adapter?(:Mysql2Adapter) || current_adapter?(:MysqlAdapter) + elsif current_adapter?(:SQLite3Adapter) && sqlite3_version > '1.2.5' || current_adapter?(:Mysql2Adapter) || current_adapter?(:MysqlAdapter) # Future versions of the sqlite3 adapter will return numeric assert_instance_of Fixnum, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") -- cgit v1.2.3 From 908f2616d5c2b9e26eb180859f7df529a7a59f08 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 14 Sep 2011 18:53:08 +1000 Subject: Document ActiveRecord::QueryMethods#select --- .../lib/active_record/relation/query_methods.rb | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index a11b7a3864..4468a38ee6 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -37,6 +37,35 @@ module ActiveRecord relation end + # Works in two unique ways. + # + # First: takes a block so it can be used just like Array#select. + # + # Model.scoped.select { |m| m.field == value } + # + # This will build an array of objects from the database for the scope, + # converting them into an array and iterating through them using Array#select. + # + # Second: Modifies the SELECT statement for the query so that only certain + # fields are retreived: + # + # >> Model.select(:field) + # => [#] + # + # Although in the above example it looks as though this method returns an + # array, in actual fact it returns a relation object and can have other query + # methods appended to it, such as the other methods in ActiveRecord::QueryMethods. + # + # This method will also take multiple parameters: + # + # >> Model.select(:field, :other_field, :and_one_more) + # => [#] + # + # Any attributes that do not have fields retreived by a select + # will return `nil` when the getter method for that attribute is used: + # + # >> Model.select(:field).first.other_field + # => nil def select(value = Proc.new) if block_given? to_a.select {|*block_args| value.call(*block_args) } -- cgit v1.2.3 From ea29968bcfa455d9bef8c41436b6bea669dfc06d Mon Sep 17 00:00:00 2001 From: Jan Vlnas Date: Sun, 18 Sep 2011 16:41:21 +0300 Subject: Locale code for Czech is ":cs" --- railties/guides/source/i18n.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile index a35cd6c506..14ce6a19d5 100644 --- a/railties/guides/source/i18n.textile +++ b/railties/guides/source/i18n.textile @@ -91,7 +91,7 @@ This means, that in the +:en+ locale, the key _hello_ will map to the _Hello wor The I18n library will use *English* as a *default locale*, i.e. if you don't set a different locale, +:en+ will be used for looking up translations. -NOTE: The i18n library takes a *pragmatic approach* to locale keys (after "some discussion":http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en), including only the _locale_ ("language") part, like +:en+, +:pl+, not the _region_ part, like +:en-US+ or +:en-UK+, which are traditionally used for separating "languages" and "regional setting" or "dialects". Many international applications use only the "language" element of a locale such as +:cz+, +:th+ or +:es+ (for Czech, Thai and Spanish). However, there are also regional differences within different language groups that may be important. For instance, in the +:en-US+ locale you would have $ as a currency symbol, while in +:en-UK+, you would have £. Nothing stops you from separating regional and other settings in this way: you just have to provide full "English - United Kingdom" locale in a +:en-UK+ dictionary. Various "Rails I18n plugins":http://rails-i18n.org/wiki such as "Globalize2":https://github.com/joshmh/globalize2/tree/master may help you implement it. +NOTE: The i18n library takes a *pragmatic approach* to locale keys (after "some discussion":http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en), including only the _locale_ ("language") part, like +:en+, +:pl+, not the _region_ part, like +:en-US+ or +:en-UK+, which are traditionally used for separating "languages" and "regional setting" or "dialects". Many international applications use only the "language" element of a locale such as +:cs+, +:th+ or +:es+ (for Czech, Thai and Spanish). However, there are also regional differences within different language groups that may be important. For instance, in the +:en-US+ locale you would have $ as a currency symbol, while in +:en-UK+, you would have £. Nothing stops you from separating regional and other settings in this way: you just have to provide full "English - United Kingdom" locale in a +:en-UK+ dictionary. Various "Rails I18n plugins":http://rails-i18n.org/wiki such as "Globalize2":https://github.com/joshmh/globalize2/tree/master may help you implement it. The *translations load path* (+I18n.load_path+) is just a Ruby Array of paths to your translation files that will be loaded automatically and available in your application. You can pick whatever directory and translation file naming scheme makes sense for you. -- cgit v1.2.3 From 51bef9d8fb0b4da7a104425ab8545e9331387743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 18 Sep 2011 09:09:01 -0700 Subject: to_xml should also rely on serializable hash. --- activemodel/lib/active_model/serializers/xml.rb | 46 +++++++--------------- .../cases/serializers/xml_serialization_test.rb | 17 ++++++++ .../active_record/serializers/xml_serializer.rb | 2 +- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index 64dda3bcee..d61d9d7119 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -15,10 +15,10 @@ module ActiveModel class Attribute #:nodoc: attr_reader :name, :value, :type - def initialize(name, serializable, raw_value=nil) + def initialize(name, serializable, value) @name, @serializable = name, serializable - raw_value = raw_value.in_time_zone if raw_value.respond_to?(:in_time_zone) - @value = raw_value || @serializable.send(name) + value = value.in_time_zone if value.respond_to?(:in_time_zone) + @value = value @type = compute_type end @@ -49,40 +49,24 @@ module ActiveModel def initialize(serializable, options = nil) @serializable = serializable @options = options ? options.dup : {} - - @options[:only] = Array.wrap(@options[:only]).map { |n| n.to_s } - @options[:except] = Array.wrap(@options[:except]).map { |n| n.to_s } end - # To replicate the behavior in ActiveRecord#attributes, :except - # takes precedence over :only. If :only is not set - # for a N level model but is set for the N+1 level models, - # then because :except is set to a default value, the second - # level model can have both :except and :only set. So if - # :only is set, always delete :except. - def attributes_hash - attributes = @serializable.attributes - if options[:only].any? - attributes.slice(*options[:only]) - elsif options[:except].any? - attributes.except(*options[:except]) - else - attributes - end + def serializable_hash + @serializable.serializable_hash(@options.except(:include)) end - def serializable_attributes - attributes_hash.map do |name, value| - self.class::Attribute.new(name, @serializable, value) + def serializable_collection + methods = Array.wrap(options[:methods]).map(&:to_s) + serializable_hash.map do |name, value| + name = name.to_s + if methods.include?(name) + self.class::MethodAttribute.new(name, @serializable, value) + else + self.class::Attribute.new(name, @serializable, value) + end end end - def serializable_methods - Array.wrap(options[:methods]).map do |name| - self.class::MethodAttribute.new(name.to_s, @serializable) if @serializable.respond_to?(name.to_s) - end.compact - end - def serialize require 'builder' unless defined? ::Builder @@ -114,7 +98,7 @@ module ActiveModel end def add_attributes_and_methods - (serializable_attributes + serializable_methods).each do |attribute| + serializable_collection.each do |attribute| key = ActiveSupport::XmlMini.rename_key(attribute.name, options) ActiveSupport::XmlMini.to_tag(key, attribute.value, options.merge(attribute.decorations)) diff --git a/activemodel/test/cases/serializers/xml_serialization_test.rb b/activemodel/test/cases/serializers/xml_serialization_test.rb index a38ef8e223..fc73d9dcd8 100644 --- a/activemodel/test/cases/serializers/xml_serialization_test.rb +++ b/activemodel/test/cases/serializers/xml_serialization_test.rb @@ -33,6 +33,12 @@ class Address end end +class SerializableContact < Contact + def serializable_hash(options={}) + super(options.merge(:only => [:name, :age])) + end +end + class XmlSerializationTest < ActiveModel::TestCase def setup @contact = Contact.new @@ -96,6 +102,17 @@ class XmlSerializationTest < ActiveModel::TestCase assert_match %r{aaron stack}, @xml + assert_match %r{25}, @xml + assert_no_match %r{}, @xml + end + test "should allow skipped types" do @xml = @contact.to_xml :skip_types => true assert_match %r{25}, @xml diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb index cbfa1ad609..0e7f57aa43 100644 --- a/activerecord/lib/active_record/serializers/xml_serializer.rb +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb @@ -179,7 +179,7 @@ module ActiveRecord #:nodoc: class XmlSerializer < ActiveModel::Serializers::Xml::Serializer #:nodoc: def initialize(*args) super - options[:except] |= Array.wrap(@serializable.class.inheritance_column) + options[:except] = Array.wrap(options[:except]) | Array.wrap(@serializable.class.inheritance_column) end class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc: -- cgit v1.2.3 From d589d9f16045e535d5cefc5ae34b5d4340c17d80 Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Sun, 18 Sep 2011 23:20:09 +0530 Subject: fix test error when running with postgresql. This Sqlite3 should be in if block. Was giving error because sqlite3 is not loaded --- activerecord/test/cases/query_cache_test.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index cda30a773e..7feac2b920 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -147,8 +147,10 @@ class QueryCacheTest < ActiveRecord::TestCase end def test_cache_does_not_wrap_string_results_in_arrays - require 'sqlite3/version' if current_adapter?(:SQLite3Adapter) - sqlite3_version = RUBY_PLATFORM =~ /java/ ? Jdbc::SQLite3::VERSION : SQLite3::VERSION + if current_adapter?(:SQLite3Adapter) + require 'sqlite3/version' + sqlite3_version = RUBY_PLATFORM =~ /java/ ? Jdbc::SQLite3::VERSION : SQLite3::VERSION + end Task.cache do # Oracle adapter returns count() as Fixnum or Float -- cgit v1.2.3 From 8e3d26733b8eb05e09c52c4533db6c2cfe8b07eb Mon Sep 17 00:00:00 2001 From: brainopia Date: Sun, 18 Sep 2011 23:37:27 +0400 Subject: Fix test to reflect use of to_param for keys --- activesupport/test/core_ext/hash_ext_test.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 1813ba2a4d..fa800eada2 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -9,7 +9,7 @@ require 'active_support/inflections' class HashExtTest < Test::Unit::TestCase class IndifferentHash < HashWithIndifferentAccess end - + class SubclassingArray < Array end @@ -272,14 +272,14 @@ class HashExtTest < Test::Unit::TestCase hash = { "urls" => { "url" => [ { "address" => "1" }, { "address" => "2" } ] }}.with_indifferent_access assert_equal "1", hash[:urls][:url].first[:address] end - + def test_should_preserve_array_subclass_when_value_is_array array = SubclassingArray.new array << { "address" => "1" } hash = { "urls" => { "url" => array }}.with_indifferent_access assert_equal SubclassingArray, hash[:urls][:url].class end - + def test_should_preserve_array_class_when_hash_value_is_frozen_array array = SubclassingArray.new array << { "address" => "1" } @@ -543,7 +543,7 @@ class HashExtToParamTests < Test::Unit::TestCase end def test_to_param_hash - assert_equal 'custom2=param2-1&custom=param-1', {ToParam.new('custom') => ToParam.new('param'), ToParam.new('custom2') => ToParam.new('param2')}.to_param + assert_equal 'custom-1=param-1&custom2-1=param2-1', {ToParam.new('custom') => ToParam.new('param'), ToParam.new('custom2') => ToParam.new('param2')}.to_param end def test_to_param_hash_escapes_its_keys_and_values @@ -955,13 +955,13 @@ class HashToXmlTest < Test::Unit::TestCase hash = Hash.from_xml(xml) assert_equal "bacon is the best", hash['blog']['name'] end - + def test_empty_cdata_from_xml xml = "" - + assert_equal "", Hash.from_xml(xml)["data"] end - + def test_xsd_like_types_from_xml bacon_xml = <<-EOT @@ -1004,7 +1004,7 @@ class HashToXmlTest < Test::Unit::TestCase assert_equal expected_product_hash, Hash.from_xml(product_xml)["product"] end - + def test_should_use_default_value_for_unknown_key hash_wia = HashWithIndifferentAccess.new(3) assert_equal 3, hash_wia[:new_key] -- cgit v1.2.3 From 7ed97bc8149f745317a897304c8c86f0e3bba4d2 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Tue, 20 Sep 2011 19:33:01 +0530 Subject: remove unnecessary markup --- .../guides/source/active_support_core_extensions.textile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index b3d8760a73..e81fe13010 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -3387,9 +3387,9 @@ Time.zone_default # In Barcelona, 2010/03/28 02:00 0100 becomes 2010/03/28 03:00 0200 due to DST. t = Time.local_time(2010, 3, 28, 1, 59, 59) -# => Sun Mar 28 01:59:59 0100 2010 +# => Sun Mar 28 01:59:59 +0100 2010 t.advance(:seconds => 1) -# => Sun Mar 28 03:00:00 0200 2010 +# => Sun Mar 28 03:00:00 +0200 2010 * If +since+ or +ago+ jump to a time that can't be expressed with +Time+ a +DateTime+ object is returned instead. @@ -3406,7 +3406,7 @@ The method +all_day+ returns a range representing the whole day of the current t now = Time.current -# => Mon, 09 Aug 2010 23:20:05 UTC 00:00 +# => Mon, 09 Aug 2010 23:20:05 UTC +00:00 now.all_day # => Mon, 09 Aug 2010 00:00:00 UTC 00:00..Mon, 09 Aug 2010 23:59:59 UTC 00:00 @@ -3415,7 +3415,7 @@ Analogously, +all_week+, +all_month+, +all_quarter+ and +all_year+ all serve the now = Time.current -# => Mon, 09 Aug 2010 23:20:05 UTC 00:00 +# => Mon, 09 Aug 2010 23:20:05 UTC +00:00 now.all_week # => Mon, 09 Aug 2010 00:00:00 UTC 00:00..Sun, 15 Aug 2010 23:59:59 UTC 00:00 now.all_month @@ -3434,7 +3434,7 @@ Active Support defines +Time.current+ to be +Time.zone.now+ if there's a user ti Time.zone_default # => # Time.current -# => Fri, 06 Aug 2010 17:11:58 CEST 02:00 +# => Fri, 06 Aug 2010 17:11:58 CEST +02:00 Analogously to +DateTime+, the predicates +past?+, and +future?+ are relative to +Time.current+. @@ -3445,7 +3445,7 @@ Use the +local_time+ class method to create time objects honoring the user time Time.zone_default # => # Time.local_time(2010, 8, 15) -# => Sun Aug 15 00:00:00 0200 2010 +# => Sun Aug 15 00:00:00 +0200 2010 The +utc_time+ class method returns a time in UTC: -- cgit v1.2.3 From ed1ada84ac5b443ef979c14a4d0f1a8a57fe9ab9 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Tue, 20 Sep 2011 19:39:46 +0530 Subject: copy edits 908f2616 --- activerecord/lib/active_record/relation/query_methods.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 4468a38ee6..670ba0987d 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -47,21 +47,21 @@ module ActiveRecord # converting them into an array and iterating through them using Array#select. # # Second: Modifies the SELECT statement for the query so that only certain - # fields are retreived: + # fields are retrieved: # # >> Model.select(:field) # => [#] # # Although in the above example it looks as though this method returns an - # array, in actual fact it returns a relation object and can have other query + # array, it actually returns a relation object and can have other query # methods appended to it, such as the other methods in ActiveRecord::QueryMethods. # # This method will also take multiple parameters: # # >> Model.select(:field, :other_field, :and_one_more) - # => [#] + # => [#] # - # Any attributes that do not have fields retreived by a select + # Any attributes that do not have fields retrieved by a select # will return `nil` when the getter method for that attribute is used: # # >> Model.select(:field).first.other_field -- cgit v1.2.3 From 5684ecf74966d81e6fa7193689881b5243cbbc39 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Tue, 20 Sep 2011 19:47:33 +0530 Subject: copy edits 302e5707 --- railties/guides/source/i18n.textile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile index 14ce6a19d5..11e1473ba2 100644 --- a/railties/guides/source/i18n.textile +++ b/railties/guides/source/i18n.textile @@ -365,14 +365,13 @@ NOTE: You need to restart the server when you add new locale files. You may use YAML (+.yml+) or plain Ruby (+.rb+) files for storing your translations in SimpleStore. YAML is the preferred option among Rails developers. However, it has one big disadvantage. YAML is very sensitive to whitespace and special characters, so the application may not load your dictionary properly. Ruby files will crash your application on first request, so you may easily find what's wrong. (If you encounter any "weird issues" with YAML dictionaries, try putting the relevant portion of your dictionary into a Ruby file.) -h4. Passing variables into the translation +h4. Passing variables to translations -You may use translation with parameters, if you want. +You can use variables in the translation messages and pass their values from the view. # app/views/home/index.html.erb -

      <%=t 'greet_username', :user => "Bill", :message => "Goodbye" %>

      -

      <%=t 'greet_username', :user => "DHH", :message => "Hello" %>

      +<%=t 'greet_username', :user => "Bill", :message => "Goodbye" %> # config/locales/en.yml en: -- cgit v1.2.3 From 857d20efdab98cf56b777e034e1f150187c5fe9a Mon Sep 17 00:00:00 2001 From: Guillermo Iguaran Date: Tue, 20 Sep 2011 02:12:29 -0500 Subject: Move precompile task to Sprockets::StaticCompiler --- actionpack/lib/sprockets/assets.rake | 24 ++----------- actionpack/lib/sprockets/railtie.rb | 1 + actionpack/lib/sprockets/static_compiler.rb | 53 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 actionpack/lib/sprockets/static_compiler.rb diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index 81223b7ead..e38ac6b489 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -20,30 +20,10 @@ namespace :assets do config = Rails.application.config env = Rails.application.assets target = Pathname.new(File.join(Rails.public_path, config.assets.prefix)) - manifest = {} manifest_path = config.assets.manifest || target - config.assets.precompile.each do |path| - env.each_logical_path do |logical_path| - if path.is_a?(Regexp) - next unless path.match(logical_path) - elsif path.is_a?(Proc) - next unless path.call(logical_path) - else - next unless File.fnmatch(path.to_s, logical_path) - end - - if asset = env.find_asset(logical_path) - asset_path = config.assets.digest ? asset.digest_path : logical_path - manifest[logical_path] = asset_path - filename = target.join(asset_path) - - mkdir_p filename.dirname - asset.write_to(filename) - asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/ - end - end - end + static_compiler = Sprockets::StaticCompiler.new(env, target, :digest => config.assets.digest) + manifest = static_compiler.precompile(config.assets.precompile) File.open("#{manifest_path}/manifest.yml", 'wb') do |f| YAML.dump(manifest, f) diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb index f05d835554..9b31604dbe 100644 --- a/actionpack/lib/sprockets/railtie.rb +++ b/actionpack/lib/sprockets/railtie.rb @@ -2,6 +2,7 @@ module Sprockets autoload :Helpers, "sprockets/helpers" autoload :LazyCompressor, "sprockets/compressors" autoload :NullCompressor, "sprockets/compressors" + autoload :StaticCompiler, "sprockets/static_compiler" # TODO: Get rid of config.assets.enabled class Railtie < ::Rails::Railtie diff --git a/actionpack/lib/sprockets/static_compiler.rb b/actionpack/lib/sprockets/static_compiler.rb new file mode 100644 index 0000000000..fa4f9451df --- /dev/null +++ b/actionpack/lib/sprockets/static_compiler.rb @@ -0,0 +1,53 @@ +require 'fileutils' +require 'pathname' + +module Sprockets + class StaticCompiler + attr_accessor :env, :target, :digest + + def initialize(env, target, options = {}) + @env = env + @target = target + @digest = options.key?(:digest) ? options.delete(:digest) : true + end + + def precompile(paths) + Rails.application.config.assets.digest = digest + manifest = {} + + env.each_logical_path do |logical_path| + next unless precompile_path?(logical_path, paths) + if asset = env.find_asset(logical_path) + manifest[logical_path] = compile(asset) + end + end + manifest + end + + def compile(asset) + asset_path = digest_asset(asset) + filename = target.join(asset_path) + FileUtils.mkdir_p filename.dirname + asset.write_to(filename) + asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/ + asset_path + end + + def precompile_path?(logical_path, paths) + paths.each do |path| + if path.is_a?(Regexp) + return true if path.match(logical_path) + elsif path.is_a?(Proc) + return true if path.call(logical_path) + else + return true if File.fnmatch(path.to_s, logical_path) + end + end + false + end + + def digest_asset(asset) + digest ? asset.digest_path : asset.logical_path + end + end +end -- cgit v1.2.3 From 952bccd1abe142c214605897a14682ae29a16adc Mon Sep 17 00:00:00 2001 From: Waynn Lue Date: Wed, 21 Sep 2011 01:23:58 -0700 Subject: add "the" to mirror the structure of the other two points --- railties/README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/README.rdoc b/railties/README.rdoc index 501541eb06..95c43045b0 100644 --- a/railties/README.rdoc +++ b/railties/README.rdoc @@ -6,7 +6,7 @@ Railties is responsible for gluing all frameworks together. Overall, it: * manages the +rails+ command line interface; -* and provides Rails generators core. +* and provides the Rails generators core. == Download -- cgit v1.2.3 From 564d7edf690ab60e439df7d7dfebc5144d8d1867 Mon Sep 17 00:00:00 2001 From: Waynn Lue Date: Wed, 21 Sep 2011 01:28:59 -0700 Subject: add a '.' to etc --- railties/guides/source/i18n.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile index 11e1473ba2..81d2ba9a56 100644 --- a/railties/guides/source/i18n.textile +++ b/railties/guides/source/i18n.textile @@ -12,7 +12,7 @@ So, in the process of _internationalizing_ your Rails application you have to: In the process of _localizing_ your application you'll probably want to do the following three things: -* Replace or supplement Rails' default locale -- e.g. date and time formats, month names, Active Record model names, etc +* Replace or supplement Rails' default locale -- e.g. date and time formats, month names, Active Record model names, etc. * Abstract strings in your application into keyed dictionaries -- e.g. flash messages, static text in your views, etc. * Store the resulting dictionaries somewhere -- cgit v1.2.3 From 3c5340ec9cbf12d19e734289ba748186af492d60 Mon Sep 17 00:00:00 2001 From: Waynn Lue Date: Wed, 21 Sep 2011 02:10:07 -0700 Subject: add a missing "on" and remove the "endprologue" text --- railties/guides/source/i18n.textile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile index 81d2ba9a56..46f6942d02 100644 --- a/railties/guides/source/i18n.textile +++ b/railties/guides/source/i18n.textile @@ -16,9 +16,7 @@ In the process of _localizing_ your application you'll probably want to do the f * Abstract strings in your application into keyed dictionaries -- e.g. flash messages, static text in your views, etc. * Store the resulting dictionaries somewhere -This guide will walk you through the I18n API and contains a tutorial how to internationalize a Rails application from the start. - -endprologue. +This guide will walk you through the I18n API and contains a tutorial on how to internationalize a Rails application from the start. NOTE: The Ruby I18n framework provides you with all necessary means for internationalization/localization of your Rails application. You may, however, use any of various plugins and extensions available, which add additional functionality or features. See the Rails "I18n Wiki":http://rails-i18n.org/wiki for more information. -- cgit v1.2.3 From 8d7aee71738fbf1ff090ff44a09624e592b94b04 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 21 Sep 2011 02:19:44 +0530 Subject: indentation fixes --- railties/guides/source/active_support_core_extensions.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index e81fe13010..5aee001545 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -3518,8 +3518,8 @@ h4. +around_[level]+ Takes two arguments, a +before_message+ and +after_message+ and calls the current level method on the +Logger+ instance, passing in the +before_message+, then the specified message, then the +after_message+: - logger = Logger.new("log/development.log") - logger.around_info("before", "after") { |logger| logger.info("during") } +logger = Logger.new("log/development.log") +logger.around_info("before", "after") { |logger| logger.info("during") } h4. +silence+ -- cgit v1.2.3 From 3e80462b95808457eb1584195909e26887a1a40d Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 21 Sep 2011 19:28:36 +0530 Subject: Revert "add a missing "on" and remove the "endprologue" text" This reverts commit 3c5340ec9cbf12d19e734289ba748186af492d60. Reason: endprologue should not have been removed. --- railties/guides/source/i18n.textile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile index 46f6942d02..81d2ba9a56 100644 --- a/railties/guides/source/i18n.textile +++ b/railties/guides/source/i18n.textile @@ -16,7 +16,9 @@ In the process of _localizing_ your application you'll probably want to do the f * Abstract strings in your application into keyed dictionaries -- e.g. flash messages, static text in your views, etc. * Store the resulting dictionaries somewhere -This guide will walk you through the I18n API and contains a tutorial on how to internationalize a Rails application from the start. +This guide will walk you through the I18n API and contains a tutorial how to internationalize a Rails application from the start. + +endprologue. NOTE: The Ruby I18n framework provides you with all necessary means for internationalization/localization of your Rails application. You may, however, use any of various plugins and extensions available, which add additional functionality or features. See the Rails "I18n Wiki":http://rails-i18n.org/wiki for more information. -- cgit v1.2.3 From 8aa537c9452d40aeaf25e6d7e0c5bb1205b05d1a Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Thu, 22 Sep 2011 02:13:04 +0530 Subject: fix incorrect comment --- activesupport/lib/active_support/core_ext/string/output_safety.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 3ae3d64fa4..94999807dd 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -144,7 +144,7 @@ module ActiveSupport #:nodoc: UNSAFE_STRING_METHODS.each do |unsafe_method| class_eval <<-EOT, __FILE__, __LINE__ + 1 def #{unsafe_method}(*args, &block) # def capitalize(*args, &block) - to_str.#{unsafe_method}(*args, &block) # to_str.gsub(*args, &block) + to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block) end # end def #{unsafe_method}!(*args) # def capitalize!(*args) -- cgit v1.2.3 From f373f296d0347f025402049d94901d57987e226c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 21 Sep 2011 15:28:05 -0700 Subject: Slightly reorganize lookup context modules in order to better isolate cache responsibilities. --- actionpack/lib/action_view/lookup_context.rb | 211 ++++++++++++++------------- 1 file changed, 111 insertions(+), 100 deletions(-) diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 9ec410ac2b..a119df003a 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/module/remove_method' module ActionView # = Action View Lookup Context @@ -17,12 +18,11 @@ module ActionView mattr_accessor :registered_details self.registered_details = [] - mattr_accessor :registered_detail_setters - self.registered_detail_setters = [] - def self.register_detail(name, options = {}, &block) self.registered_details << name - self.registered_detail_setters << [name, "#{name}="] + + initialize = registered_details.map { |n| "self.#{n} = details[:#{n}]" } + update = registered_details.map { |n| "self.#{n} = details[:#{n}] if details.key?(:#{n})" } Accessors.send :define_method, :"_#{name}_defaults", &block Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1 @@ -34,6 +34,16 @@ module ActionView value = Array.wrap(value.presence || _#{name}_defaults) _set_detail(:#{name}, value) if value != @details[:#{name}] end + + remove_possible_method :initialize_details + def initialize_details(details) + #{initialize.join("\n")} + end + + remove_possible_method :update_details + def update_details(details) + #{update.join("\n")} + end METHOD end @@ -60,18 +70,53 @@ module ActionView end end - def initialize(view_paths, details = {}, prefixes = []) - @details, @details_key = { :handlers => default_handlers }, nil - @frozen_formats, @skip_default_locale = false, false - @cache = true - @prefixes = prefixes + # Add caching behavior on top of Details. + module DetailsCache + attr_accessor :cache - self.view_paths = view_paths - self.registered_detail_setters.each do |key, setter| - send(setter, details[key]) + # Calculate the details key. Remove the handlers from calculation to improve performance + # since the user cannot modify it explicitly. + def details_key #:nodoc: + @details_key ||= DetailsKey.get(@details) if @cache + end + + # Temporary skip passing the details_key forward. + def disable_cache + old_value, @cache = @cache, false + yield + ensure + @cache = old_value + end + + # Update the details keys by merging the given hash into the current + # details hash. If a block is given, the details are modified just during + # the execution of the block and reverted to the previous value after. + def update_details(new_details) + if block_given? + old_details = @details.dup + super + + begin + yield + ensure + @details_key = nil + @details = old_details + end + else + super + end + end + + protected + + def _set_detail(key, value) + @details_key = nil + @details = @details.dup if @details.frozen? + @details[key] = value.freeze end end + # Helpers related to template lookup using the lookup context information. module ViewPaths attr_reader :view_paths @@ -141,111 +186,77 @@ module ActionView end end - module Details - attr_accessor :cache - - # Calculate the details key. Remove the handlers from calculation to improve performance - # since the user cannot modify it explicitly. - def details_key #:nodoc: - @details_key ||= DetailsKey.get(@details) if @cache - end - - # Temporary skip passing the details_key forward. - def disable_cache - old_value, @cache = @cache, false - yield - ensure - @cache = old_value - end + include Accessors + include DetailsCache + include ViewPaths - # Freeze the current formats in the lookup context. By freezing them, you are guaranteeing - # that next template lookups are not going to modify the formats. The controller can also - # use this, to ensure that formats won't be further modified (as it does in respond_to blocks). - def freeze_formats(formats, unless_frozen=false) #:nodoc: - return if unless_frozen && @frozen_formats - self.formats = formats - @frozen_formats = true - end + def initialize(view_paths, details = {}, prefixes = []) + @details, @details_key = { :handlers => default_handlers }, nil + @frozen_formats, @skip_default_locale = false, false + @cache = true + @prefixes = prefixes - # Overload formats= to expand ["*/*"] values and automatically - # add :html as fallback to :js. - def formats=(values) - if values - values.concat(_formats_defaults) if values.delete "*/*" - values << :html if values == [:js] - end - super(values) - end + self.view_paths = view_paths + initialize_details(details) + end - # Do not use the default locale on template lookup. - def skip_default_locale! - @skip_default_locale = true - self.locale = nil - end + # Freeze the current formats in the lookup context. By freezing them, you + # that next template lookups are not going to modify the formats. The con + # use this, to ensure that formats won't be further modified (as it does + def freeze_formats(formats, unless_frozen=false) #:nodoc: + return if unless_frozen && @frozen_formats + self.formats = formats + @frozen_formats = true + end - # Overload locale to return a symbol instead of array. - def locale - @details[:locale].first + # Override formats= to expand ["*/*"] values and automatically + # add :html as fallback to :js. + def formats=(values) + if values + values.concat(_formats_defaults) if values.delete "*/*" + values << :html if values == [:js] end + super(values) + end - # Overload locale= to also set the I18n.locale. If the current I18n.config object responds - # to original_config, it means that it's has a copy of the original I18n configuration and it's - # acting as proxy, which we need to skip. - def locale=(value) - if value - config = I18n.config.respond_to?(:original_config) ? I18n.config.original_config : I18n.config - config.locale = value - end - - super(@skip_default_locale ? I18n.locale : _locale_defaults) - end + # Do not use the default locale on template lookup. + def skip_default_locale! + @skip_default_locale = true + self.locale = nil + end - # A method which only uses the first format in the formats array for layout lookup. - # This method plays straight with instance variables for performance reasons. - def with_layout_format - if formats.size == 1 - yield - else - old_formats = formats - _set_detail(:formats, formats[0,1]) + # Override locale to return a symbol instead of array. + def locale + @details[:locale].first + end - begin - yield - ensure - _set_detail(:formats, old_formats) - end - end + # Overload locale= to also set the I18n.locale. If the current I18n.config object responds + # to original_config, it means that it's has a copy of the original I18n configuration and it's + # acting as proxy, which we need to skip. + def locale=(value) + if value + config = I18n.config.respond_to?(:original_config) ? I18n.config.original_config : I18n.config + config.locale = value end - # Update the details keys by merging the given hash into the current - # details hash. If a block is given, the details are modified just during - # the execution of the block and reverted to the previous value after. - def update_details(new_details) - old_details = @details.dup + super(@skip_default_locale ? I18n.locale : _locale_defaults) + end - registered_detail_setters.each do |key, setter| - send(setter, new_details[key]) if new_details.key?(key) - end + # A method which only uses the first format in the formats array for layout lookup. + # This method plays straight with instance variables for performance reasons. + def with_layout_format + if formats.size == 1 + yield + else + old_formats = formats + _set_detail(:formats, formats[0,1]) begin yield ensure - @details_key = nil - @details = old_details + _set_detail(:formats, old_formats) end end - - protected - - def _set_detail(key, value) - @details_key = nil - @details = @details.dup if @details.frozen? - @details[key] = value.freeze - end end - - include Accessors - include Details - include ViewPaths end end -- cgit v1.2.3 From 007f56701102647088673d92b165c3d862fbba22 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 21 Sep 2011 20:51:30 -0300 Subject: Add jquery-rails to Gemfile of plugins, test/dummy app uses it. Closes #3091 --- railties/lib/rails/generators/rails/plugin_new/templates/Gemfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile index 160baa6906..f4efd3af74 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile @@ -5,6 +5,9 @@ source "http://rubygems.org" # development dependencies will be added by default to the :development group. gemspec +# jquery-rails is used by the dummy application +gem "jquery-rails" + # Declare any dependencies that are still in development here instead of in # your gemspec. These might include edge Rails or gems from your path or # Git. Remember to move these dependencies to your gemspec before releasing @@ -17,4 +20,4 @@ gemspec <% end -%> # To use debugger -# <%= ruby_debugger_gemfile_entry %> \ No newline at end of file +# <%= ruby_debugger_gemfile_entry %> -- cgit v1.2.3