From 0244b43ecdf1aee9dac328b0e828156b579d9ada Mon Sep 17 00:00:00 2001 From: Rohit Arondekar Date: Thu, 20 May 2010 03:23:21 -0700 Subject: Minor typo fix in callbacks.rb of abstract_controller --- actionpack/lib/abstract_controller/callbacks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb index ee496dadc5..67efeb7063 100644 --- a/actionpack/lib/abstract_controller/callbacks.rb +++ b/actionpack/lib/abstract_controller/callbacks.rb @@ -20,7 +20,7 @@ module AbstractController end module ClassMethods - # If :only or :accept are used, convert the options into the + # If :only or :except are used, convert the options into the # primitive form (:per_key) used by ActiveSupport::Callbacks. # The basic idea is that :only => :index gets converted to # :if => proc {|c| c.action_name == "index" }, but that the -- cgit v1.2.3 From c36374e7688fb0d316e0b6e59515e05a1761bebe Mon Sep 17 00:00:00 2001 From: Rohit Arondekar Date: Fri, 21 May 2010 06:53:45 -0700 Subject: Getting Started, don't forget to link to yourself if you are adding to the changelog. --- railties/guides/source/getting_started.textile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index dd4e94a9e1..fe623e969f 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1486,8 +1486,7 @@ h3. Changelog "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/2 -* May 16, 2010: Added a section on configuration gotchas to address common encoding - problems that people might have +* 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 "Mikel Lindsaar":credits.html#raasdnil * April 1, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -- cgit v1.2.3 From 133ada6ab0f0cb7bef2bd40dbc18f2d5bc6b964e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 17 Apr 2010 05:13:40 +0200 Subject: auto_link: support arbitrary URI schemes like "ftp:" and "file:" recognizes all URI scheme allowed characters, such as colon and period. [#3494 state:resolved] --- actionpack/lib/action_view/helpers/text_helper.rb | 6 +++--- actionpack/test/template/text_helper_test.rb | 21 ++++++++++----------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 0e1bc139ff..fa930ac626 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -537,7 +537,7 @@ module ActionView end AUTO_LINK_RE = %r{ - ( https?:// | www\. ) + (?: ([\w+.:-]+:)// | www\. ) [^\s<]+ }x unless const_defined?(:AUTO_LINK_RE) @@ -548,7 +548,7 @@ module ActionView def auto_link_urls(text, html_options = {}) link_attributes = html_options.stringify_keys text.gsub(AUTO_LINK_RE) do - href = $& + scheme, href = $1, $& punctuation = [] left, right = $`, $' # detect already linked URLs and URLs in the middle of a tag @@ -566,7 +566,7 @@ module ActionView end link_text = block_given?? yield(href) : href - href = 'http://' + href unless href =~ %r{^[a-z]+://}i + href = 'http://' + href unless scheme content_tag(:a, h(link_text), link_attributes.merge('href' => href)) + punctuation.reverse.join('') end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 8b6c107a21..13f55cacb6 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -376,17 +376,16 @@ class TextHelperTest < ActionView::TestCase end def test_auto_link_other_protocols - silence_warnings do - begin - old_re_value = ActionView::Helpers::TextHelper::AUTO_LINK_RE - ActionView::Helpers::TextHelper.const_set :AUTO_LINK_RE, %r{(ftp://)[^\s<]+} - link_raw = 'ftp://example.com/file.txt' - link_result = generate_result(link_raw) - assert_equal %(Download #{link_result}), auto_link("Download #{link_raw}") - ensure - ActionView::Helpers::TextHelper.const_set :AUTO_LINK_RE, old_re_value - end - end + ftp_raw = 'ftp://example.com/file.txt' + assert_equal %(Download #{generate_result(ftp_raw)}), auto_link("Download #{ftp_raw}") + + file_scheme = 'file:///home/username/RomeoAndJuliet.pdf' + z39_scheme = 'z39.50r://host:696/db' + chrome_scheme = 'chrome://package/section/path' + view_source = 'view-source:http://en.wikipedia.org/wiki/URI_scheme' + assert_equal generate_result(z39_scheme), auto_link(z39_scheme) + assert_equal generate_result(chrome_scheme), auto_link(chrome_scheme) + assert_equal generate_result(view_source), auto_link(view_source) end def test_auto_link_already_linked -- cgit v1.2.3 From 8f0b2138ee979799092e0489f7298289c90901b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Wed, 11 Mar 2009 11:27:44 +0100 Subject: avoid auto_linking already linked emails; more robust detection of linked URLs References #1523 [#1862 state:resolved] [#3591 state:resolved] Add test that shows how link text can contain HTML if needed: the trick is using block form in combination with `raw`. Let link text be automatically HTML-escaped [#2017 state:resolved] --- actionpack/lib/action_view/helpers/text_helper.rb | 27 +++++++++++------ actionpack/test/template/text_helper_test.rb | 37 ++++++++++++++++++----- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index fa930ac626..41423d4e2e 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -539,7 +539,12 @@ module ActionView AUTO_LINK_RE = %r{ (?: ([\w+.:-]+:)// | www\. ) [^\s<]+ - }x unless const_defined?(:AUTO_LINK_RE) + }x + + # regexps for determining context, used high-volume + AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, //i, /<\/a>/i] + + AUTO_EMAIL_RE = /[\w.!#\$%+-]+@[\w-]+(?:\.[\w-]+)+/ BRACKETS = { ']' => '[', ')' => '(', '}' => '{' } @@ -550,9 +555,8 @@ module ActionView text.gsub(AUTO_LINK_RE) do scheme, href = $1, $& punctuation = [] - left, right = $`, $' - # detect already linked URLs and URLs in the middle of a tag - if left =~ /<[^>]+$/ && right =~ /^[^>]*>/ + + if auto_linked?($`, $') # do not change string; URL is already linked href else @@ -568,7 +572,7 @@ module ActionView link_text = block_given?? yield(href) : href href = 'http://' + href unless scheme - content_tag(:a, h(link_text), link_attributes.merge('href' => href)) + punctuation.reverse.join('') + content_tag(:a, link_text, link_attributes.merge('href' => href)) + punctuation.reverse.join('') end end end @@ -576,11 +580,10 @@ module ActionView # Turns all email addresses into clickable links. If a block is given, # each email is yielded and the result is used as the link text. def auto_link_email_addresses(text, html_options = {}) - body = text.dup - text.gsub(/([\w\.!#\$%\-+]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do - text = $1 + text.gsub(AUTO_EMAIL_RE) do + text = $& - if body.match(/]*>(.*)(#{Regexp.escape(text)})(.*)<\/a>/) + if auto_linked?($`, $') text else display_text = (block_given?) ? yield(text) : text @@ -588,6 +591,12 @@ module ActionView end end end + + # Detects already linked context or position in the middle of a tag + def auto_linked?(left, right) + (left =~ AUTO_LINK_CRE[0] and right =~ AUTO_LINK_CRE[1]) or + (left.rindex(AUTO_LINK_CRE[2]) and $' !~ AUTO_LINK_CRE[3]) + end end end end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 13f55cacb6..0b84c8f811 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -304,6 +304,7 @@ class TextHelperTest < ActionView::TestCase assert_equal %(

Link #{link_result_with_options}

), auto_link("

Link #{link_raw}

", :all, {:target => "_blank"}) assert_equal %(Go to #{link_result}.), auto_link(%(Go to #{link_raw}.)) assert_equal %(

Go to #{link_result}, then say hello to #{email_result}.

), auto_link(%(

Go to #{link_raw}, then say hello to #{email_raw}.

)) + assert_equal %(#{link_result} #{link_result}), auto_link(%(#{link_result} #{link_raw})) email2_raw = '+david@loudthinking.com' email2_result = %{#{email2_raw}} @@ -390,9 +391,24 @@ class TextHelperTest < ActionView::TestCase def test_auto_link_already_linked linked1 = generate_result('Ruby On Rails', 'http://www.rubyonrails.com') - linked2 = generate_result('www.rubyonrails.com', 'http://www.rubyonrails.com') + linked2 = %('www.example.com') + linked3 = %('www.example.com') + linked4 = %('www.example.com') + linked5 = %('close www.example.com') assert_equal linked1, auto_link(linked1) assert_equal linked2, auto_link(linked2) + assert_equal linked3, auto_link(linked3) + assert_equal linked4, auto_link(linked4) + assert_equal linked5, auto_link(linked5) + + linked_email = %Q(Mail me) + assert_equal linked_email, auto_link(linked_email) + end + + def test_auto_link_within_tags + link_raw = 'http://www.rubyonrails.org/images/rails.png' + link_result = %Q() + assert_equal link_result, auto_link(link_result) end def test_auto_link_with_brackets @@ -412,12 +428,6 @@ class TextHelperTest < ActionView::TestCase assert_equal "{link: #{link3_result}}", auto_link("{link: #{link3_raw}}") end - def test_auto_link_in_tags - link_raw = 'http://www.rubyonrails.org/images/rails.png' - link_result = %Q() - assert_equal link_result, auto_link(link_result) - end - def test_auto_link_at_eol url1 = "http://api.rubyonrails.com/Foo.html" url2 = "http://www.ruby-doc.org/core/Bar.html" @@ -431,6 +441,19 @@ class TextHelperTest < ActionView::TestCase assert_equal %(

#{url[0...7]}...
#{email[0...7]}...

), auto_link("

#{url}
#{email}

") { |url| truncate(url, :length => 10) } end + + def test_auto_link_with_block_with_html + pic = "http://example.com/pic.png" + url = "http://example.com/album?a&b=c" + + assert_equal %(My pic: -- full album here #{generate_result(url)}), auto_link("My pic: #{pic} -- full album here #{url}") { |link| + if link =~ /\.(jpg|gif|png|bmp|tif)$/i + raw %() + else + link + end + } + end def test_auto_link_with_options_hash assert_dom_equal 'Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com.', -- cgit v1.2.3 From f493f31533cf8db7756be8ed62a749ed57b7c7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Fri, 16 Apr 2010 23:31:38 +0200 Subject: cleanup `update/reset_counters`: less SQL strings, more ActiveRecord/Arel --- activerecord/lib/active_record/counter_cache.rb | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index cbebded995..3bdb6970f8 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -19,7 +19,9 @@ module ActiveRecord child_class = reflect_on_association(association).klass counter_name = child_class.reflect_on_association(self.name.downcase.to_sym).counter_cache_column - connection.update("UPDATE #{quoted_table_name} SET #{connection.quote_column_name(counter_name)} = #{object.send(association).count} WHERE #{connection.quote_column_name(primary_key)} = #{quote_value(object.id)}", "#{name} UPDATE") + self.unscoped.where(arel_table[self.primary_key].eq(object.id)).arel.update( + arel_table[counter_name] => object.send(association).count + ) end end @@ -53,19 +55,13 @@ module ActiveRecord # # SET comment_count = comment_count + 1, # # WHERE id IN (10, 15) def update_counters(id, counters) - updates = counters.inject([]) { |list, (counter_name, increment)| - sign = increment < 0 ? "-" : "+" - list << "#{connection.quote_column_name(counter_name)} = COALESCE(#{connection.quote_column_name(counter_name)}, 0) #{sign} #{increment.abs}" - }.join(", ") - - if id.is_a?(Array) - ids_list = id.map {|i| quote_value(i)}.join(', ') - condition = "IN (#{ids_list})" - else - condition = "= #{quote_value(id)}" + updates = counters.map do |counter_name, value| + operator = value < 0 ? '-' : '+' + quoted_column = connection.quote_column_name(counter_name) + "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}" end - update_all(updates, "#{connection.quote_column_name(primary_key)} #{condition}") + update_all(updates.join(', '), primary_key => id ) end # Increment a number field by one, usually representing a count. -- cgit v1.2.3 From bfca7d744d6172fc6c0bc05beaff2abe260a4f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 17 Apr 2010 00:32:06 +0200 Subject: move counter_cache tests to a separate file and refactor --- activerecord/test/cases/base_test.rb | 49 ---------------------- activerecord/test/cases/counter_cache_test.rb | 58 +++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 49 deletions(-) create mode 100755 activerecord/test/cases/counter_cache_test.rb diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 0c7723c0e6..1d883f7ea8 100755 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -708,55 +708,6 @@ class BasicsTest < ActiveRecord::TestCase assert Topic.find(2).approved? end - def test_increment_counter - Topic.increment_counter("replies_count", 1) - assert_equal 2, Topic.find(1).replies_count - - Topic.increment_counter("replies_count", 1) - assert_equal 3, Topic.find(1).replies_count - end - - def test_decrement_counter - Topic.decrement_counter("replies_count", 2) - assert_equal(-1, Topic.find(2).replies_count) - - Topic.decrement_counter("replies_count", 2) - assert_equal(-2, Topic.find(2).replies_count) - end - - def test_reset_counters - assert_equal 1, Topic.find(1).replies_count - - Topic.increment_counter("replies_count", 1) - assert_equal 2, Topic.find(1).replies_count - - Topic.reset_counters(1, :replies) - assert_equal 1, Topic.find(1).replies_count - end - - def test_update_counter - category = categories(:general) - assert_nil category.categorizations_count - assert_equal 2, category.categorizations.count - - Category.update_counters(category.id, "categorizations_count" => category.categorizations.count) - category.reload - assert_not_nil category.categorizations_count - assert_equal 2, category.categorizations_count - - Category.update_counters(category.id, "categorizations_count" => category.categorizations.count) - category.reload - assert_not_nil category.categorizations_count - assert_equal 4, category.categorizations_count - - category_2 = categories(:technology) - count_1, count_2 = (category.categorizations_count || 0), (category_2.categorizations_count || 0) - Category.update_counters([category.id, category_2.id], "categorizations_count" => 2) - category.reload; category_2.reload - assert_equal count_1 + 2, category.categorizations_count - assert_equal count_2 + 2, category_2.categorizations_count - end - def test_update_all assert_equal Topic.count, Topic.update_all("content = 'bulk updated!'") assert_equal "bulk updated!", Topic.find(1).content diff --git a/activerecord/test/cases/counter_cache_test.rb b/activerecord/test/cases/counter_cache_test.rb new file mode 100755 index 0000000000..b72356cf6f --- /dev/null +++ b/activerecord/test/cases/counter_cache_test.rb @@ -0,0 +1,58 @@ +require 'cases/helper' +require 'models/topic' +require 'models/reply' +require 'models/category' +require 'models/categorization' + +class CounterCacheTest < ActiveRecord::TestCase + fixtures :topics, :categories, :categorizations + + setup do + @topic = Topic.find(1) + end + + test "increment counter" do + assert_difference '@topic.reload.replies_count' do + Topic.increment_counter(:replies_count, @topic.id) + end + end + + test "decrement counter" do + assert_difference '@topic.reload.replies_count', -1 do + Topic.decrement_counter(:replies_count, @topic.id) + end + end + + test "reset counters" do + # throw the count off by 1 + Topic.increment_counter(:replies_count, @topic.id) + + # check that it gets reset + assert_difference '@topic.reload.replies_count', -1 do + Topic.reset_counters(@topic.id, :replies) + end + end + + test "update counter with initial null value" do + category = categories(:general) + assert_equal 2, category.categorizations.count + assert_nil category.categorizations_count + + Category.update_counters(category.id, :categorizations_count => category.categorizations.count) + assert_equal 2, category.reload.categorizations_count + end + + test "update counter for decrement" do + assert_difference '@topic.reload.replies_count', -3 do + Topic.update_counters(@topic.id, :replies_count => -3) + end + end + + test "update counters of multiple records" do + t1, t2 = topics(:first, :second) + + assert_difference ['t1.reload.replies_count', 't2.reload.replies_count'], 2 do + Topic.update_counters([t1.id, t2.id], :replies_count => 2) + end + end +end -- cgit v1.2.3 From bc84bd17d1f981ca4899f336f6b94e552bc6a058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 17 Apr 2010 02:01:38 +0200 Subject: fix `reset_counters` to work even with complex class names e.g. it guesses that a belongs_to association to Namespace::MyModel is named "my_model", unlike before where it would look up an association named "namespace::mymodel" and fail. --- activerecord/lib/active_record/counter_cache.rb | 10 ++++++---- activerecord/test/cases/counter_cache_test.rb | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index 3bdb6970f8..9601ed6afd 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -16,13 +16,15 @@ module ActiveRecord def reset_counters(id, *counters) object = find(id) counters.each do |association| - child_class = reflect_on_association(association).klass - counter_name = child_class.reflect_on_association(self.name.downcase.to_sym).counter_cache_column + child_class = reflect_on_association(association.to_sym).klass + belongs_name = self.name.demodulize.underscore.to_sym + counter_name = child_class.reflect_on_association(belongs_name).counter_cache_column - self.unscoped.where(arel_table[self.primary_key].eq(object.id)).arel.update( + self.unscoped.where(arel_table[self.primary_key].eq(object.id)).arel.update({ arel_table[counter_name] => object.send(association).count - ) + }) end + return true end # A generic "counter updater" implementation, intended primarily to be diff --git a/activerecord/test/cases/counter_cache_test.rb b/activerecord/test/cases/counter_cache_test.rb index b72356cf6f..377de168b9 100755 --- a/activerecord/test/cases/counter_cache_test.rb +++ b/activerecord/test/cases/counter_cache_test.rb @@ -7,6 +7,14 @@ require 'models/categorization' class CounterCacheTest < ActiveRecord::TestCase fixtures :topics, :categories, :categorizations + class SpecialTopic < ::Topic + has_many :special_replies, :foreign_key => 'parent_id' + end + + class SpecialReply < ::Reply + belongs_to :special_topic, :foreign_key => 'parent_id', :counter_cache => 'replies_count' + end + setup do @topic = Topic.find(1) end @@ -32,6 +40,23 @@ class CounterCacheTest < ActiveRecord::TestCase Topic.reset_counters(@topic.id, :replies) end end + + test "reset counters with string argument" do + Topic.increment_counter('replies_count', @topic.id) + + assert_difference '@topic.reload.replies_count', -1 do + Topic.reset_counters(@topic.id, 'replies') + end + end + + test "reset counters with modularized and camelized classnames" do + special = SpecialTopic.create!(:title => 'Special') + SpecialTopic.increment_counter(:replies_count, special.id) + + assert_difference 'special.reload.replies_count', -1 do + SpecialTopic.reset_counters(special.id, :special_replies) + end + end test "update counter with initial null value" do category = categories(:general) -- cgit v1.2.3 From 7db557f1520b2c2c60958e67c049ff424f61cbf1 Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Mon, 24 May 2010 18:07:08 +0200 Subject: New rake validate_guides task to validate output/*.html against the W3C Validator --- railties/Rakefile | 6 ++++ railties/guides/w3c_validator.rb | 67 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 railties/guides/w3c_validator.rb diff --git a/railties/Rakefile b/railties/Rakefile index daffd8ce30..efdb31cbd8 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -50,6 +50,12 @@ task :update_prototype_ujs do system "curl http://github.com/rails/prototype-ujs/raw/master/src/rails.js > lib/rails/generators/rails/app/templates/public/javascripts/rails.js" end +# Validate guides ------------------------------------------------------------------------- +desc 'Validate guides, use ONLY=foo to process just "foo.html"' +task :validate_guides do + ruby "guides/w3c_validator.rb" +end + # Generate documentation ------------------------------------------------------------------ Rake::RDocTask.new { |rdoc| diff --git a/railties/guides/w3c_validator.rb b/railties/guides/w3c_validator.rb new file mode 100644 index 0000000000..b55645a7a9 --- /dev/null +++ b/railties/guides/w3c_validator.rb @@ -0,0 +1,67 @@ +# --------------------------------------------------------------------------- +# +# This script validates the generated guides against the W3C Validator. +# +# Guides are taken from the output directory, from where all .html files are +# submitted to the validator. +# +# This script is prepared to be launched from the railties directory as a rake task: +# +# rake validate_guides +# +# If nothing is specified, all files will be validated, but you can check just +# some of them using this environment variable: +# +# ONLY +# Use ONLY if you want to validate only one or a set of guides. Prefixes are +# enough: +# +# # validates only association_basics.html +# ONLY=assoc rake validate_guides +# +# Separate many using commas: +# +# # validates only +# ONLY=assoc,migrations rake validate_guides +# +# --------------------------------------------------------------------------- + +require 'rubygems' +require 'w3c_validators' +include W3CValidators + +module RailsGuides + class Validator + + def validate + validator = MarkupValidator.new + + guides_to_validate.each do |f| + puts "Validating #{f}" + results = validator.validate_file(f) + + if !results.validity + puts "#{f} FAILED W3C validation with #{results.errors.size} error(s):" + results.errors.each do |error| + puts error.to_s + end + end + end + end + + private + def guides_to_validate + guides = Dir["./guides/output/*.html"] + ENV.key?('ONLY') ? select_only(guides) : guides + end + + def select_only(guides) + prefixes = ENV['ONLY'].split(",").map(&:strip) + guides.select do |guide| + prefixes.any? {|p| guide.start_with?("./guides/output/#{p}")} + end + end + end +end + +RailsGuides::Validator.new.validate \ No newline at end of file -- cgit v1.2.3 From 781692d58386416c6828b2e1b33df8e2fa89dfc1 Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Mon, 24 May 2010 18:12:24 +0200 Subject: Fixed minor typo on credits --- railties/guides/source/credits.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/credits.html.erb b/railties/guides/source/credits.html.erb index e9eb31bcae..825e042628 100644 --- a/railties/guides/source/credits.html.erb +++ b/railties/guides/source/credits.html.erb @@ -44,7 +44,7 @@ Ruby on Rails Guides: Credits <% end %> <%= author('Mikel Lindsaar', 'raasdnil') do %> - Mikel Lindsaar has been working with Rails since 2006 and is the author of the Ruby Mail gem and core contributor (he helped re-write Action Mailer's API). Mikel is the founder of RubyX, has a blog and tweets. + Mikel Lindsaar has been working with Rails since 2006 and is the author of the Ruby Mail gem and core contributor (he helped re-write Action Mailer's API). Mikel is the founder of RubyX, has a blog and tweets. <% end %> <%= author('Cássio Marques', 'cmarques') do %> -- cgit v1.2.3 From d85b3ef3c1b0aa658babf3f3d200586dfd5c4147 Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Mon, 24 May 2010 18:30:47 +0200 Subject: Added info about guides validation to Contribute guide --- railties/guides/source/contribute.textile | 1 + 1 file changed, 1 insertion(+) diff --git a/railties/guides/source/contribute.textile b/railties/guides/source/contribute.textile index 66f24e5c7e..88c5c79e9d 100644 --- a/railties/guides/source/contribute.textile +++ b/railties/guides/source/contribute.textile @@ -14,6 +14,7 @@ h3. How to Contribute? * Sample format : "Active Record Associations":http://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 +rake generate_guides+ in the +railties+ directory. +* You're encouraged to validate XHTML for the generated guides before commiting your changes by running +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? -- cgit v1.2.3 From 844b195292f14a96806852510bf67eb67a13c919 Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Mon, 24 May 2010 19:00:37 +0200 Subject: Fixed XHTML on activerecord_validation_callbacks guide --- railties/guides/source/activerecord_validations_callbacks.textile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile index ee30f3963b..857551c9d5 100644 --- a/railties/guides/source/activerecord_validations_callbacks.textile +++ b/railties/guides/source/activerecord_validations_callbacks.textile @@ -139,7 +139,7 @@ end +invalid?+ is simply the inverse of +valid?+. +invalid?+ triggers your validations and returns true if any errors were added to the object, and false otherwise. -h4. +errors[]+ +h4(#validations_overview-errors). +errors[]+ To verify whether or not a particular attribute of an object is valid, you can use +errors[:attribute]+ that returns an array with all attribute errors, when there are no errors on the specified attribute, an empty array is returned. @@ -597,7 +597,7 @@ In addition to the +valid?+ and +invalid?+ methods covered earlier, Rails provid The following is a list of the most commonly used methods. Please refer to the +ActiveRecord::Errors+ documentation for a list of all the available methods. -h4. +errors+ +h4(#working_with_validation_errors-errors). +errors+ Returns an OrderedHash with all errors. Each key is the attribute name and value is an array of strings with all errors. @@ -617,7 +617,7 @@ person.valid? # => true person.errors # => [] -h4. +errors[]+ +h4(#working_with_validation_errors-errors-2). +errors[]+ +errors[]+ is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute returns an empty array. @@ -1162,6 +1162,7 @@ h3. Changelog "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks +* 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 -- cgit v1.2.3 From 2a833d7bd8c7d76d833fc248a113fb2f1cfe6d2b Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Thu, 15 Apr 2010 08:10:28 +1000 Subject: Cover more of the Rails initialization process, regarding the internals of YourApp::Application inheritance from Rails::Application and more. --- railties/guides/source/initialization.textile | 66 +++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 96d6998e1c..cccbb9df06 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -1819,7 +1819,7 @@ On the surface, this looks like a simple class inheritance. There's more underne end -We do not already have a +Rails.application+, so instead this resorts to calling +super+. +Rails::Application+ descends from +Rails::Engine+ and so will call the +inherited+ method in +Rails::Engine+, but before that it's important to note that +called_from+ is defined an +attr_accessor+ on +Rails::Engine+: +We do not already have a +Rails.application+, so instead this resorts to calling +super+. +Rails::Application+ descends from +Rails::Engine+ and so will call the +inherited+ method in +Rails::Engine+ (in _railties/lib/rails/engine.rb_), but before that it's important to note that +called_from+ is defined an +attr_accessor+ on +Rails::Engine+ and that +YourApp::Application+ is not an +abstract_railtie+: def inherited(base) @@ -1835,8 +1835,68 @@ We do not already have a +Rails.application+, so instead this resorts to calling end -This +called_from+ setting looks a little overwhelming to begin with, but the short end of it is that it returns the route to your application's config directory, something like: _/home/you/yourapp/config_. After +called_from+ has been set, +super+ is again called and this means the +Rails::Railtie#inherited+ method. - +This +called_from+ setting looks a little overwhelming to begin with, but the short end of it is that it returns the route to your application's config directory, something like: _/home/you/yourapp/config_. After +called_from+ has been set, +super+ is again called and this means the +Rails::Railtie#inherited+ method (in _railties/lib/rails/railtie.rb_): + + + def inherited(base) + unless base.abstract_railtie? + base.send(:include, self::Configurable) + subclasses << base + end + end + + +Again, +YourApp::Application+ will return false for +abstract_railtie+ and so the code inside the +unless+ will be ran. The first line: + + + base.send(:include, self::Configurable) + + +includes the +self::Configurable+ module, with self being +Rails::Application+ in this context: + + + module Rails + class Application + module Configurable + def self.included(base) + base.extend ClassMethods + end + + module ClassMethods + def inherited(base) + raise "You cannot inherit from a Rails::Application child" + end + end + + def config + @config ||= Application::Configuration.new(self.class.find_root_with_flag("config.ru", Dir.pwd)) + end + end + end + end + + +The inclusion of the +Rails::Application::Configurable+ module triggers the +included+ method in here which extends +YourApp::Application+ with the +Rails::Application::Configurable::ClassMethods+. + +Now that the chain of +super+ calls is done, we'll go back to the original +inherited+ method in +Rails::Application+ and the final line in this method: + + + Rails.application = base.instance + + ++base+ in this case is +YourApp::Application+ and calling +instance+ on this will return an instance of +YourApp::Application+ through the +instance+ method defined here: + + + def instance + if self == Rails::Application + Rails.application + else + @@instance ||= new + end + end + + ++self+ in this case is +YourApp::Application+, so it won't match to +Rails::Application+ so instead the +new+ method is called which calls the +initialize+ method. -- cgit v1.2.3 From 6602fb62a0e66c1fc6203b3495624b6ee82339f9 Mon Sep 17 00:00:00 2001 From: jacortinas Date: Fri, 30 Apr 2010 09:05:32 -0500 Subject: A small rdoc change made on lines 39 and 41 on activesupport/lib/active_support/core_ext/object/to_param.rb. It looks like the method name might have been changed, and the comments were never changed to coincide with the new method name. --- activesupport/lib/active_support/core_ext/object/to_param.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 activesupport/lib/active_support/core_ext/object/to_param.rb diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb old mode 100644 new mode 100755 index 49e41e919a..06f077e920 --- a/activesupport/lib/active_support/core_ext/object/to_param.rb +++ b/activesupport/lib/active_support/core_ext/object/to_param.rb @@ -38,9 +38,9 @@ class Hash # passed to enclose the param names (see example below). # # ==== Examples - # { :name => 'David', :nationality => 'Danish' }.to_query # => "name=David&nationality=Danish" + # { :name => 'David', :nationality => 'Danish' }.to_param # => "name=David&nationality=Danish" # - # { :name => 'David', :nationality => 'Danish' }.to_query('user') # => "user[name]=David&user[nationality]=Danish" + # { :name => 'David', :nationality => 'Danish' }.to_param('user') # => "user[name]=David&user[nationality]=Danish" def to_param(namespace = nil) collect do |key, value| value.to_query(namespace ? "#{namespace}[#{key}]" : key) -- cgit v1.2.3 From 0855e0404424483e097b2396dc2e54d8f17e74d0 Mon Sep 17 00:00:00 2001 From: David Chelimsky Date: Sun, 21 Feb 2010 09:31:23 -0600 Subject: fix small doc bug about running single unit test files --- actionpack/RUNNING_UNIT_TESTS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/RUNNING_UNIT_TESTS b/actionpack/RUNNING_UNIT_TESTS index 16b119878a..95a8bc7497 100644 --- a/actionpack/RUNNING_UNIT_TESTS +++ b/actionpack/RUNNING_UNIT_TESTS @@ -11,7 +11,7 @@ Rake can be found at http://rake.rubyforge.org If you only want to run a single test suite, or don't want to bother with Rake, you can do so with something like: - ruby controller/base_tests.rb + ruby -Itest test/controller/base_tests.rb == Dependency on ActiveRecord and database setup -- cgit v1.2.3 From 96e2094b8b634e4af0d9d3c8a1db9bbb7023a4a7 Mon Sep 17 00:00:00 2001 From: Josiah Ivey Date: Tue, 25 May 2010 08:03:04 -0500 Subject: Form Helpers guide: Use new syntax for fields_for examples --- railties/guides/source/form_helpers.textile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index 0c0a4e2263..515b3aad39 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -255,7 +255,7 @@ You can create a similar binding without actually creating +<form>+ tags <%= form_for :person, @person, :url => { :action => "create" } do |person_form| %> <%= person_form.text_field :name %> - <% fields_for @person.contact_detail do |contact_details_form| %> + <%= fields_for @person.contact_detail do |contact_details_form| %> <%= contact_details_form.text_field :phone_number %> <% end %> <% end %> @@ -697,7 +697,7 @@ You might want to render a form with a set of edit fields for each of a person's <%= form_for @person do |person_form| %> <%= person_form.text_field :name %> <% for address in @person.addresses %> - <% person_form.fields_for address, :index => address do |address_form|%> + <%= person_form.fields_for address, :index => address do |address_form|%> <%= address_form.text_field :city %> <% end %> <% end %> @@ -725,7 +725,7 @@ Rails knows that all these inputs should be part of the person hash because you To create more intricate nestings, you can specify the first part of the input name (+person[address]+ in the previous example) explicitly, for example -<% fields_for 'person[address][primary]', address, :index => address do |address_form| %> +<%= fields_for 'person[address][primary]', address, :index => address do |address_form| %> <%= address_form.text_field :city %> <% end %> @@ -741,7 +741,7 @@ As a general rule the final input name is the concatenation of the name given to As a shortcut you can append [] to the name and omit the +:index+ option. This is the same as specifying +:index => address+ so -<% fields_for 'person[address][primary][]', address do |address_form| %> +<%= fields_for 'person[address][primary][]', address do |address_form| %> <%= address_form.text_field :city %> <% end %> -- cgit v1.2.3 From 7bd30b9585ec709cb56d26a54182e438bae00a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elomar=20Fran=C3=A7a?= Date: Mon, 24 May 2010 23:55:14 -0300 Subject: Adding to_key to ActiveResource objects using ActiveModel::Conversion [#4685 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activeresource/lib/active_resource/base.rb | 6 +----- activeresource/test/cases/base_test.rb | 7 +++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index 6397fbc280..b89097ac4b 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -1044,11 +1044,6 @@ module ActiveResource attributes[self.class.primary_key] = id end - # Allows Active Resource objects to be used as parameters in Action Pack URL generation. - def to_param - id && id.to_s - end - # Test for equality. Resource are equal if and only if +other+ is the same object or # is an instance of the same class, is not new?, and has the same +id+. # @@ -1411,6 +1406,7 @@ module ActiveResource class Base extend ActiveModel::Naming include CustomMethods, Observing, Validations + include ActiveModel::Conversion include ActiveModel::Serializers::JSON include ActiveModel::Serializers::Xml end diff --git a/activeresource/test/cases/base_test.rb b/activeresource/test/cases/base_test.rb index 15084802f8..35c3f4c6ef 100644 --- a/activeresource/test/cases/base_test.rb +++ b/activeresource/test/cases/base_test.rb @@ -1081,6 +1081,13 @@ class BaseTest < Test::Unit::TestCase assert_equal '1', matz.to_param end + def test_to_key_quacks_like_active_record + new_person = Person.new + assert_nil new_person.to_key + matz = Person.find(1) + assert_equal [1], matz.to_key + end + def test_parse_deep_nested_resources luis = Customer.find(1) assert_kind_of Customer, luis -- cgit v1.2.3 From 9ae7e93920999511447179f7c44e4654ebfda476 Mon Sep 17 00:00:00 2001 From: David Chelimsky Date: Tue, 25 May 2010 23:12:09 -0500 Subject: reorganize tests for AV::TC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - decouple tests from the test case class by moving them outside - split out more TestCase subs as cleaner way of avoiding bleed of class level concepts Signed-off-by: José Valim --- actionpack/test/template/test_case_test.rb | 278 ++++++++++++++--------------- 1 file changed, 138 insertions(+), 140 deletions(-) diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index 25dbc04ce1..a34bca8145 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -2,21 +2,23 @@ require 'abstract_unit' require 'controller/fake_controllers' module ActionView - class TestCase - module ATestHelper - end - module AnotherTestHelper - def from_another_helper - 'Howdy!' - end + module ATestHelper + end + + module AnotherTestHelper + def from_another_helper + 'Howdy!' end + end - module ASharedTestHelper - def from_shared_helper - 'Holla!' - end + module ASharedTestHelper + def from_shared_helper + 'Holla!' end + end + + class TestCase helper ASharedTestHelper module SharedTests @@ -29,175 +31,171 @@ module ActionView end end end + end - class GeneralViewTest < ActionView::TestCase - include SharedTests - test_case = self + class GeneralViewTest < ActionView::TestCase + include SharedTests + test_case = self - test "works without testing a helper module" do - assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy')) - end + test "works without testing a helper module" do + assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy')) + end - test "can render a layout with block" do - assert_equal "Before (ChrisCruft)\n!\nAfter", - render(:layout => "test/layout_for_partial", :locals => {:name => "ChrisCruft"}) {"!"} - end + test "can render a layout with block" do + assert_equal "Before (ChrisCruft)\n!\nAfter", + render(:layout => "test/layout_for_partial", :locals => {:name => "ChrisCruft"}) {"!"} + end - helper AnotherTestHelper - test "additional helper classes can be specified as in a controller" do - assert test_case.ancestors.include?(AnotherTestHelper) - assert_equal 'Howdy!', from_another_helper - end + helper AnotherTestHelper + test "additional helper classes can be specified as in a controller" do + assert test_case.ancestors.include?(AnotherTestHelper) + assert_equal 'Howdy!', from_another_helper + end - test "determine_default_helper_class returns nil if name.sub(/Test$/, '').constantize resolves to a class" do - assert_nil self.class.determine_default_helper_class("String") - end + test "determine_default_helper_class returns nil if name.sub(/Test$/, '').constantize resolves to a class" do + assert_nil self.class.determine_default_helper_class("String") + end - test "delegates notice to request.flash" do - _view.request.flash.expects(:notice).with("this message") - _view.notice("this message") - end + test "delegates notice to request.flash" do + _view.request.flash.expects(:notice).with("this message") + _view.notice("this message") + end - test "delegates alert to request.flash" do - _view.request.flash.expects(:alert).with("this message") - _view.alert("this message") - end + test "delegates alert to request.flash" do + _view.request.flash.expects(:alert).with("this message") + _view.alert("this message") end + end - class ClassMethodsTest < ActionView::TestCase - include SharedTests - test_case = self + class ClassMethodsTest < ActionView::TestCase + include SharedTests + test_case = self - tests ATestHelper - test "tests the specified helper module" do - assert_equal ATestHelper, test_case.helper_class - assert test_case.ancestors.include?(ATestHelper) - end + tests ATestHelper + test "tests the specified helper module" do + assert_equal ATestHelper, test_case.helper_class + assert test_case.ancestors.include?(ATestHelper) + end - helper AnotherTestHelper - test "additional helper classes can be specified as in a controller" do - assert test_case.ancestors.include?(AnotherTestHelper) - assert_equal 'Howdy!', from_another_helper + helper AnotherTestHelper + test "additional helper classes can be specified as in a controller" do + assert test_case.ancestors.include?(AnotherTestHelper) + assert_equal 'Howdy!', from_another_helper - test_case.helper_class.module_eval do - def render_from_helper - from_another_helper - end + test_case.helper_class.module_eval do + def render_from_helper + from_another_helper end - assert_equal 'Howdy!', render(:partial => 'test/from_helper') end + assert_equal 'Howdy!', render(:partial => 'test/from_helper') end + end - class ATestHelperTest < ActionView::TestCase - include SharedTests - test_case = self - - test "inflects the name of the helper module to test from the test case class" do - assert_equal ATestHelper, test_case.helper_class - assert test_case.ancestors.include?(ATestHelper) - end - - test "a configured test controller is available" do - assert_kind_of ActionController::Base, controller - assert_equal '', controller.controller_path + class HelperInclusionTest < ActionView::TestCase + module RenderHelper + def render_from_helper + render :partial => 'customer', :collection => @customers end + end - test "helper class that is being tested is always included in view instance" do - # This ensure is a hidious hack to deal with these tests bleeding - # methods between eachother - begin - self.class.helper_class.module_eval do - def render_from_helper - render :partial => 'customer', :collection => @customers - end - end - - @controller.controller_path = 'test' + helper RenderHelper - @customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')] - assert_match /Hello: EloyHello: Manfred/, render(:partial => 'test/from_helper') + test "helper class that is being tested is always included in view instance" do + @controller.controller_path = 'test' - ensure - self.class.helper_class.send(:remove_method, :render_from_helper) - end - end + @customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')] + assert_match /Hello: EloyHello: Manfred/, render(:partial => 'test/from_helper') + end + end - test "no additional helpers should shared across test cases" do - assert !test_case.ancestors.include?(AnotherTestHelper) - assert_raise(NoMethodError) { send :from_another_helper } + class HelperExposureTest < ActionView::TestCase + helper(Module.new do + def render_from_helper + from_test_case end + end) + test "is able to make methods available to the view" do + assert_equal 'Word!', render(:partial => 'test/from_helper') + end - test "is able to use routes" do - controller.request.assign_parameters(@routes, 'foo', 'index') - assert_equal '/foo', url_for - assert_equal '/bar', url_for(:controller => 'bar') - end + def from_test_case; 'Word!'; end + helper_method :from_test_case + end - test "is able to use named routes" do - with_routing do |set| - set.draw { |map| resources :contents } - assert_equal 'http://test.host/contents/new', new_content_url - assert_equal 'http://test.host/contents/1', content_url(:id => 1) - end - end + class ATestHelperTest < ActionView::TestCase + include SharedTests + test_case = self - test "named routes can be used from helper included in view" do - with_routing do |set| - set.draw { |map| resources :contents } - _helpers.module_eval do - def render_from_helper - new_content_url - end - end + test "inflects the name of the helper module to test from the test case class" do + assert_equal ATestHelper, test_case.helper_class + assert test_case.ancestors.include?(ATestHelper) + end - assert_equal 'http://test.host/contents/new', render(:partial => 'test/from_helper') - end - end + test "a configured test controller is available" do + assert_kind_of ActionController::Base, controller + assert_equal '', controller.controller_path + end - test "is able to render partials with local variables" do - assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy')) - assert_equal 'Eloy', render(:partial => 'developers/developer', - :locals => { :developer => stub(:name => 'Eloy') }) - end + test "no additional helpers should shared across test cases" do + assert !test_case.ancestors.include?(AnotherTestHelper) + assert_raise(NoMethodError) { send :from_another_helper } + end - test "is able to render partials from templates and also use instance variables" do - @controller.controller_path = "test" + test "is able to use routes" do + controller.request.assign_parameters(@routes, 'foo', 'index') + assert_equal '/foo', url_for + assert_equal '/bar', url_for(:controller => 'bar') + end - @customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')] - assert_match /Hello: EloyHello: Manfred/, render(:file => 'test/list') + test "is able to use named routes" do + with_routing do |set| + set.draw { |map| resources :contents } + assert_equal 'http://test.host/contents/new', new_content_url + assert_equal 'http://test.host/contents/1', content_url(:id => 1) end + end - test "is able to make methods available to the view" do - # This ensure is a hidious hack to deal with these tests bleeding - # methods between eachother - begin - _helpers.module_eval do - def render_from_helper; from_test_case end + test "named routes can be used from helper included in view" do + with_routing do |set| + set.draw { |map| resources :contents } + _helpers.module_eval do + def render_from_helper + new_content_url end - assert_equal 'Word!', render(:partial => 'test/from_helper') - ensure - _helpers.send(:remove_method, :render_from_helper) end + + assert_equal 'http://test.host/contents/new', render(:partial => 'test/from_helper') end + end - def from_test_case; 'Word!'; end - helper_method :from_test_case + test "is able to render partials with local variables" do + assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy')) + assert_equal 'Eloy', render(:partial => 'developers/developer', + :locals => { :developer => stub(:name => 'Eloy') }) end - class AssertionsTest < ActionView::TestCase - def render_from_helper - form_tag('/foo') do - safe_concat render(:text => '
  • foo
') - end + test "is able to render partials from templates and also use instance variables" do + @controller.controller_path = "test" + + @customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')] + assert_match /Hello: EloyHello: Manfred/, render(:file => 'test/list') + end + + end + + class AssertionsTest < ActionView::TestCase + def render_from_helper + form_tag('/foo') do + safe_concat render(:text => '
  • foo
') end - helper_method :render_from_helper + end + helper_method :render_from_helper - test "uses the output_buffer for assert_select" do - render(:partial => 'test/from_helper') + test "uses the output_buffer for assert_select" do + render(:partial => 'test/from_helper') - assert_select 'form' do - assert_select 'li', :text => 'foo' - end + assert_select 'form' do + assert_select 'li', :text => 'foo' end end end -- cgit v1.2.3 From e02db06ece7aeecec7c37f5b0e3de7d65c8684e6 Mon Sep 17 00:00:00 2001 From: David Chelimsky Date: Tue, 25 May 2010 23:46:00 -0500 Subject: In AV::TC, move protect_against_forgery? from the test_case to the _helper module included in the view. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ensures that protect_against_forgery? is present when a helper included in a partial that is rendered by the template under test calls it (which happens in FormTagHelper#extra_tags_for_form, for example). [#4700 state:resolved] Signed-off-by: José Valim --- actionpack/lib/action_view/test_case.rb | 13 +++++++++---- actionpack/test/template/test_case_test.rb | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index e71761db6d..4dbbd2eb6a 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -89,16 +89,13 @@ module ActionView self.class.send(:include_helper_modules!) make_test_case_available_to_view! + say_no_to_protect_against_forgery! end def config @controller.config if @controller.respond_to?(:config) end - def protect_against_forgery? - false - end - def render(options = {}, local_assigns = {}, &block) @rendered << output = _view.render(options, local_assigns, &block) output @@ -117,6 +114,14 @@ module ActionView HTML::Document.new(@rendered.blank? ? @output_buffer : @rendered).root end + def say_no_to_protect_against_forgery! + _helpers.module_eval do + def protect_against_forgery? + false + end + end + end + def make_test_case_available_to_view! test_case_instance = self _helpers.module_eval do diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index a34bca8145..16e5ee4f72 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -122,6 +122,21 @@ module ActionView helper_method :from_test_case end + class IgnoreProtectAgainstForgeryTest < ActionView::TestCase + module HelperThatInvokesProtectAgainstForgery + def help_me + protect_against_forgery? + end + end + + helper HelperThatInvokesProtectAgainstForgery + + test "protect_from_forgery? in any helpers returns false" do + assert !_view.help_me + end + + end + class ATestHelperTest < ActionView::TestCase include SharedTests test_case = self -- cgit v1.2.3 From f1ae0321fa779b25eb4a46526f6094812af0e26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 27 May 2010 23:50:34 +0200 Subject: Use I18n 0.4.0 --- activesupport/activesupport.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index cfd85f61c9..09635c2f18 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.has_rdoc = true - s.add_dependency('i18n', '~> 0.4.0.beta1') + s.add_dependency('i18n', '~> 0.4.0') s.add_dependency('tzinfo', '~> 0.3.16') s.add_dependency('builder', '~> 2.1.2') s.add_dependency('memcache-client', '>= 1.7.5') -- cgit v1.2.3 From 6330e2af11ee9531b1b0bcad25e5b97541623b40 Mon Sep 17 00:00:00 2001 From: eparreno Date: Fri, 28 May 2010 16:46:12 +0200 Subject: add <%= to fields_for examples --- railties/guides/source/action_view_overview.textile | 2 +- railties/guides/source/getting_started.textile | 2 +- railties/guides/source/nested_model_forms.textile | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index 43ebe87875..8b5eda0973 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -699,7 +699,7 @@ Creates a scope around a specific model object like form_for, but doesn‘t crea First name: <%= person_form.text_field :first_name %> Last name : <%= person_form.text_field :last_name %> - <% fields_for @person.permission do |permission_fields| %> + <%= fields_for @person.permission do |permission_fields| %> Admin? : <%= permission_fields.check_box :admin %> <% end %> <% end %> diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index fe623e969f..46e709d0f5 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1342,7 +1342,7 @@ We also add a @post.tags.build at the top of this form, this is to make Now create the folder app/views/tags and make a file in there called _form.html.erb which contains the form for the tag: -<% form.fields_for :tags do |tag_form| %> +<%= form.fields_for :tags do |tag_form| %>
<%= tag_form.label :name, 'Tag:' %> <%= tag_form.text_field :name %> diff --git a/railties/guides/source/nested_model_forms.textile b/railties/guides/source/nested_model_forms.textile index 4a79902232..39b0c32f24 100644 --- a/railties/guides/source/nested_model_forms.textile +++ b/railties/guides/source/nested_model_forms.textile @@ -143,7 +143,7 @@ Now add a nested form for the +address+ association: <%= form_for @person do |f| %> <%= f.text_field :name %> - <% f.fields_for :address do |af| %> + <%= f.fields_for :address do |af| %> <%= f.text_field :street %> <% end %> <% end %> @@ -184,7 +184,7 @@ The form code for an association collection is pretty similar to that of a singl <%= form_for @person do |f| %> <%= f.text_field :name %> - <% f.fields_for :projects do |pf| %> + <%= f.fields_for :projects do |pf| %> <%= f.text_field :name %> <% end %> <% end %> -- cgit v1.2.3 From d21aa6de4f6d5a6a7249a43b7ba803ee45e42584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 28 May 2010 02:37:54 +0100 Subject: performance and integration tests inherit from AD, not AC Signed-off-by: wycats --- .../generators/test_unit/integration/templates/integration_test.rb | 2 +- .../generators/test_unit/performance/templates/performance_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb b/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb index 2c57158b1c..de0823749c 100644 --- a/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb +++ b/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb @@ -1,6 +1,6 @@ require 'test_helper' -class <%= class_name %>Test < ActionController::IntegrationTest +class <%= class_name %>Test < ActionDispatch::IntegrationTest fixtures :all # Replace this with your real tests. diff --git a/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb b/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb index 362e3dc09f..e827aa918f 100644 --- a/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb +++ b/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb @@ -1,7 +1,7 @@ require 'test_helper' require 'rails/performance_test_help' -class <%= class_name %>Test < ActionController::PerformanceTest +class <%= class_name %>Test < ActionDispatch::PerformanceTest # Replace this with your real tests. def test_homepage get '/' -- cgit v1.2.3 From 45e60283e733a535d68d499aa20e095c905f43b0 Mon Sep 17 00:00:00 2001 From: wycats Date: Sat, 29 May 2010 20:07:47 +0200 Subject: Removing Metal from Rails 3. If you have existing Metals, you have a few options: * if your metal behaves like a middleware, add it to the middleware stack via config.middleware.use. You can use methods on the middleware stack to control exactly where it should go * if it behaves like a Rack endpoint, you can link to it in the router. This will result in more optimal routing time, and allows you to remove code in your endpoint that matches specific URLs in favor of the more powerful handling in the router itself. For the future, you can use ActionController::Metal to get a very fast controller with the ability to opt-in to specific controller features without paying the penalty of the full controller stack. Since Rails 3 is closer to Rack, the Metal abstraction is no longer needed. --- actionpack/lib/action_dispatch.rb | 1 - .../lib/action_dispatch/middleware/cascade.rb | 29 -------- railties/guides/source/configuring.textile | 2 - railties/guides/source/initialization.textile | 6 +- railties/guides/source/rails_on_rack.textile | 51 ------------- railties/lib/rails/application.rb | 10 +-- railties/lib/rails/application/configuration.rb | 7 +- railties/lib/rails/application/metal_loader.rb | 50 ------------- railties/lib/rails/engine.rb | 7 +- railties/lib/rails/engine/configuration.rb | 1 - railties/lib/rails/generators/base.rb | 2 +- railties/lib/rails/generators/rails/metal/USAGE | 8 -- .../generators/rails/metal/metal_generator.rb | 11 --- .../generators/rails/metal/templates/metal.rb | 12 --- railties/lib/rails/tasks/framework.rake | 2 +- railties/test/application/metal_test.rb | 86 ---------------------- railties/test/application/middleware_test.rb | 6 -- railties/test/application/paths_test.rb | 2 - railties/test/generators/metal_generator_test.rb | 17 ----- railties/test/railties/shared_tests.rb | 18 ----- 20 files changed, 9 insertions(+), 319 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/middleware/cascade.rb delete mode 100644 railties/lib/rails/application/metal_loader.rb delete mode 100644 railties/lib/rails/generators/rails/metal/USAGE delete mode 100644 railties/lib/rails/generators/rails/metal/metal_generator.rb delete mode 100644 railties/lib/rails/generators/rails/metal/templates/metal.rb delete mode 100644 railties/test/application/metal_test.rb delete mode 100644 railties/test/generators/metal_generator_test.rb diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index dfb8919561..cdf81c6648 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -43,7 +43,6 @@ module ActionDispatch autoload_under 'middleware' do autoload :Callbacks - autoload :Cascade autoload :Cookies autoload :Flash autoload :Head diff --git a/actionpack/lib/action_dispatch/middleware/cascade.rb b/actionpack/lib/action_dispatch/middleware/cascade.rb deleted file mode 100644 index 9f5c9891f0..0000000000 --- a/actionpack/lib/action_dispatch/middleware/cascade.rb +++ /dev/null @@ -1,29 +0,0 @@ -module ActionDispatch - class Cascade - def self.new(*apps) - apps = apps.flatten - - case apps.length - when 0 - raise ArgumentError, "app is required" - when 1 - apps.first - else - super(apps) - end - end - - def initialize(apps) - @apps = apps - end - - def call(env) - result = nil - @apps.each do |app| - result = app.call(env) - break unless result[1]["X-Cascade"] == "pass" - end - result - end - end -end diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index bd2289890a..ab72b48034 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -63,8 +63,6 @@ h4. Rails General Configuration * +config.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging. -* +config.metals+ accepts an array used as the metals to load. If this is set to nil, all metals will be loaded in alphabetical order. If this is set to [], no metals will be loaded. Otherwise metals will be loaded in the order specified - * +config.plugin_loader+ overrides the class that handles loading each plugin. Defaults to +Rails::Plugin::Loader+. * +config.plugin_locators+ overrides the class that handle finding the desired plugins that you‘d like to load for your application. By default it is the +Rails::Plugin::FileSystemLocator+. diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index cccbb9df06..58ae115ba7 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -668,7 +668,6 @@ This file requires _rails/railtie.rb_ which defines +Rails::Railtie+. * add_routing_namespaces * add_locales * add_view_paths -* add_metals * add_generator_templates * load_application_initializers * load_application_classes @@ -726,7 +725,6 @@ This file is used to set up the +Rails::Paths+ module which is used to set up he paths.app.helpers "app/helpers", :eager_load => true paths.app.models "app/models", :eager_load => true paths.app.mailers "app/mailers", :eager_load => true - paths.app.metals "app/metal", :eager_load => true paths.app.views "app/views", :eager_load => true paths.lib "lib", :load_path => true paths.lib.tasks "lib/tasks", :glob => "**/*.rake" @@ -3154,7 +3152,6 @@ This method is defined like this: middleware.use('ActionDispatch::Cookies') middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) middleware.use('ActionDispatch::Flash', :if => lambda { ActionController::Base.session_store }) - middleware.use(lambda { Rails::Rack::Metal.new(Rails.application.config.paths.app.metals.to_a, Rails.application.config.metals) }) middleware.use('ActionDispatch::ParamsParser') middleware.use('::Rack::MethodOverride') middleware.use('::ActionDispatch::Head') @@ -3288,7 +3285,7 @@ Finally, a +Rails::Application::Configuration+ object will be returned. On this attr_accessor :after_initialize_blocks, :cache_classes, :colorize_logging, :consider_all_requests_local, :dependency_loading, - :load_once_paths, :logger, :metals, :plugins, + :load_once_paths, :logger, :plugins, :preload_frameworks, :reload_plugins, :serve_static_assets, :time_zone, :whiny_nils @@ -3574,7 +3571,6 @@ The +super+ method it references comes from +Rails::Engine::Configuration+ which paths.app.controllers "app/controllers", :eager_load => true paths.app.helpers "app/helpers", :eager_load => true paths.app.models "app/models", :eager_load => true - paths.app.metals "app/metal" paths.app.views "app/views" paths.lib "lib", :load_path => true paths.lib.tasks "lib/tasks", :glob => "**/*.rake" diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile index 512be43668..eaebb05f17 100644 --- a/railties/guides/source/rails_on_rack.textile +++ b/railties/guides/source/rails_on_rack.textile @@ -222,57 +222,6 @@ use MyOwnStackFromStratch run ActionController::Dispatcher.new -h3. Rails Metal Applications - -Rails Metal applications are minimal Rack applications specially designed for integrating with a typical Rails application. As Rails Metal Applications skip all of the Action Controller stack, serving a request has no overhead from the Rails framework itself. This is especially useful for infrequent cases where the performance of the full stack Rails framework is an issue. - -Ryan Bates' "Railscast on Rails Metal":http://railscasts.com/episodes/150-rails-metal provides a nice walkthrough generating and using Rails Metal. - -h4. Generating a Metal Application - -Rails provides a generator called +metal+ for creating a new Metal application: - - -$ rails generate metal poller - - -This generates +poller.rb+ in the +app/metal+ directory: - - -# Allow the metal piece to run in isolation -require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails) - -class Poller - def self.call(env) - if env["PATH_INFO"] =~ /^\/poller/ - [200, {"Content-Type" => "text/html"}, ["Hello, World!"]] - else - [404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]] - end - end -end - - -Metal applications within +app/metal+ folders in plugins will also be discovered and added to the list. - -Metal applications are an optimization. You should make sure to "understand the related performance implications":http://weblog.rubyonrails.org/2008/12/20/performance-of-rails-metal before using it. - -WARNING: To continue the Metal chain execution, return an +X-Cascade+ HTTP header with a value of +pass+. - -h4. Execution Order - -All Metal Applications are executed in alphabetical order of their filenames, so +aaa.rb+ will come before +bbb.rb+ in the metal chain. - -You can override the default ordering in your environment. Simply add a line like the following to +config/application.rb+ - -It is, however, possible to override the default ordering in your environment. Simply add a line like the following to +config/environment.rb+ - - -config.metals = ["Bbb", "Aaa"] - - -Each string in the array should be the name of your metal class. If you do this then be warned that any metal applications not listed will not be loaded. - h3. Resources h4. Learning Rack diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index a3b3a56bc8..c588a41443 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -27,7 +27,7 @@ module Rails # Besides providing the same configuration as Rails::Engine and Rails::Railtie, # the application object has several specific configurations, for example # "allow_concurrency", "cache_classes", "consider_all_requests_local", "filter_parameters", - # "logger", "metals", "reload_engines", "reload_plugins" and so forth. + # "logger", "reload_engines", "reload_plugins" and so forth. # # Check Rails::Application::Configuration to see them all. # @@ -36,17 +36,15 @@ module Rails # The application object is also responsible for holding the routes and reloading routes # whenever the files change in development. # - # == Middlewares and metals + # == Middlewares # - # The Application is also responsible for building the middleware stack and setting up - # both application and engines metals. + # The Application is also responsible for building the middleware stack. # class Application < Engine autoload :Bootstrap, 'rails/application/bootstrap' autoload :Configurable, 'rails/application/configurable' autoload :Configuration, 'rails/application/configuration' autoload :Finisher, 'rails/application/finisher' - autoload :MetalLoader, 'rails/application/metal_loader' autoload :Railties, 'rails/application/railties' autoload :RoutesReloader, 'rails/application/routes_reloader' @@ -83,7 +81,7 @@ module Rails end end - delegate :middleware, :metal_loader, :to => :config + delegate :middleware, :to => :config def require_environment! environment = paths.config.environment.to_a.first diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 1b8af370f7..f3a326f36d 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -9,7 +9,7 @@ module Rails attr_accessor :allow_concurrency, :cache_classes, :cache_store, :encoding, :consider_all_requests_local, :dependency_loading, - :filter_parameters, :log_level, :logger, :metals, + :filter_parameters, :log_level, :logger, :plugins, :preload_frameworks, :reload_engines, :reload_plugins, :secret_token, :serve_static_assets, :session_options, :time_zone, :whiny_nils @@ -45,10 +45,6 @@ module Rails @middleware ||= app_middleware.merge_into(default_middleware_stack) end - def metal_loader - @metal_loader ||= Rails::Application::MetalLoader.new - end - def paths @paths ||= begin paths = super @@ -157,7 +153,6 @@ module Rails middleware.use('::ActionDispatch::ParamsParser') middleware.use('::Rack::MethodOverride') middleware.use('::ActionDispatch::Head') - middleware.use(lambda { metal_loader.build_middleware(metals) }, :if => lambda { metal_loader.metals.any? }) end end end diff --git a/railties/lib/rails/application/metal_loader.rb b/railties/lib/rails/application/metal_loader.rb deleted file mode 100644 index 2a43fa7892..0000000000 --- a/railties/lib/rails/application/metal_loader.rb +++ /dev/null @@ -1,50 +0,0 @@ -require 'action_dispatch' - -module Rails - class Application - class MetalLoader - attr_reader :paths, :metals - - def initialize - @paths, @metals = [], [] - end - - def build_middleware(list=nil) - load_metals!(list) - self - end - - def new(app) - ActionDispatch::Cascade.new(@metals, app) - end - - def name - ActionDispatch::Cascade.name - end - alias :to_s :name - - protected - - def load_metals!(list) - metals = [] - list = Array(list || :all).map(&:to_sym) - - paths.each do |path| - matcher = /\A#{Regexp.escape(path)}\/(.*)\.rb\Z/ - Dir.glob("#{path}/**/*.rb").sort.each do |metal_path| - metal = metal_path.sub(matcher, '\1').to_sym - next unless list.include?(metal) || list.include?(:all) - require_dependency metal.to_s - metals << metal - end - end - - metals = metals.sort_by do |m| - [list.index(m) || list.index(:all), m.to_s] - end - - @metals = metals.map { |m| m.to_s.camelize.constantize } - end - end - end -end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index b44755820c..cdb00a4eff 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -25,7 +25,7 @@ module Rails # end # # Then ensure that this file is loaded at the top of your config/application.rb (or in - # your Gemfile) and it will automatically load models, controllers, helpers and metals + # your Gemfile) and it will automatically load models, controllers and helpers # inside app, load routes at "config/routes.rb", load locales at "config/locales/*", # load tasks at "lib/tasks/*". # @@ -73,7 +73,6 @@ module Rails # paths.app.controllers = "app/controllers" # paths.app.helpers = "app/helpers" # paths.app.models = "app/models" - # paths.app.metals = "app/metal" # paths.app.views = "app/views" # paths.lib = "lib" # paths.lib.tasks = "lib/tasks" @@ -202,10 +201,6 @@ module Rails end end - initializer :add_metals do |app| - app.metal_loader.paths.unshift(*paths.app.metals.to_a) - end - initializer :load_config_initializers do paths.config.initializers.to_a.sort.each do |initializer| load(initializer) diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index c5411a0331..446fe0bda9 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -19,7 +19,6 @@ module Rails paths.app.helpers "app/helpers", :eager_load => true paths.app.models "app/models", :eager_load => true paths.app.mailers "app/mailers", :eager_load => true - paths.app.metals "app/metal", :eager_load => true paths.app.views "app/views" paths.lib "lib", :load_path => true paths.lib.tasks "lib/tasks", :glob => "**/*.rake" diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 766644bbc2..bd2260fc29 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -288,7 +288,7 @@ module Rails end # Removes the namespaces and get the generator name. For example, - # Rails::Generators::MetalGenerator will return "metal" as generator name. + # Rails::Generators::ModelGenerator will return "model" as generator name. # def self.generator_name @generator_name ||= begin diff --git a/railties/lib/rails/generators/rails/metal/USAGE b/railties/lib/rails/generators/rails/metal/USAGE deleted file mode 100644 index c88325a444..0000000000 --- a/railties/lib/rails/generators/rails/metal/USAGE +++ /dev/null @@ -1,8 +0,0 @@ -Description: - Cast some metal! - -Examples: - `rails generate metal poller` - - This will create: - Metal: app/metal/poller.rb diff --git a/railties/lib/rails/generators/rails/metal/metal_generator.rb b/railties/lib/rails/generators/rails/metal/metal_generator.rb deleted file mode 100644 index fe4f945cad..0000000000 --- a/railties/lib/rails/generators/rails/metal/metal_generator.rb +++ /dev/null @@ -1,11 +0,0 @@ -module Rails - module Generators - class MetalGenerator < NamedBase - check_class_collision - - def create_metal_file - template "metal.rb", "app/metal/#{file_name}.rb" - end - end - end -end diff --git a/railties/lib/rails/generators/rails/metal/templates/metal.rb b/railties/lib/rails/generators/rails/metal/templates/metal.rb deleted file mode 100644 index 8cc3f1f258..0000000000 --- a/railties/lib/rails/generators/rails/metal/templates/metal.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Allow the metal piece to run in isolation -require File.expand_path('../../../config/environment', __FILE__) unless defined?(Rails) - -class <%= class_name %> - def self.call(env) - if env["PATH_INFO"] =~ /^\/<%= file_name %>/ - [200, {"Content-Type" => "text/html"}, ["Hello, World!"]] - else - [404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]] - end - end -end diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake index 063a393bfc..ac510eee2e 100644 --- a/railties/lib/rails/tasks/framework.rake +++ b/railties/lib/rails/tasks/framework.rake @@ -37,7 +37,7 @@ namespace :rails do project_templates = "#{Rails.root}/lib/templates" default_templates = { "erb" => %w{controller mailer scaffold}, - "rails" => %w{controller helper metal scaffold_controller stylesheets} } + "rails" => %w{controller helper scaffold_controller stylesheets} } default_templates.each do |type, names| local_template_type_dir = File.join(project_templates, type) diff --git a/railties/test/application/metal_test.rb b/railties/test/application/metal_test.rb deleted file mode 100644 index 1ec62282c8..0000000000 --- a/railties/test/application/metal_test.rb +++ /dev/null @@ -1,86 +0,0 @@ -require 'isolation/abstract_unit' - -module ApplicationTests - class MetalTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - boot_rails - - require 'rack/test' - extend Rack::Test::Methods - end - - def app - @app ||= begin - require "#{app_path}/config/environment" - Rails.application - end - end - - test "single metal endpoint" do - app_file 'app/metal/foo_metal.rb', <<-RUBY - class FooMetal - def self.call(env) - [200, { "Content-Type" => "text/html"}, ["FooMetal"]] - end - end - RUBY - - get "/not/slash" - assert_equal 200, last_response.status - assert_equal "FooMetal", last_response.body - end - - test "multiple metal endpoints" do - app_file 'app/metal/metal_a.rb', <<-RUBY - class MetalA - def self.call(env) - [404, { "Content-Type" => "text/html", "X-Cascade" => "pass" }, ["Metal A"]] - end - end - RUBY - - app_file 'app/metal/metal_b.rb', <<-RUBY - class MetalB - def self.call(env) - [200, { "Content-Type" => "text/html"}, ["Metal B"]] - end - end - RUBY - - get "/not/slash" - assert_equal 200, last_response.status - assert_equal "Metal B", last_response.body - end - - test "pass through to application" do - app_file 'app/metal/foo_metal.rb', <<-RUBY - class FooMetal - def self.call(env) - [404, { "Content-Type" => "text/html", "X-Cascade" => "pass" }, ["Not Found"]] - end - end - RUBY - - controller :foo, <<-RUBY - class FooController < ActionController::Base - def index - render :text => "foo" - end - end - RUBY - - app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| - match ':controller(/:action)' - end - RUBY - - get "/foo" - assert_equal 200, last_response.status - assert_equal "foo", last_response.body - end - end -end diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 617525bf78..78e7c39660 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -82,12 +82,6 @@ module ApplicationTests assert_equal "Rack::Config", middleware.first end - test "shows cascade if any metal exists" do - app_file "app/metal/foo.rb", "class Foo; end" - boot! - assert middleware.include?("ActionDispatch::Cascade") - end - # x_sendfile_header middleware test "config.action_dispatch.x_sendfile_header defaults to ''" do make_basic_app diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb index 978d677efc..c98b11556b 100644 --- a/railties/test/application/paths_test.rb +++ b/railties/test/application/paths_test.rb @@ -38,7 +38,6 @@ module ApplicationTests test "booting up Rails yields a valid paths object" do assert_path @paths.app.models, "app", "models" - assert_path @paths.app.metals, "app", "metal" assert_path @paths.app.helpers, "app", "helpers" assert_path @paths.app.views, "app", "views" assert_path @paths.lib, "lib" @@ -73,7 +72,6 @@ module ApplicationTests assert_in_load_path "vendor" assert_not_in_load_path "app", "views" - assert_not_in_load_path "app", "metal" assert_not_in_load_path "config" assert_not_in_load_path "config", "locales" assert_not_in_load_path "config", "environments" diff --git a/railties/test/generators/metal_generator_test.rb b/railties/test/generators/metal_generator_test.rb deleted file mode 100644 index 615122c882..0000000000 --- a/railties/test/generators/metal_generator_test.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'generators/generators_test_helper' -require 'rails/generators/rails/metal/metal_generator' - -class MetalGeneratorTest < Rails::Generators::TestCase - include GeneratorsTestHelper - arguments %w(foo) - - def test_metal_skeleton_is_created - run_generator - assert_file "app/metal/foo.rb", /class Foo/ - end - - def test_check_class_collision - content = capture(:stderr){ run_generator ["object"] } - assert_match /The name 'Object' is either already used in your application or reserved/, content - end -end diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb index 20328d402d..3f78d7d3fe 100644 --- a/railties/test/railties/shared_tests.rb +++ b/railties/test/railties/shared_tests.rb @@ -241,24 +241,6 @@ YAML assert_equal "1", I18n.t(:bar) end - def test_plugin_metals_added_to_middleware_stack - @plugin.write 'app/metal/foo_metal.rb', <<-RUBY - class FooMetal - def self.call(env) - [200, { "Content-Type" => "text/html"}, ["FooMetal"]] - end - end - RUBY - - boot_rails - require 'rack/test' - extend Rack::Test::Methods - - get "/not/slash" - assert_equal 200, last_response.status - assert_equal "FooMetal", last_response.body - end - def test_namespaced_controllers_with_namespaced_routes @plugin.write "config/routes.rb", <<-RUBY Rails.application.routes.draw do -- cgit v1.2.3 From e5a56eb297f41dae12e03cf03bad4a25068bba09 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 26 May 2010 12:55:04 -0300 Subject: fix translation test in actionpack [#4701 state:commited] Signed-off-by: wycats --- actionpack/test/fixtures/test/scoped_translation.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/test/fixtures/test/scoped_translation.erb b/actionpack/test/fixtures/test/scoped_translation.erb index 30baa61c77..3be63ab3cc 100644 --- a/actionpack/test/fixtures/test/scoped_translation.erb +++ b/actionpack/test/fixtures/test/scoped_translation.erb @@ -1 +1 @@ -<%= t('.foo.bar') %> \ No newline at end of file +<%= t('.foo.bar').join %> \ No newline at end of file -- cgit v1.2.3 From d7f6f2b596d00a7deb4f83592aaa78436c5c3163 Mon Sep 17 00:00:00 2001 From: wycats Date: Sat, 29 May 2010 21:20:52 +0200 Subject: Now that we always return a proxy from mb_chars, even in 1.9, all Strings coming back from AS are UTF-8. --- actionpack/test/template/text_helper_test.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 0b84c8f811..bb808b77a5 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -84,8 +84,9 @@ class TextHelperTest < ActionView::TestCase end else def test_truncate_multibyte - assert_equal "\354\225\210\353\205\225\355...", - truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10) + # .mb_chars always returns a UTF-8 String. + # assert_equal "\354\225\210\353\205\225\355...", + # truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10) assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'), truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), :length => 10) @@ -218,7 +219,8 @@ class TextHelperTest < ActionView::TestCase else def test_excerpt_with_utf8 assert_equal("...\357\254\203ciency could not be...".force_encoding('UTF-8'), excerpt("That's why e\357\254\203ciency could not be helped".force_encoding('UTF-8'), 'could', 8)) - assert_equal("...\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped", 'could', 8)) + # .mb_chars always returns UTF-8, even in 1.9. This is not great, but it's how it works. Let's work this out. + # assert_equal("...\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped".force_encoding("BINARY"), 'could', 8)) end end -- cgit v1.2.3 From 19d8c8cbe4aae570e3b48080e3182e5634aa7aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 29 May 2010 22:29:14 +0200 Subject: Remove the laziness from the middleware stack. --- actionpack/lib/action_dispatch/middleware/stack.rb | 72 +++++----------------- actionpack/test/dispatch/middleware_stack_test.rb | 19 +----- railties/lib/rails/application.rb | 28 ++++++++- railties/lib/rails/application/bootstrap.rb | 2 +- railties/lib/rails/application/configuration.rb | 28 +-------- railties/lib/rails/tasks/middleware.rake | 2 +- railties/test/application/middleware_test.rb | 2 +- .../generators/integration_test_generator_test.rb | 2 +- .../generators/performance_test_generator_test.rb | 2 +- 9 files changed, 51 insertions(+), 106 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 5c5362ce4a..0e5ab507df 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -3,49 +3,15 @@ require "active_support/inflector/methods" module ActionDispatch class MiddlewareStack < Array class Middleware - def self.new(klass, *args, &block) - if klass.is_a?(self) - klass - else - super - end - end - attr_reader :args, :block def initialize(klass, *args, &block) - @klass = klass - - options = args.extract_options! - if options.has_key?(:if) - @conditional = options.delete(:if) - else - @conditional = true - end - args << options unless options.empty? - - @args = args - @block = block + @klass, @args, @block = klass, args, block end def klass - if @klass.respond_to?(:new) - @klass - elsif @klass.respond_to?(:call) - @klass.call - else - ActiveSupport::Inflector.constantize(@klass.to_s) - end - end - - def active? - return false unless klass - - if @conditional.respond_to?(:call) - @conditional.call - else - @conditional - end + return @klass if @klass.respond_to?(:new) + @klass = ActiveSupport::Inflector.constantize(@klass.to_s) end def ==(middleware) @@ -58,7 +24,7 @@ module ActionDispatch if lazy_compare?(@klass) && lazy_compare?(middleware) normalize(@klass) == normalize(middleware) else - klass.name == middleware.to_s + klass.name == normalize(middleware.to_s) end end end @@ -68,25 +34,18 @@ module ActionDispatch end def build(app) - if block - klass.new(app, *build_args, &block) - else - klass.new(app, *build_args) - end + klass.new(app, *args, &block) end - private - def lazy_compare?(object) - object.is_a?(String) || object.is_a?(Symbol) - end + private - def normalize(object) - object.to_s.strip.sub(/^::/, '') - end + def lazy_compare?(object) + object.is_a?(String) || object.is_a?(Symbol) + end - def build_args - Array(args).map { |arg| arg.respond_to?(:call) ? arg.call : arg } - end + def normalize(object) + object.to_s.strip.sub(/^::/, '') + end end def initialize(*args, &block) @@ -119,15 +78,14 @@ module ActionDispatch end def active - find_all { |middleware| middleware.active? } + ActiveSupport::Deprecation.warn "All middlewares in the chaing are active since the laziness " << + "was removed from the middleware stack", caller end def build(app = nil, &blk) app ||= blk - raise "MiddlewareStack#build requires an app" unless app - - active.reverse.inject(app) { |a, e| e.build(a) } + reverse.inject(app) { |a, e| e.build(a) } end end end diff --git a/actionpack/test/dispatch/middleware_stack_test.rb b/actionpack/test/dispatch/middleware_stack_test.rb index 7cf6365af3..170c5b8565 100644 --- a/actionpack/test/dispatch/middleware_stack_test.rb +++ b/actionpack/test/dispatch/middleware_stack_test.rb @@ -66,29 +66,14 @@ class MiddlewareStackTest < ActiveSupport::TestCase assert_equal BazMiddleware, @stack[0].klass end - test "active returns all only enabled middleware" do - assert_no_difference "@stack.active.size" do - assert_difference "@stack.size" do - @stack.use BazMiddleware, :if => lambda { false } - end - end - end - test "lazy evaluates middleware class" do assert_difference "@stack.size" do - @stack.use lambda { BazMiddleware } + @stack.use "MiddlewareStackTest::BazMiddleware" end assert_equal BazMiddleware, @stack.last.klass end - test "lazy evaluates middleware arguments" do - assert_difference "@stack.size" do - @stack.use BazMiddleware, lambda { :foo } - end - assert_equal [:foo], @stack.last.send(:build_args) - end - - test "lazy compares so unloaded constants can be loaded" do + test "lazy compares so unloaded constants are not loaded" do @stack.use "UnknownMiddleware" @stack.use :"MiddlewareStackTest::BazMiddleware" assert @stack.include?("::MiddlewareStackTest::BazMiddleware") diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index c588a41443..7416e94eeb 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -124,7 +124,10 @@ module Rails end def app - @app ||= config.middleware.build(routes) + @app ||= begin + config.middleware = config.middleware.merge_into(default_middleware_stack) + config.middleware.build(routes) + end end def call(env) @@ -148,6 +151,29 @@ module Rails protected + def default_middleware_stack + ActionDispatch::MiddlewareStack.new.tap do |middleware| + middleware.use ::ActionDispatch::Static, paths.public.to_a.first if config.serve_static_assets + middleware.use ::Rack::Lock if !config.allow_concurrency + middleware.use ::Rack::Runtime + middleware.use ::Rails::Rack::Logger + middleware.use ::ActionDispatch::ShowExceptions, config.consider_all_requests_local if config.action_dispatch.show_exceptions + middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies + middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header + middleware.use ::ActionDispatch::Callbacks, !config.cache_classes + middleware.use ::ActionDispatch::Cookies + + if config.session_store + middleware.use config.session_store, config.session_options + middleware.use ::ActionDispatch::Flash + end + + middleware.use ::ActionDispatch::ParamsParser + middleware.use ::Rack::MethodOverride + middleware.use ::ActionDispatch::Head + end + end + def initialize_tasks require "rails/tasks" task :environment do diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index e62eed8a87..0a435f0f36 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -47,7 +47,7 @@ module Rails silence_warnings { Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store(config.cache_store) } if RAILS_CACHE.respond_to?(:middleware) - config.middleware.insert_after(:"Rack::Lock", RAILS_CACHE.middleware) + config.middleware.insert_before("Rack::Runtime", RAILS_CACHE.middleware) end end end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index f3a326f36d..25e54e9dce 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -9,7 +9,7 @@ module Rails attr_accessor :allow_concurrency, :cache_classes, :cache_store, :encoding, :consider_all_requests_local, :dependency_loading, - :filter_parameters, :log_level, :logger, + :filter_parameters, :log_level, :logger, :middleware, :plugins, :preload_frameworks, :reload_engines, :reload_plugins, :secret_token, :serve_static_assets, :session_options, :time_zone, :whiny_nils @@ -25,6 +25,7 @@ module Rails @session_store = :cookie_store @session_options = {} @time_zone = "UTC" + @middleware = app_middleware end def encoding=(value) @@ -41,10 +42,6 @@ module Rails end end - def middleware - @middleware ||= app_middleware.merge_into(default_middleware_stack) - end - def paths @paths ||= begin paths = super @@ -134,27 +131,6 @@ module Rails @session_options = args.shift || {} end end - - protected - - def default_middleware_stack - ActionDispatch::MiddlewareStack.new.tap do |middleware| - middleware.use('::ActionDispatch::Static', lambda { paths.public.to_a.first }, :if => lambda { serve_static_assets }) - middleware.use('::Rack::Lock', :if => lambda { !allow_concurrency }) - middleware.use('::Rack::Runtime') - middleware.use('::Rails::Rack::Logger') - middleware.use('::ActionDispatch::ShowExceptions', lambda { consider_all_requests_local }, :if => lambda { action_dispatch.show_exceptions }) - middleware.use('::ActionDispatch::RemoteIp', lambda { action_dispatch.ip_spoofing_check }, lambda { action_dispatch.trusted_proxies }) - middleware.use('::Rack::Sendfile', lambda { action_dispatch.x_sendfile_header }) - middleware.use('::ActionDispatch::Callbacks', lambda { !cache_classes }) - middleware.use('::ActionDispatch::Cookies') - middleware.use(lambda { session_store }, lambda { session_options }) - middleware.use('::ActionDispatch::Flash', :if => lambda { session_store }) - middleware.use('::ActionDispatch::ParamsParser') - middleware.use('::Rack::MethodOverride') - middleware.use('::ActionDispatch::Head') - end - end end end end diff --git a/railties/lib/rails/tasks/middleware.rake b/railties/lib/rails/tasks/middleware.rake index 251da67c96..e670989345 100644 --- a/railties/lib/rails/tasks/middleware.rake +++ b/railties/lib/rails/tasks/middleware.rake @@ -1,6 +1,6 @@ desc 'Prints out your Rack middleware stack' task :middleware => :environment do - Rails.configuration.middleware.active.each do |middleware| + Rails.configuration.middleware.each do |middleware| puts "use #{middleware.inspect}" end puts "run #{Rails::Application.instance.class.name}.routes" diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 78e7c39660..bab17d8af5 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -164,7 +164,7 @@ module ApplicationTests end def middleware - AppTemplate::Application.middleware.active.map(&:klass).map(&:name) + AppTemplate::Application.middleware.map(&:klass).map(&:name) end def remote_ip(env = {}) diff --git a/railties/test/generators/integration_test_generator_test.rb b/railties/test/generators/integration_test_generator_test.rb index cf282a0911..d05ed76d24 100644 --- a/railties/test/generators/integration_test_generator_test.rb +++ b/railties/test/generators/integration_test_generator_test.rb @@ -7,6 +7,6 @@ class IntegrationTestGeneratorTest < Rails::Generators::TestCase def test_integration_test_skeleton_is_created run_generator - assert_file "test/integration/integration_test.rb", /class IntegrationTest < ActionController::IntegrationTest/ + assert_file "test/integration/integration_test.rb", /class IntegrationTest < ActionDispatch::IntegrationTest/ end end diff --git a/railties/test/generators/performance_test_generator_test.rb b/railties/test/generators/performance_test_generator_test.rb index 8fda83b36f..37f9857193 100644 --- a/railties/test/generators/performance_test_generator_test.rb +++ b/railties/test/generators/performance_test_generator_test.rb @@ -7,6 +7,6 @@ class PerformanceTestGeneratorTest < Rails::Generators::TestCase def test_performance_test_skeleton_is_created run_generator - assert_file "test/performance/performance_test.rb", /class PerformanceTest < ActionController::PerformanceTest/ + assert_file "test/performance/performance_test.rb", /class PerformanceTest < ActionDispatch::PerformanceTest/ end end -- cgit v1.2.3 From 0078df6b54e595421bb486613f7bc3693250b592 Mon Sep 17 00:00:00 2001 From: wycats Date: Sun, 30 May 2010 11:07:34 +0200 Subject: Update template to allow handlers to more cleanly handle encodings (ht: nex3) --- actionpack/lib/action_view/template.rb | 77 +++++++++++----------- actionpack/lib/action_view/template/error.rb | 1 + .../lib/action_view/template/handlers/erb.rb | 52 +++++++-------- actionpack/test/template/template_test.rb | 17 +++-- 4 files changed, 78 insertions(+), 69 deletions(-) diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 5d8ac6b115..53ad24fdc6 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -22,6 +22,10 @@ module ActionView # users will see diamonds with question marks in them in # the browser. # + # For the rest of this documentation, when we say "UTF-8", + # we mean "UTF-8 or whatever the default_internal encoding + # is set to". By default, it will be UTF-8. + # # To mitigate this problem, we use a few strategies: # 1. If the source is not valid UTF-8, we raise an exception # when the template is compiled to alert the user @@ -32,8 +36,7 @@ module ActionView # to the resulting compiled source returned by the # template handler. # 3. In all cases, we transcode the resulting String to - # the default_internal encoding (which defaults - # to UTF-8). + # the UTF-8. # # This means that other parts of Rails can always assume # that templates are encoded in UTF-8, even if the original @@ -60,14 +63,14 @@ module ActionView # # If you want to provide an alternate mechanism for # specifying encodings (like ERB does via <%# encoding: ... %>), - # you may indicate that you are willing to accept - # BINARY data by implementing self.accepts_binary? + # you may indicate that you will handle encodings yourself + # by implementing self.handles_encoding? # on your handler. # - # If you do, Rails will not raise an exception if - # the template's encoding could not be determined, - # assuming that you have another mechanism for - # making the determination. + # If you do, Rails will not try to encode the String + # into the default_internal, passing you the unaltered + # bytes tagged with the assumed encoding (from + # default_external). # # In this case, make sure you return a String from # your handler encoded in the default_internal. Since @@ -171,7 +174,12 @@ module ActionView # before passing the source on to the template engine, leaving a # blank line in its stead. # - # Note that after we figure out the correct encoding, we then + # If the template engine handles encodings, we send the encoded + # String to the engine without further processing. This allows + # the template engine to support additional mechanisms for + # specifying the encoding. For instance, ERB supports <%# encoding: %> + # + # Otherwise, after we figure out the correct encoding, we then # encode the source into Encoding.default_internal. In general, # this means that templates will be UTF-8 inside of Rails, # regardless of the original source encoding. @@ -182,8 +190,11 @@ module ActionView locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join if source.encoding_aware? + # Look for # encoding: *. If we find one, we'll encode the + # String in that encoding, otherwise, we'll use the + # default external encoding. if source.sub!(/\A#{ENCODING_FLAG}/, '') - encoding = $1 + encoding = magic_encoding = $1 else encoding = Encoding.default_external end @@ -192,34 +203,28 @@ module ActionView # or the encoding specified in the file source.force_encoding(encoding) - # If the original encoding is BINARY, the actual - # encoding is either stored out-of-band (such as - # in ERB <%# %> style magic comments) or missing. - # This is also true if the original encoding is - # something other than BINARY, but it's invalid. - if source.encoding != Encoding::BINARY && source.valid_encoding? + # If the user didn't specify an encoding, and the handler + # handles encodings, we simply pass the String as is to + # the handler (with the default_external tag) + if !magic_encoding && @handler.respond_to?(:handles_encoding?) && @handler.handles_encoding? + source + # Otherwise, if the String is valid in the encoding, + # encode immediately to default_internal. This means + # that if a handler doesn't handle encodings, it will + # always get Strings in the default_internal + elsif source.valid_encoding? source.encode! - # If the assumed encoding is incorrect, check to - # see whether the handler accepts BINARY. If it - # does, it has another mechanism for determining - # the true encoding of the String. - elsif @handler.respond_to?(:accepts_binary?) && @handler.accepts_binary? - source.force_encoding(Encoding::BINARY) - # If the handler does not accept BINARY, the - # assumed encoding (either the default_external, - # or the explicit encoding specified by the user) - # is incorrect. We raise an exception here. + # Otherwise, since the String is invalid in the encoding + # specified, raise an exception else raise WrongEncodingError.new(source, encoding) end - - # Don't validate the encoding yet -- the handler - # may treat the String as raw bytes and extract - # the encoding some other way end code = @handler.call(self) + # Make sure that the resulting String to be evalled is in the + # encoding of the code source = <<-end_src def #{method_name}(local_assigns) _old_virtual_path, @_virtual_path = @_virtual_path, #{@virtual_path.inspect};_old_output_buffer = @output_buffer;#{locals_code};#{code} @@ -229,20 +234,16 @@ module ActionView end_src if source.encoding_aware? - # Handlers should return their source Strings in either the - # default_internal or BINARY. If the handler returns a BINARY - # String, we assume its encoding is the one we determined - # earlier, and encode the resulting source in the default_internal. - if source.encoding == Encoding::BINARY - source.force_encoding(Encoding.default_internal) - end + # Make sure the source is in the encoding of the returned code + source.force_encoding(code.encoding) # In case we get back a String from a handler that is not in # BINARY or the default_internal, encode it to the default_internal source.encode! # Now, validate that the source we got back from the template - # handler is valid in the default_internal + # handler is valid in the default_internal. This is for handlers + # that handle encoding but screw up unless source.valid_encoding? raise WrongEncodingError.new(@source, Encoding.default_internal) end diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb index d3a53d2147..e50de7e5af 100644 --- a/actionpack/lib/action_view/template/error.rb +++ b/actionpack/lib/action_view/template/error.rb @@ -13,6 +13,7 @@ module ActionView end def message + @string.force_encoding("BINARY") "Your template was not saved as valid #{@encoding}. Please " \ "either specify #{@encoding} as the encoding for your template " \ "in your text editor, or mark the template with its " \ diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index cbed0108cf..ce609e01af 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -79,51 +79,49 @@ module ActionView ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*") - def self.accepts_binary? + def self.handles_encoding? true end def compile(template) if template.source.encoding_aware? - # Even though Rails has given us a String tagged with the - # default_internal encoding (likely UTF-8), it is possible - # that the String is actually encoded using a different - # encoding, specified via an ERB magic comment. If the - # String is not actually UTF-8, the regular expression - # engine will (correctly) raise an exception. For now, - # we'll reset the String to BINARY so we can run regular - # expressions against it + # First, convert to BINARY, so in case the encoding is + # wrong, we can still find an encoding tag + # (<%# encoding %>) inside the String using a regular + # expression template_source = template.source.dup.force_encoding("BINARY") - # Erubis does not have direct support for encodings. - # As a result, we will extract the ERB-style magic - # comment, give the String to Erubis as BINARY data, - # and then tag the resulting String with the extracted - # encoding later erb = template_source.gsub(ENCODING_TAG, '') encoding = $2 - if !encoding && (template.source.encoding == Encoding::BINARY) - raise WrongEncodingError.new(template_source, Encoding.default_external) - end + erb.force_encoding valid_encoding(template.source.dup, encoding) + + # Always make sure we return a String in the default_internal + erb.encode! else erb = template.source.dup end - result = self.class.erb_implementation.new( + self.class.erb_implementation.new( erb, :trim => (self.class.erb_trim_mode == "-") ).src + end + + private + def valid_encoding(string, encoding) + # If a magic encoding comment was found, tag the + # String with this encoding. This is for a case + # where the original String was assumed to be, + # for instance, UTF-8, but a magic comment + # proved otherwise + string.force_encoding(encoding) if encoding + + # If the String is valid, return the encoding we found + return string.encoding if string.valid_encoding? - # If an encoding tag was found, tag the String - # we're returning with that encoding. Otherwise, - # return a BINARY String, which is what ERB - # returns. Note that if a magic comment was - # not specified, we will return the data to - # Rails as BINARY, which will then use its - # own encoding logic to create a UTF-8 String. - result = "\n#{result}".force_encoding(encoding).encode if encoding - result + # Otherwise, raise an exception + raise WrongEncodingError.new(string, string.encoding) end end end diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 995d728d50..18e0e83ec3 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -114,10 +114,12 @@ class TestERBTemplate < ActiveSupport::TestCase end def test_encoding_can_be_specified_with_magic_comment_in_erb - @template = new_template("<%# encoding: ISO-8859-1 %>hello \xFCmlat") - result = render - assert_equal Encoding::UTF_8, render.encoding - assert_equal "hello \u{fc}mlat", render + with_external_encoding Encoding::UTF_8 do + @template = new_template("<%# encoding: ISO-8859-1 %>hello \xFCmlat") + result = render + assert_equal Encoding::UTF_8, render.encoding + assert_equal "hello \u{fc}mlat", render + end end def test_error_when_template_isnt_valid_utf8 @@ -126,5 +128,12 @@ class TestERBTemplate < ActiveSupport::TestCase render end end + + def with_external_encoding(encoding) + old, Encoding.default_external = Encoding.default_external, encoding + yield + ensure + Encoding.default_external = old + end end end \ No newline at end of file -- cgit v1.2.3 From b870daba5ff71973b237616fb95f90bb321ae7fb Mon Sep 17 00:00:00 2001 From: wycats Date: Sun, 30 May 2010 12:11:50 +0200 Subject: Update CHANGELOG --- actionpack/CHANGELOG | 2 ++ railties/CHANGELOG | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 54c7771f4c..faa0d674dc 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0.0 [beta 4/release candidate] (unreleased)* +* Remove middleware laziness [José Valim] + * Make session stores rely on request.cookie_jar and change set_session semantics to return the cookie value instead of a boolean. [José Valim] * OAuth 2: HTTP Token Authorization support to complement Basic and Digest Authorization. [Rick Olson] diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 1d76c77ade..fe3ab3cdcf 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,7 +1,7 @@ *Rails 3.0.0 [beta 4/release candidate] (unreleased)* * Version bump - +* Removed Rails Metal [YK & JV]. *Rails 3.0.0 [beta 3] (April 13th, 2010)* -- cgit v1.2.3 From 9a93844aba44319d3c8487a554124beb00ccc267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 30 May 2010 15:53:14 +0200 Subject: Add :only and :except to controllers MiddlewareStack. This allows you to do the following: class PostsController < ApplicationController use AutheMiddleware, :except => [:index, :show] end --- actionpack/lib/action_controller/metal.rb | 48 ++++++++++++++++++++-- actionpack/lib/action_dispatch/middleware/stack.rb | 8 ++-- .../test/controller/new_base/middleware_test.rb | 33 ++++++++++----- 3 files changed, 71 insertions(+), 18 deletions(-) diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 30aa34d956..775a5002e2 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -1,6 +1,48 @@ require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/object/blank' +require 'action_dispatch/middleware/stack' module ActionController + # Extend ActionDispatch middleware stack to make it aware of options + # allowing the following syntax in controllers: + # + # class PostsController < ApplicationController + # use AuthenticationMiddleware, :except => [:index, :show] + # end + # + class MiddlewareStack < ActionDispatch::MiddlewareStack #:nodoc: + class Middleware < ActionDispatch::MiddlewareStack::Middleware #:nodoc: + def initialize(klass, *args) + options = args.extract_options! + @only = Array(options.delete(:only)).map(&:to_s) + @except = Array(options.delete(:except)).map(&:to_s) + args << options unless options.empty? + super + end + + def valid?(action) + if @only.present? + @only.include?(action) + elsif @except.present? + !@except.include?(action) + else + true + end + end + end + + def build(action, app=nil, &block) + app ||= block + action = action.to_s + raise "MiddlewareStack#build requires an app" unless app + + reverse.inject(app) do |a, middleware| + middleware.valid?(action) ? + middleware.build(a) : a + end + end + end + # ActionController::Metal provides a way to get a valid Rack application from a controller. # # In AbstractController, dispatching is triggered directly by calling #process on a new controller. @@ -91,10 +133,10 @@ module ActionController end class_attribute :middleware_stack - self.middleware_stack = ActionDispatch::MiddlewareStack.new + self.middleware_stack = ActionController::MiddlewareStack.new def self.inherited(base) - self.middleware_stack = base.middleware_stack.dup + base.middleware_stack = self.middleware_stack.dup super end @@ -120,7 +162,7 @@ module ActionController # ==== Returns # Proc:: A rack application def self.action(name, klass = ActionDispatch::Request) - middleware_stack.build do |env| + middleware_stack.build(name.to_s) do |env| new.dispatch(name, klass.new(env)) end end diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 0e5ab507df..e3180dba77 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -55,7 +55,7 @@ module ActionDispatch def insert(index, *args, &block) index = self.index(index) unless index.is_a?(Integer) - middleware = Middleware.new(*args, &block) + middleware = self.class::Middleware.new(*args, &block) super(index, middleware) end @@ -73,7 +73,7 @@ module ActionDispatch end def use(*args, &block) - middleware = Middleware.new(*args, &block) + middleware = self.class::Middleware.new(*args, &block) push(middleware) end @@ -82,8 +82,8 @@ module ActionDispatch "was removed from the middleware stack", caller end - def build(app = nil, &blk) - app ||= blk + def build(app = nil, &block) + app ||= block raise "MiddlewareStack#build requires an app" unless app reverse.inject(app) { |a, e| e.build(a) } end diff --git a/actionpack/test/controller/new_base/middleware_test.rb b/actionpack/test/controller/new_base/middleware_test.rb index 65942ebc15..26a66c91a6 100644 --- a/actionpack/test/controller/new_base/middleware_test.rb +++ b/actionpack/test/controller/new_base/middleware_test.rb @@ -28,7 +28,6 @@ module MiddlewareTest class MyController < ActionController::Metal use MyMiddleware - middleware.insert_before MyMiddleware, ExclaimerMiddleware def index @@ -39,8 +38,23 @@ module MiddlewareTest class InheritedController < MyController end - module MiddlewareTests - extend ActiveSupport::Testing::Declarative + class ActionsController < ActionController::Metal + use MyMiddleware, :only => :show + middleware.insert_before MyMiddleware, ExclaimerMiddleware, :except => :index + + def index + self.response_body = "index" + end + + def show + self.response_body = "show" + end + end + + class TestMiddleware < ActiveSupport::TestCase + def setup + @app = MyController.action(:index) + end test "middleware that is 'use'd is called as part of the Rack application" do result = @app.call(env_for("/")) @@ -52,13 +66,13 @@ module MiddlewareTest result = @app.call(env_for("/")) assert_equal "First!", result[1]["Middleware-Order"] end - end - class TestMiddleware < ActiveSupport::TestCase - include MiddlewareTests + test "middleware stack accepts only and except as options" do + result = ActionsController.action(:show).call(env_for("/")) + assert_equal "First!", result[1]["Middleware-Order"] - def setup - @app = MyController.action(:index) + result = ActionsController.action(:index).call(env_for("/")) + assert_nil result[1]["Middleware-Order"] end def env_for(url) @@ -70,8 +84,5 @@ module MiddlewareTest def setup @app = InheritedController.action(:index) end - - test "middleware inherits" do - end end end -- cgit v1.2.3 From 82f67586b29b97de56a8d36569cd8477183d0623 Mon Sep 17 00:00:00 2001 From: eparreno Date: Mon, 31 May 2010 10:37:13 +0200 Subject: AR validations & callbacks: update callbacks list --- .../source/activerecord_validations_callbacks.textile | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile index 857551c9d5..d83ea57864 100644 --- a/railties/guides/source/activerecord_validations_callbacks.textile +++ b/railties/guides/source/activerecord_validations_callbacks.textile @@ -879,32 +879,28 @@ Here is a list with all the available Active Record callbacks, listed in the sam h4. Creating an Object * +before_validation+ -* +before_validation_on_create+ * +after_validation+ -* +after_validation_on_create+ * +before_save+ +* +after_save+ * +before_create+ -* INSERT OPERATION +* +around_create+ * +after_create+ -* +after_save+ h4. Updating an Object * +before_validation+ -* +before_validation_on_update+ * +after_validation+ -* +after_validation_on_update+ * +before_save+ +* +after_save+ * +before_update+ -* UPDATE OPERATION +* +around_update+ * +after_update+ -* +after_save+ h4. Destroying an Object * +before_destroy+ -* DELETE OPERATION * +after_destroy+ +* +around_destroy+ WARNING. +after_save+ runs both on create and update, but always _after_ the more specific callbacks +after_create+ and +after_update+, no matter the order in which the macro calls were executed. -- cgit v1.2.3 From f5104caf3b36a206aaf8a4355a2b3a73bbf55e5b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 29 May 2010 16:40:16 -0300 Subject: rack-test version updated and removed from Gemfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- Gemfile | 1 - actionpack/actionpack.gemspec | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 3b347ea9ef..214fdf77da 100644 --- a/Gemfile +++ b/Gemfile @@ -39,7 +39,6 @@ elsif RUBY_ENGINE == "jruby" end # AP -gem "rack-test", "0.5.3", :require => 'rack/test' gem "RedCloth", ">= 4.2.2" group :documentation do diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index a5abe9be10..64a4441034 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', version) s.add_dependency('activemodel', version) s.add_dependency('rack', '~> 1.1.0') - s.add_dependency('rack-test', '~> 0.5.0') + s.add_dependency('rack-test', '~> 0.5.4') s.add_dependency('rack-mount', '~> 0.6.3') s.add_dependency('erubis', '~> 2.6.5') end -- cgit v1.2.3 From 1854209bb3d06bc81034dfec4ef75412700eae74 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 31 May 2010 07:31:08 -0300 Subject: Unforce i18n from AS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/actionpack.gemspec | 1 + activemodel/activemodel.gemspec | 1 + activesupport/activesupport.gemspec | 1 - .../lib/active_support/core_ext/array/conversions.rb | 12 +++++++++--- .../lib/active_support/core_ext/string/interpolation.rb | 1 + activesupport/lib/active_support/i18n.rb | 9 +++++++-- 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 64a4441034..040d05f050 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', version) s.add_dependency('activemodel', version) + s.add_dependency('i18n', '~> 0.4.0') s.add_dependency('rack', '~> 1.1.0') s.add_dependency('rack-test', '~> 0.5.4') s.add_dependency('rack-mount', '~> 0.6.3') diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index 9695911398..f06761ceb9 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -20,4 +20,5 @@ Gem::Specification.new do |s| s.has_rdoc = true s.add_dependency('activesupport', version) + s.add_dependency('i18n', '~> 0.4.0') end diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 09635c2f18..b07e74c5d4 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -19,7 +19,6 @@ Gem::Specification.new do |s| s.has_rdoc = true - s.add_dependency('i18n', '~> 0.4.0') s.add_dependency('tzinfo', '~> 0.3.16') s.add_dependency('builder', '~> 2.1.2') s.add_dependency('memcache-client', '>= 1.7.5') diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index 2b07f05d27..7e4d30f5e8 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -9,9 +9,15 @@ class Array # * :two_words_connector - The sign or word used to join the elements in arrays with two elements (default: " and ") # * :last_word_connector - The sign or word used to join the last element in arrays with three or more elements (default: ", and ") def to_sentence(options = {}) - default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale]) - default_two_words_connector = I18n.translate(:'support.array.two_words_connector', :locale => options[:locale]) - default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale]) + if defined?(I18n) + default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale]) + default_two_words_connector = I18n.translate(:'support.array.two_words_connector', :locale => options[:locale]) + default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale]) + else + default_words_connector = ", " + default_two_words_connector = " and " + default_last_word_connector = ", and " + end options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale) options.reverse_merge! :words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector diff --git a/activesupport/lib/active_support/core_ext/string/interpolation.rb b/activesupport/lib/active_support/core_ext/string/interpolation.rb index 932117cc10..7f764e9de1 100644 --- a/activesupport/lib/active_support/core_ext/string/interpolation.rb +++ b/activesupport/lib/active_support/core_ext/string/interpolation.rb @@ -1 +1,2 @@ +require 'active_support/i18n' require 'i18n/core_ext/string/interpolate' diff --git a/activesupport/lib/active_support/i18n.rb b/activesupport/lib/active_support/i18n.rb index 11af48d67e..0ffdd904fd 100644 --- a/activesupport/lib/active_support/i18n.rb +++ b/activesupport/lib/active_support/i18n.rb @@ -1,3 +1,8 @@ -require 'i18n' +begin + require 'i18n' +rescue LoadError => e + $stderr.puts "You don't have i18n installed in your application. Please add it to your Gemfile and run bundle install" + raise e +end I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml" -ActiveSupport.run_load_hooks(:i18n) \ No newline at end of file +ActiveSupport.run_load_hooks(:i18n) -- cgit v1.2.3 From ea037ff55791a33d24773efd380b734f733c2815 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 31 May 2010 13:48:47 -0500 Subject: Base options cant live in lazy loaded helpers as they then wont be available to set for config --- actionpack/lib/action_view/base.rb | 4 ++++ actionpack/lib/action_view/helpers/active_model_helper.rb | 7 ------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 735398d972..f4af763afe 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -165,6 +165,10 @@ module ActionView #:nodoc: cattr_accessor :debug_rjs @@debug_rjs = false + # Specify the proc used to decorate input tags that refer to attributes with errors. + cattr_accessor :field_error_proc + @@field_error_proc = Proc.new{ |html_tag, instance| "
#{html_tag}
".html_safe } + class_attribute :helpers remove_method :helpers attr_reader :helpers diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index 0cddd09eb0..8054de0af6 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -4,13 +4,6 @@ require 'active_support/core_ext/enumerable' require 'active_support/core_ext/object/blank' module ActionView - ActiveSupport.on_load(:action_view) do - class ActionView::Base - @@field_error_proc = Proc.new{ |html_tag, instance| "
#{html_tag}
".html_safe } - cattr_accessor :field_error_proc - end - end - module Helpers module ActiveModelHelper %w(input form error_messages_for error_message_on).each do |method| -- cgit v1.2.3 From 0bed93be25e6bcae2b1a74cec70413118be66736 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 1 Jun 2010 04:12:04 -0300 Subject: Unforce tzinfo from AS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/actionpack.gemspec | 1 + activerecord/activerecord.gemspec | 1 + activesupport/activesupport.gemspec | 1 - activesupport/lib/active_support/values/time_zone.rb | 8 +++++++- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 040d05f050..f20c964003 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -25,5 +25,6 @@ Gem::Specification.new do |s| s.add_dependency('rack', '~> 1.1.0') s.add_dependency('rack-test', '~> 0.5.4') s.add_dependency('rack-mount', '~> 0.6.3') + s.add_dependency('tzinfo', '~> 0.3.16') s.add_dependency('erubis', '~> 2.6.5') end diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index 59caa53be0..44c8fb83e1 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -24,4 +24,5 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', version) s.add_dependency('activemodel', version) s.add_dependency('arel', '~> 0.3.3') + s.add_dependency('tzinfo', '~> 0.3.16') end diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index b07e74c5d4..4179bc27b3 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -19,7 +19,6 @@ Gem::Specification.new do |s| s.has_rdoc = true - s.add_dependency('tzinfo', '~> 0.3.16') s.add_dependency('builder', '~> 2.1.2') s.add_dependency('memcache-client', '>= 1.7.5') end diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 2ac5134911..67b37785f5 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -1,5 +1,11 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/try' +begin + require 'tzinfo' +rescue LoadError => e + $stderr.puts "You don't have tzinfo installed in your application. Please add it to your Gemfile and run bundle install" + raise e +end # The TimeZone class serves as a wrapper around TZInfo::Timezone instances. It allows us to do the following: # @@ -313,7 +319,7 @@ module ActiveSupport # TODO: Preload instead of lazy load for thread safety def self.find_tzinfo(name) - require 'tzinfo' unless defined?(::TZInfo) + require 'active_support/tzinfo' unless defined?(::TZInfo) ::TZInfo::TimezoneProxy.new(MAPPING[name] || name) end -- cgit v1.2.3 From 31e1445a8194f1eab70ac8c7d45797f0708c6c8e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 1 Jun 2010 04:57:34 -0300 Subject: Unforce builder from AS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/actionpack.gemspec | 1 + activemodel/activemodel.gemspec | 1 + activesupport/activesupport.gemspec | 1 - activesupport/lib/active_support/builder.rb | 6 ++++++ activesupport/lib/active_support/core_ext/array/conversions.rb | 2 +- activesupport/lib/active_support/core_ext/hash/conversions.rb | 2 +- 6 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 activesupport/lib/active_support/builder.rb diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index f20c964003..0f45cb5a4a 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', version) s.add_dependency('activemodel', version) + s.add_dependency('builder', '~> 2.1.2') s.add_dependency('i18n', '~> 0.4.0') s.add_dependency('rack', '~> 1.1.0') s.add_dependency('rack-test', '~> 0.5.4') diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index f06761ceb9..678007c0ef 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -20,5 +20,6 @@ Gem::Specification.new do |s| s.has_rdoc = true s.add_dependency('activesupport', version) + s.add_dependency('builder', '~> 2.1.2') s.add_dependency('i18n', '~> 0.4.0') end diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 4179bc27b3..f2ee35ce75 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -19,6 +19,5 @@ Gem::Specification.new do |s| s.has_rdoc = true - s.add_dependency('builder', '~> 2.1.2') s.add_dependency('memcache-client', '>= 1.7.5') end diff --git a/activesupport/lib/active_support/builder.rb b/activesupport/lib/active_support/builder.rb new file mode 100644 index 0000000000..321e462acd --- /dev/null +++ b/activesupport/lib/active_support/builder.rb @@ -0,0 +1,6 @@ +begin + require 'builder' +rescue LoadError => e + $stderr.puts "You don't have builder installed in your application. Please add it to your Gemfile and run bundle install" + raise e +end diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index 7e4d30f5e8..79e3828817 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -134,7 +134,7 @@ class Array # # def to_xml(options = {}) - require 'builder' unless defined?(Builder) + require 'active_support/builder' unless defined?(Builder) options = options.dup options[:indent] ||= 2 diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index 14e5d2f8ac..565c9af7fb 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -55,7 +55,7 @@ class Hash # configure your own builder with the :builder option. The method also accepts # options like :dasherize and friends, they are forwarded to the builder. def to_xml(options = {}) - require 'builder' unless defined?(Builder) + require 'active_support/builder' unless defined?(Builder) options = options.dup options[:indent] ||= 2 -- cgit v1.2.3 From 57144388f0b4c31e43ced7cfd1d6efaded88cf5e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 1 Jun 2010 05:06:17 -0300 Subject: Unforce memcache from AS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- Gemfile | 3 +++ activesupport/activesupport.gemspec | 2 -- activesupport/lib/active_support/cache/mem_cache_store.rb | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 214fdf77da..9f11869f4c 100644 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,9 @@ elsif RUBY_ENGINE == "jruby" gem "jruby-openssl" end +# AS +gem "memcache-client", ">= 1.7.5" + # AR if mri || RUBY_ENGINE == "rbx" gem "sqlite3-ruby", "= 1.3.0.beta.2", :require => 'sqlite3' diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index f2ee35ce75..8611a1e5fa 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -18,6 +18,4 @@ Gem::Specification.new do |s| s.require_path = 'lib' s.has_rdoc = true - - s.add_dependency('memcache-client', '>= 1.7.5') end diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index d8377a208f..e3a2688e2f 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -1,4 +1,9 @@ -require 'memcache' +begin + require 'memcache' +rescue LoadError => e + $stderr.puts "You don't have memcache installed in your application. Please add it to your Gemfile and run bundle install" + raise e +end require 'digest/md5' module ActiveSupport -- cgit v1.2.3 From 0cc4cd020da024674b5cf20ab23ff7498bc55f4a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 1 Jun 2010 06:32:16 -0300 Subject: Unforce text-format from AM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- Gemfile | 3 +++ actionmailer/actionmailer.gemspec | 1 - actionmailer/lib/action_mailer.rb | 6 ------ actionmailer/lib/action_mailer/mail_helper.rb | 7 +++++++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index 9f11869f4c..d57afc8630 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,9 @@ end # AS gem "memcache-client", ">= 1.7.5" +# AM +gem "text-format", "~> 1.0.0" + # AR if mri || RUBY_ENGINE == "rbx" gem "sqlite3-ruby", "= 1.3.0.beta.2", :require => 'sqlite3' diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index 280771e4db..4706b63b79 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -21,5 +21,4 @@ Gem::Specification.new do |s| s.add_dependency('actionpack', version) s.add_dependency('mail', '~> 2.2.1') - s.add_dependency('text-format', '~> 1.0.0') end diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 70cc312634..6e2d288082 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -49,9 +49,3 @@ module ActionMailer autoload :TestCase autoload :TestHelper end - -module Text - extend ActiveSupport::Autoload - - autoload :Format, 'text/format' -end diff --git a/actionmailer/lib/action_mailer/mail_helper.rb b/actionmailer/lib/action_mailer/mail_helper.rb index ab5c3469b2..aab6e12387 100644 --- a/actionmailer/lib/action_mailer/mail_helper.rb +++ b/actionmailer/lib/action_mailer/mail_helper.rb @@ -3,6 +3,13 @@ module ActionMailer # Uses Text::Format to take the text and format it, indented two spaces for # each line, and wrapped at 72 columns. def block_format(text) + begin + require 'text/format' + rescue LoadError => e + $stderr.puts "You don't have text-format installed in your application. Please add it to your Gemfile and run bundle install" + raise e + end unless defined?(Text::Format) + formatted = text.split(/\n\r\n/).collect { |paragraph| Text::Format.new( :columns => 72, :first_indent => 2, :body_indent => 2, :text => paragraph -- cgit v1.2.3 From a0bb1dda119a7488b8a4d61b354a64e619b0d1b3 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 1 Jun 2010 15:44:14 +0200 Subject: revises rdoc of AMo::Error#add [#4738 state:resolved] --- activemodel/lib/active_model/errors.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 14afc5265f..15d468f5d8 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -170,13 +170,13 @@ module ActiveModel end end - # Adds an error message (+messsage+) to the +attribute+, which will be returned on a call to on(attribute) - # for the same attribute and ensure that this error object returns false when asked if empty?. More than one - # error can be added to the same +attribute+ in which case an array will be returned on a call to on(attribute). - # If no +messsage+ is supplied, :invalid is assumed. + # Adds +message+ to the error messages on +attribute+, which will be returned on a call to + # on(attribute) for the same attribute. More than one error can be added to the same + # +attribute+ in which case an array will be returned on a call to on(attribute). + # If no +message+ is supplied, :invalid is assumed. # - # If +message+ is a Symbol, it will be translated, using the appropriate scope (see translate_error). - # If +message+ is a Proc, it will be called, allowing for things like Time.now to be used within an error + # If +message+ is a symbol, it will be translated using the appropriate scope (see +translate_error+). + # If +message+ is a proc, it will be called, allowing for things like Time.now to be used within an error. def add(attribute, message = nil, options = {}) message ||= :invalid message = generate_message(attribute, message, options) if message.is_a?(Symbol) -- cgit v1.2.3 From d57397c4b62b6474ff8eb55bfd763f5e6dcdcd40 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 1 Jun 2010 16:38:42 -0500 Subject: Extracted String#truncate from TextHelper#truncate [DHH] --- actionpack/lib/action_view/helpers/text_helper.rb | 16 ++++------- activesupport/CHANGELOG | 2 ++ .../lib/active_support/core_ext/string/filters.rb | 33 ++++++++++++++++++++++ activesupport/test/core_ext/string_ext_test.rb | 29 +++++++++++++++++++ 4 files changed, 69 insertions(+), 11 deletions(-) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 41423d4e2e..860c1de6af 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/filters' require 'action_view/helpers/tag_helper' module ActionView @@ -42,7 +43,7 @@ module ActionView # ==== Examples # # truncate("Once upon a time in a world far far away") - # # => Once upon a time in a world... + # # => Once upon a time in a worl... # # truncate("Once upon a time in a world far far away", :separator => ' ') # # => Once upon a time in a world... @@ -50,9 +51,6 @@ module ActionView # truncate("Once upon a time in a world far far away", :length => 14) # # => Once upon a... # - # truncate("And they found that many people were sleeping better.", :length => 25, "(clipped)") - # # => And they found t(clipped) - # # truncate("And they found that many people were sleeping better.", :omission => "... (continued)", :length => 25) # # => And they f... (continued) # @@ -73,14 +71,10 @@ module ActionView options[:length] = args[0] || 30 options[:omission] = args[1] || "..." end - options.reverse_merge!(:length => 30, :omission => "...") - if text - l = options[:length] - options[:omission].mb_chars.length - chars = text.mb_chars - stop = options[:separator] ? (chars.rindex(options[:separator].mb_chars, l) || l) : l - (chars.length > options[:length] ? chars[0...stop] + options[:omission] : text).to_s - end + options.reverse_merge!(:length => 30) + + text.truncate(options.delete(:length), options) if text end # Highlights one or more +phrases+ everywhere in +text+ by inserting it into diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 0a25ad0406..d853788e00 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0.0 [beta 4/release candidate] (unreleased)* +* Extracted String#truncate from TextHelper#truncate [DHH] + * Ruby 1.9: support UTF-8 case folding. #4595 [Norman Clarke] * Renames Array#rand -> Array#random_element. [Santiago Pastorino, Rizwan Reza] diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb index 6fda7efef5..cdd86a836f 100644 --- a/activesupport/lib/active_support/core_ext/string/filters.rb +++ b/activesupport/lib/active_support/core_ext/string/filters.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/string/multibyte' + class String # Returns the string, first removing all whitespace on both ends of # the string, and then changing remaining consecutive whitespace @@ -17,4 +19,35 @@ class String gsub!(/\s+/, ' ') self end + + # Truncates a given +text+ after a given length if +text+ is longer than length. + # The last characters will be replaced with the :omission (defaults to "...") + # for a total length not exceeding :length. + # + # Pass a :separator to truncate +text+ at a natural break. + # + # ==== Examples + # + # "Once upon a time in a world far far away".truncate(30) + # # => Once upon a time in a worl... + # + # "Once upon a time in a world far far away".truncate(30, :separator => ' ') + # # => Once upon a time in a world... + # + # "Once upon a time in a world far far away".truncate(14) + # # => Once upon a... + # + # "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)") + # # => And they f... (continued) + def truncate(length, options = {}) + text = self.dup + options[:omission] ||= "..." + + length_with_room_for_omission = length - options[:omission].mb_chars.length + chars = text.mb_chars + stop = options[:separator] ? + (chars.rindex(options[:separator].mb_chars, length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission + + (chars.length > length ? chars[0...stop] + options[:omission] : text).to_s + end end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 759b0ddcd6..d9702dd9ff 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -210,6 +210,35 @@ class StringInflectionsTest < Test::Unit::TestCase # And changes the original string: assert_equal original, expected end + + def test_truncate + assert_equal "Hello World!", "Hello World!".truncate(12) + assert_equal "Hello Wor...", "Hello World!!".truncate(12) + end + + def test_truncate_with_omission_and_seperator + assert_equal "Hello[...]", "Hello World!".truncate(10, :omission => "[...]") + assert_equal "Hello[...]", "Hello Big World!".truncate(13, :omission => "[...]", :separator => ' ') + assert_equal "Hello Big[...]", "Hello Big World!".truncate(14, :omission => "[...]", :separator => ' ') + assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, :omission => "[...]", :separator => ' ') + end + + if RUBY_VERSION < '1.9.0' + def test_truncate_multibyte + with_kcode 'none' do + assert_equal "\354\225\210\353\205\225\355...", "\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224".truncate(10) + end + with_kcode 'u' do + assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...", + "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".truncate(10) + end + end + else + def test_truncate_multibyte + assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'), + "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8').truncate(10) + end + end end class StringBehaviourTest < Test::Unit::TestCase -- cgit v1.2.3 From 158473f0d113f0c0b02ba9b7353c10949172a1f7 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Wed, 2 Jun 2010 00:28:23 +0200 Subject: AS guide: documents String#truncate --- .../source/active_support_core_extensions.textile | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 08fddd2926..de82e871a6 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -1254,6 +1254,39 @@ There's also the destructive version +String#squish!+. NOTE: Defined in +active_support/core_ext/string/filters.rb+. +h4. +truncate+ + +The method +truncate+ returns a copy of its receiver truncated after a given +length+: + + +"Oh dear! Oh dear! I shall be late!".truncate(20) +# => "Oh dear! Oh dear!..." + + +Ellipsis can be customized with the +:omission+ option: + + +"Oh dear! Oh dear! I shall be late!".truncate(20, :omission => '…') +# => "Oh dear! Oh …" + + +Note in particular that truncation takes into account the length of the omission string. + +Pass a +:separator+ to truncate the string at a natural break: + + +"Oh dear! Oh dear! I shall be late!".truncate(18) +# => "Oh dear! Oh dea..." +"Oh dear! Oh dear! I shall be late!".truncate(18, :separator => ' ') +# => "Oh dear! Oh..." + + +In the above example "dear" gets cut first, but then +:separator+ prevents it. + +WARNING: The option +:separator+ can't be a regexp. + +NOTE: Defined in +active_support/core_ext/string/filters.rb+. + h4. Key-based Interpolation In Ruby 1.9 the % string operator supports key-based interpolation, both formatted and unformatted: -- cgit v1.2.3 From 5a0d73f17ce5590b1246d90ef54b6c6234f0fd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 2 Jun 2010 00:42:20 +0200 Subject: Add lib to load paths when application is inherited to be able to load lib code during configuration. --- railties/lib/rails/application.rb | 11 +++++++++++ railties/lib/rails/application/finisher.rb | 2 +- .../test/application/initializers/load_path_test.rb | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 7416e94eeb..85ae8cbbb1 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -67,6 +67,7 @@ module Rails raise "You cannot have more than one Rails::Application" if Rails.application super Rails.application = base.instance + Rails.application.add_lib_to_load_paths! ActiveSupport.run_load_hooks(:before_configuration, base.instance) end @@ -83,11 +84,21 @@ module Rails delegate :middleware, :to => :config + def add_lib_to_load_paths! + path = config.root.join('lib').to_s + $LOAD_PATH.unshift(path) if File.exists?(path) + end + def require_environment! environment = paths.config.environment.to_a.first require environment if environment end + def eager_load! + railties.all(&:eager_load!) + super + end + def routes @routes ||= ActionDispatch::Routing::RouteSet.new end diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index fbab4d5515..d7ff489336 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -38,7 +38,7 @@ module Rails initializer :eager_load! do if config.cache_classes && !$rails_rake_task ActiveSupport.run_load_hooks(:before_eager_load, self) - railties.all(&:eager_load!) + eager_load! end end diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb index b39b9ecaae..d31915e129 100644 --- a/railties/test/application/initializers/load_path_test.rb +++ b/railties/test/application/initializers/load_path_test.rb @@ -19,6 +19,23 @@ module ApplicationTests assert $:.include?("#{app_path}/app/models") end + test "initializing an application adds lib path on inheritance hook" do + app_file "lib/foo.rb", <<-RUBY + module Foo; end + RUBY + + add_to_config <<-RUBY + require "foo" + raise "Expected Foo to be defined" unless defined?(Foo) + RUBY + + assert_nothing_raised do + require "#{app_path}/config/environment" + end + + assert $:.include?("#{app_path}/lib") + end + test "initializing an application eager load any path under app" do app_file "app/anything/foo.rb", <<-RUBY module Foo; end -- cgit v1.2.3 From 315e8952dfbaecd4d5175ea4d0fd95611cad9e01 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Wed, 2 Jun 2010 01:34:39 +0200 Subject: revises the documentation of String#truncate and the truncate helper --- actionpack/lib/action_view/helpers/text_helper.rb | 18 +++++++++--------- .../lib/active_support/core_ext/string/filters.rb | 22 +++++++++------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 860c1de6af..bfad9f8d31 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -43,25 +43,25 @@ module ActionView # ==== Examples # # truncate("Once upon a time in a world far far away") - # # => Once upon a time in a worl... + # # => "Once upon a time in a world..." # - # truncate("Once upon a time in a world far far away", :separator => ' ') - # # => Once upon a time in a world... + # truncate("Once upon a time in a world far far away", :length => 17) + # # => "Once upon a ti..." # - # truncate("Once upon a time in a world far far away", :length => 14) - # # => Once upon a... + # truncate("Once upon a time in a world far far away", :lenght => 17, :separator => ' ') + # # => "Once upon a..." # - # truncate("And they found that many people were sleeping better.", :omission => "... (continued)", :length => 25) - # # => And they f... (continued) + # truncate("And they found that many people were sleeping better.", :length => 25, :omission => '... (continued)') + # # => "And they f... (continued)" # # You can still use truncate with the old API that accepts the # +length+ as its optional second and the +ellipsis+ as its # optional third parameter: # truncate("Once upon a time in a world far far away", 14) - # # => Once upon a... + # # => "Once upon a..." # # truncate("And they found that many people were sleeping better.", 25, "... (continued)") - # # => And they f... (continued) + # # => "And they f... (continued)" def truncate(text, *args) options = args.extract_options! unless args.empty? diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb index cdd86a836f..e15a1df9c9 100644 --- a/activesupport/lib/active_support/core_ext/string/filters.rb +++ b/activesupport/lib/active_support/core_ext/string/filters.rb @@ -20,25 +20,21 @@ class String self end - # Truncates a given +text+ after a given length if +text+ is longer than length. - # The last characters will be replaced with the :omission (defaults to "...") - # for a total length not exceeding :length. + # Truncates a given +text+ after a given length if +text+ is longer than length: # - # Pass a :separator to truncate +text+ at a natural break. + # "Once upon a time in a world far far away".truncate(27) + # # => "Once upon a time in a wo..." # - # ==== Examples + # The last characters will be replaced with the :omission string (defaults to "...") + # for a total length not exceeding :length: # - # "Once upon a time in a world far far away".truncate(30) - # # => Once upon a time in a worl... + # "Once upon a time in a world far far away".truncate(27, :separator => ' ') + # # => "Once upon a time in a..." # - # "Once upon a time in a world far far away".truncate(30, :separator => ' ') - # # => Once upon a time in a world... - # - # "Once upon a time in a world far far away".truncate(14) - # # => Once upon a... + # Pass a :separator to truncate +text+ at a natural break: # # "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)") - # # => And they f... (continued) + # # => "And they f... (continued)" def truncate(length, options = {}) text = self.dup options[:omission] ||= "..." -- cgit v1.2.3 From afc102698672cdf546a15424471d3287a39dbb06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 2 Jun 2010 08:45:03 +0200 Subject: Still copy application configuration to generator even if they are required earlier. Also tidy up the guide a little bit. --- railties/guides/source/generators.textile | 12 ++++-------- railties/lib/rails/commands/destroy.rb | 1 + railties/lib/rails/commands/generate.rb | 1 + railties/lib/rails/generators.rb | 8 ++------ railties/test/generators/generators_test_helper.rb | 7 +++++-- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile index d3757e9733..b77a2837c3 100644 --- a/railties/guides/source/generators.textile +++ b/railties/guides/source/generators.textile @@ -322,14 +322,10 @@ config.generators do |g| g.template_engine :erb g.test_framework :shoulda, :fixture => false g.stylesheets false -end - - -And at the end of the same file: - -require 'rails/generators' -Rails::Generators.fallbacks[:shoulda] = :test_unit + # Add a fallback! + g.fallbacks[:should] = :test_unit +end Now, if create a Comment scaffold, you will see that shoulda generators are being invoked, and at the end, they are just falling back to test unit generators: @@ -361,7 +357,7 @@ $ rails generate scaffold Comment body:text create test/unit/helpers/comments_helper_test.rb -Such tool allows your generators to have single responsibility, increasing the code reuse and reducing the amount of code duplication. +Such tool allows your generators to have single responsibility, increasing the code reuse and reducing the amount of duplication. h3. Changelog diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb index 9023c61bf2..db59cd8ad9 100644 --- a/railties/lib/rails/commands/destroy.rb +++ b/railties/lib/rails/commands/destroy.rb @@ -1,4 +1,5 @@ require 'rails/generators' +Rails::Generators.configure! if [nil, "-h", "--help"].include?(ARGV.first) Rails::Generators.help 'destroy' diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb index 7d05a30de8..1b3eef504a 100755 --- a/railties/lib/rails/commands/generate.rb +++ b/railties/lib/rails/commands/generate.rb @@ -1,4 +1,5 @@ require 'rails/generators' +Rails::Generators.configure! if [nil, "-h", "--help"].include?(ARGV.first) Rails::Generators.help 'generate' diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index fe8a6c0b94..af92757053 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -68,6 +68,7 @@ module Rails options.deep_merge! config.options fallbacks.merge! config.fallbacks templates_path.concat config.templates + templates_path.uniq! end def self.templates_path @@ -328,10 +329,5 @@ module Rails paths.uniq! paths end - end -end - -# If the application was already defined, configure generators, -# otherwise you have to configure it by hand. -Rails::Generators.configure! if Rails.respond_to?(:application) && Rails.application +end \ No newline at end of file diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index d8bdb344f2..4a5a9b2932 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -1,4 +1,6 @@ require 'abstract_unit' +require 'rails/generators' +require 'rails/generators/test_case' module Rails def self.root @@ -8,8 +10,9 @@ end Rails.application.config.root = Rails.root Rails.application.config.generators.templates = [File.join(Rails.root, "lib", "templates")] -require 'rails/generators' -require 'rails/generators/test_case' +# Call configure to load the settings from +# Rails.application.config.generators to Rails::Generators +Rails::Generators.configure! require 'active_record' require 'action_dispatch' -- cgit v1.2.3 From 0570720d667b5fe55aeebfba087064788d4d2ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 2 Jun 2010 09:37:38 +0200 Subject: Configure generators before invoking. --- activerecord/lib/active_record/railties/databases.rake | 1 + 1 file changed, 1 insertion(+) diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index cb7eade0ab..952f2a3070 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -435,6 +435,7 @@ namespace :db do task :create => :environment do raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations? require 'rails/generators' + Rails::Generators.configure! require 'rails/generators/rails/session_migration/session_migration_generator' Rails::Generators::SessionMigrationGenerator.start [ ENV["MIGRATION"] || "add_sessions_table" ] end -- cgit v1.2.3 From 4b91daff13be43ed913a97ffc8ad1b3f77fd9690 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Wed, 2 Jun 2010 14:42:25 +0100 Subject: Special treatement for Relation#select { with block } --- activerecord/lib/active_record/relation/query_methods.rb | 15 ++++++++++++++- activerecord/test/cases/relations_test.rb | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 6782554854..7a48a6596a 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -9,7 +9,7 @@ module ActiveRecord (ActiveRecord::Relation::ASSOCIATION_METHODS + ActiveRecord::Relation::MULTI_VALUE_METHODS).each do |query_method| attr_accessor :"#{query_method}_values" - next if [:where, :having].include?(query_method) + next if [:where, :having, :select].include?(query_method) class_eval <<-CEVAL, __FILE__, __LINE__ + 1 def #{query_method}(*args, &block) new_relation = clone @@ -21,6 +21,19 @@ module ActiveRecord CEVAL end + class_eval <<-CEVAL, __FILE__, __LINE__ + 1 + def select(*args, &block) + if block_given? + to_a.select(&block) + else + new_relation = clone + value = Array.wrap(args.flatten).reject {|x| x.blank? } + new_relation.select_values += value if value.present? + new_relation + end + end + CEVAL + [:where, :having].each do |query_method| class_eval <<-CEVAL, __FILE__, __LINE__ + 1 def #{query_method}(*args, &block) diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index b6815af67e..4097c5119e 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -112,6 +112,11 @@ class RelationTest < ActiveRecord::TestCase assert_equal 4, developers.map(&:salary).uniq.size end + def test_select_with_block + even_ids = Developer.scoped.select {|d| d.id % 2 == 0 }.map(&:id) + assert_equal [2, 4, 6, 8, 10], even_ids + end + def test_finding_with_hash_conditions_on_joined_table firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a assert_equal 1, firms.size -- cgit v1.2.3 From ffe001f19dbbd9e697f6300650779f5e1391ce1e Mon Sep 17 00:00:00 2001 From: wycats Date: Wed, 2 Jun 2010 22:56:41 +0200 Subject: Changes made while working on upgrading cells to Rails 3 --- actionpack/lib/abstract_controller/base.rb | 1 + actionpack/lib/abstract_controller/rendering.rb | 1 + actionpack/lib/action_controller/metal/rack_delegation.rb | 8 ++++---- .../lib/action_controller/metal/request_forgery_protection.rb | 1 + actionpack/lib/action_view/paths.rb | 1 + 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 8500cbd7f2..ff97a7e76a 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -1,4 +1,5 @@ require 'active_support/configurable' +require 'active_support/core_ext/module/anonymous' module AbstractController class Error < StandardError; end diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index d2db366140..6e3998aa21 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -1,4 +1,5 @@ require "abstract_controller/base" +require "action_view" module AbstractController class DoubleRenderError < Error diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index 060117756e..508ea6e2b7 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -8,10 +8,10 @@ module ActionController delegate :headers, :status=, :location=, :content_type=, :status, :location, :content_type, :to => "@_response" - def dispatch(action, request) - @_response = ActionDispatch::Response.new - @_response.request = request - super + def dispatch(action, request, response = ActionDispatch::Response.new) + @_response ||= response + @_response.request ||= request + super(action, request) end def params diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 2ba0d6e5cd..8c25b147ef 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -47,6 +47,7 @@ module ActionController #:nodoc: extend ActiveSupport::Concern include AbstractController::Helpers + include AbstractController::Callbacks included do # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 35927d09d1..7f5e5d11b8 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -31,6 +31,7 @@ module ActionView #:nodoc: def typecast! each_with_index do |path, i| + path = path.to_s if path.is_a?(Pathname) next unless path.is_a?(String) self[i] = FileSystemResolver.new(path) end -- cgit v1.2.3 From 02512914ae547eb664a78c0f6084b121d5283a61 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 2 Jun 2010 16:17:05 -0500 Subject: You need the ruby-debug available in your Gemfile for debugger to work --- activesupport/lib/active_support/core_ext/kernel/debugger.rb | 2 +- railties/lib/rails/generators/rails/app/templates/Gemfile | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/core_ext/kernel/debugger.rb b/activesupport/lib/active_support/core_ext/kernel/debugger.rb index 22fcc1910b..692340c7c7 100644 --- a/activesupport/lib/active_support/core_ext/kernel/debugger.rb +++ b/activesupport/lib/active_support/core_ext/kernel/debugger.rb @@ -2,7 +2,7 @@ module Kernel unless respond_to?(:debugger) # Starts a debugging session if ruby-debug has been loaded (call rails server --debugger to do load it). def debugger - message = "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n" + message = "\n***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****\n" defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message) end end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index f751c4519d..0b922a89c0 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -23,6 +23,9 @@ gem '<%= gem_for_database %>'<% if require_for_database %>, :require => '<%= req # Deploy with Capistrano # gem 'capistrano' +# To use debugger +# gem 'ruby-debug' + # Bundle the extra gems: # gem 'bj' # gem 'nokogiri', '1.4.1' -- cgit v1.2.3 From 631dc618853325e5780237388224cb785a3a1b82 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 2 Jun 2010 16:49:02 -0500 Subject: Extract assets paths and make them available to Action Mailer as well --- actionmailer/lib/action_mailer/base.rb | 1 + actionmailer/lib/action_mailer/railtie.rb | 9 +++++++++ actionpack/lib/abstract_controller.rb | 1 + actionpack/lib/action_controller/base.rb | 3 ++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 3c41691af7..3a82979d35 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -311,6 +311,7 @@ module ActionMailer #:nodoc: include AbstractController::Layouts include AbstractController::Helpers include AbstractController::Translation + include AbstractController::AssetPaths helper ActionMailer::MailHelper diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 0730167a3e..43a4936013 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -13,7 +13,16 @@ module ActionMailer end initializer "action_mailer.set_configs" do |app| + paths = app.config.paths + am = app.config.action_mailer + + am.assets_dir ||= paths.public.to_a.first + am.javascripts_dir ||= paths.public.javascripts.to_a.first + am.stylesheets_dir ||= paths.public.stylesheets.to_a.first + ActiveSupport.on_load(:action_mailer) do + self.config.merge!(am) + include app.routes.url_helpers app.config.action_mailer.each do |k,v| diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 2da4dc052c..5990a1bbd0 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -20,5 +20,6 @@ module AbstractController autoload :Logger autoload :Rendering autoload :Translation + autoload :AssetPaths autoload :ViewPaths end diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 4297d9bbf6..73e07d59e3 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -13,6 +13,7 @@ module ActionController MODULES = [ AbstractController::Layouts, AbstractController::Translation, + AbstractController::AssetPaths, Helpers, HideActions, @@ -67,7 +68,7 @@ module ActionController end # TODO Move this to the appropriate module - config_accessor :assets_dir, :asset_path, :javascripts_dir, :stylesheets_dir + config_accessor :asset_path ActiveSupport.run_load_hooks(:action_controller, self) end -- cgit v1.2.3 From 71375c8936696d8d7404e02ff84e3dbde3d57029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 2 Jun 2010 14:53:56 -0700 Subject: Add an asset_host accessor for consistency. --- actionpack/lib/action_controller/base.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 73e07d59e3..8611d0d3c3 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -67,8 +67,7 @@ module ActionController @subclasses ||= [] end - # TODO Move this to the appropriate module - config_accessor :asset_path + config_accessor :asset_host, :asset_path ActiveSupport.run_load_hooks(:action_controller, self) end -- cgit v1.2.3 From 4aac5fd7118065444cb860f1d76a0a76d3914364 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 2 Jun 2010 16:55:07 -0500 Subject: Missed the extraction --- actionpack/lib/abstract_controller/asset_paths.rb | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 actionpack/lib/abstract_controller/asset_paths.rb diff --git a/actionpack/lib/abstract_controller/asset_paths.rb b/actionpack/lib/abstract_controller/asset_paths.rb new file mode 100644 index 0000000000..6d6f6ac607 --- /dev/null +++ b/actionpack/lib/abstract_controller/asset_paths.rb @@ -0,0 +1,9 @@ +module AbstractController + module AssetPaths + extend ActiveSupport::Concern + + included do + config_accessor :assets_dir, :javascripts_dir, :stylesheets_dir + end + end +end \ No newline at end of file -- cgit v1.2.3