aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2008-11-17 10:17:42 -0800
committerJeremy Kemper <jeremy@bitsweat.net>2008-11-17 10:17:42 -0800
commit6ff506ffbc438a92cb6d3cb4351a0a463d57424a (patch)
treeb00760f78a94ea0f226cf825f26ef6db8890fdc5
parent29a31912fcedde9e271af8a20b890f8c62e1ea79 (diff)
parent4b33fae1f52325d22083de2e83d827b924d1c616 (diff)
downloadrails-6ff506ffbc438a92cb6d3cb4351a0a463d57424a.tar.gz
rails-6ff506ffbc438a92cb6d3cb4351a0a463d57424a.tar.bz2
rails-6ff506ffbc438a92cb6d3cb4351a0a463d57424a.zip
Merge branch 'master' of git@github.com:rails/rails
-rw-r--r--actionpack/CHANGELOG5
-rw-r--r--actionpack/lib/action_controller/mime_type.rb4
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb150
-rw-r--r--activerecord/CHANGELOG16
-rwxr-xr-xactiverecord/lib/active_record/base.rb16
-rw-r--r--activerecord/lib/active_record/fixtures.rb2
-rw-r--r--activerecord/test/cases/method_scoping_test.rb61
-rw-r--r--activerecord/test/models/developer.rb12
-rw-r--r--activesupport/lib/active_support/inflector.rb2
9 files changed, 181 insertions, 87 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index b7a824d559..4ed39133db 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,3 +1,8 @@
+*2.3.0/3.0*
+
+* Fixed RedCloth and BlueCloth shouldn't preload. Instead just assume that they're available if you want to use textilize and markdown and let autoload require them [DHH]
+
+
*2.2.1 [RC2] (November 14th, 2008)*
* Restore backwards compatible functionality for setting relative_url_root. Include deprecation
diff --git a/actionpack/lib/action_controller/mime_type.rb b/actionpack/lib/action_controller/mime_type.rb
index 8ca3a70341..6923a13f3f 100644
--- a/actionpack/lib/action_controller/mime_type.rb
+++ b/actionpack/lib/action_controller/mime_type.rb
@@ -25,7 +25,7 @@ module Mime
# These are the content types which browsers can generate without using ajax, flash, etc
# i.e. following a link, getting an image or posting a form. CSRF protection
# only needs to protect against these types.
- @@browser_generated_types = Set.new [:html, :url_encoded_form, :multipart_form]
+ @@browser_generated_types = Set.new [:html, :url_encoded_form, :multipart_form, :text]
cattr_reader :browser_generated_types
@@ -177,7 +177,7 @@ module Mime
end
# Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See
- # ActionController::RequestForgerProtection.
+ # ActionController::RequestForgeryProtection.
def verify_request?
browser_generated?
end
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 9bd3d63423..510c1a6a76 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -226,91 +226,79 @@ module ActionView
end * "\n"
end
- begin
- require_library_or_gem "redcloth" unless Object.const_defined?(:RedCloth)
-
- # Returns the text with all the Textile[http://www.textism.com/tools/textile] codes turned into HTML tags.
- #
- # You can learn more about Textile's syntax at its website[http://www.textism.com/tools/textile].
- # <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
- # is available</i>.
- #
- # ==== Examples
- # textilize("*This is Textile!* Rejoice!")
- # # => "<p><strong>This is Textile!</strong> Rejoice!</p>"
- #
- # textilize("I _love_ ROR(Ruby on Rails)!")
- # # => "<p>I <em>love</em> <acronym title="Ruby on Rails">ROR</acronym>!</p>"
- #
- # textilize("h2. Textile makes markup -easy- simple!")
- # # => "<h2>Textile makes markup <del>easy</del> simple!</h2>"
- #
- # textilize("Visit the Rails website "here":http://www.rubyonrails.org/.)
- # # => "<p>Visit the Rails website <a href="http://www.rubyonrails.org/">here</a>.</p>"
- def textilize(text)
- if text.blank?
- ""
- else
- textilized = RedCloth.new(text, [ :hard_breaks ])
- textilized.hard_breaks = true if textilized.respond_to?(:hard_breaks=)
- textilized.to_html
- end
+ # Returns the text with all the Textile[http://www.textism.com/tools/textile] codes turned into HTML tags.
+ #
+ # You can learn more about Textile's syntax at its website[http://www.textism.com/tools/textile].
+ # <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
+ # is available</i>.
+ #
+ # ==== Examples
+ # textilize("*This is Textile!* Rejoice!")
+ # # => "<p><strong>This is Textile!</strong> Rejoice!</p>"
+ #
+ # textilize("I _love_ ROR(Ruby on Rails)!")
+ # # => "<p>I <em>love</em> <acronym title="Ruby on Rails">ROR</acronym>!</p>"
+ #
+ # textilize("h2. Textile makes markup -easy- simple!")
+ # # => "<h2>Textile makes markup <del>easy</del> simple!</h2>"
+ #
+ # textilize("Visit the Rails website "here":http://www.rubyonrails.org/.)
+ # # => "<p>Visit the Rails website <a href="http://www.rubyonrails.org/">here</a>.</p>"
+ def textilize(text)
+ if text.blank?
+ ""
+ else
+ textilized = RedCloth.new(text, [ :hard_breaks ])
+ textilized.hard_breaks = true if textilized.respond_to?(:hard_breaks=)
+ textilized.to_html
end
+ end
- # Returns the text with all the Textile codes turned into HTML tags,
- # but without the bounding <p> tag that RedCloth adds.
- #
- # You can learn more about Textile's syntax at its website[http://www.textism.com/tools/textile].
- # <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
- # is available</i>.
- #
- # ==== Examples
- # textilize_without_paragraph("*This is Textile!* Rejoice!")
- # # => "<strong>This is Textile!</strong> Rejoice!"
- #
- # textilize_without_paragraph("I _love_ ROR(Ruby on Rails)!")
- # # => "I <em>love</em> <acronym title="Ruby on Rails">ROR</acronym>!"
- #
- # textilize_without_paragraph("h2. Textile makes markup -easy- simple!")
- # # => "<h2>Textile makes markup <del>easy</del> simple!</h2>"
- #
- # textilize_without_paragraph("Visit the Rails website "here":http://www.rubyonrails.org/.)
- # # => "Visit the Rails website <a href="http://www.rubyonrails.org/">here</a>."
- def textilize_without_paragraph(text)
- textiled = textilize(text)
- if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end
- if textiled[-4..-1] == "</p>" then textiled = textiled[0..-5] end
- return textiled
- end
- rescue LoadError
- # We can't really help what's not there
+ # Returns the text with all the Textile codes turned into HTML tags,
+ # but without the bounding <p> tag that RedCloth adds.
+ #
+ # You can learn more about Textile's syntax at its website[http://www.textism.com/tools/textile].
+ # <i>This method is requires RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
+ # to be available</i>.
+ #
+ # ==== Examples
+ # textilize_without_paragraph("*This is Textile!* Rejoice!")
+ # # => "<strong>This is Textile!</strong> Rejoice!"
+ #
+ # textilize_without_paragraph("I _love_ ROR(Ruby on Rails)!")
+ # # => "I <em>love</em> <acronym title="Ruby on Rails">ROR</acronym>!"
+ #
+ # textilize_without_paragraph("h2. Textile makes markup -easy- simple!")
+ # # => "<h2>Textile makes markup <del>easy</del> simple!</h2>"
+ #
+ # textilize_without_paragraph("Visit the Rails website "here":http://www.rubyonrails.org/.)
+ # # => "Visit the Rails website <a href="http://www.rubyonrails.org/">here</a>."
+ def textilize_without_paragraph(text)
+ textiled = textilize(text)
+ if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end
+ if textiled[-4..-1] == "</p>" then textiled = textiled[0..-5] end
+ return textiled
end
- begin
- require_library_or_gem "bluecloth" unless Object.const_defined?(:BlueCloth)
-
- # Returns the text with all the Markdown codes turned into HTML tags.
- # <i>This method is only available if BlueCloth[http://www.deveiate.org/projects/BlueCloth]
- # is available</i>.
- #
- # ==== Examples
- # markdown("We are using __Markdown__ now!")
- # # => "<p>We are using <strong>Markdown</strong> now!</p>"
- #
- # markdown("We like to _write_ `code`, not just _read_ it!")
- # # => "<p>We like to <em>write</em> <code>code</code>, not just <em>read</em> it!</p>"
- #
- # markdown("The [Markdown website](http://daringfireball.net/projects/markdown/) has more information.")
- # # => "<p>The <a href="http://daringfireball.net/projects/markdown/">Markdown website</a>
- # # has more information.</p>"
- #
- # markdown('![The ROR logo](http://rubyonrails.com/images/rails.png "Ruby on Rails")')
- # # => '<p><img src="http://rubyonrails.com/images/rails.png" alt="The ROR logo" title="Ruby on Rails" /></p>'
- def markdown(text)
- text.blank? ? "" : BlueCloth.new(text).to_html
- end
- rescue LoadError
- # We can't really help what's not there
+ # Returns the text with all the Markdown codes turned into HTML tags.
+ # <i>This method requires BlueCloth[http://www.deveiate.org/projects/BlueCloth]
+ # to be available</i>.
+ #
+ # ==== Examples
+ # markdown("We are using __Markdown__ now!")
+ # # => "<p>We are using <strong>Markdown</strong> now!</p>"
+ #
+ # markdown("We like to _write_ `code`, not just _read_ it!")
+ # # => "<p>We like to <em>write</em> <code>code</code>, not just <em>read</em> it!</p>"
+ #
+ # markdown("The [Markdown website](http://daringfireball.net/projects/markdown/) has more information.")
+ # # => "<p>The <a href="http://daringfireball.net/projects/markdown/">Markdown website</a>
+ # # has more information.</p>"
+ #
+ # markdown('![The ROR logo](http://rubyonrails.com/images/rails.png "Ruby on Rails")')
+ # # => '<p><img src="http://rubyonrails.com/images/rails.png" alt="The ROR logo" title="Ruby on Rails" /></p>'
+ def markdown(text)
+ text.blank? ? "" : BlueCloth.new(text).to_html
end
# Returns +text+ transformed into HTML using simple formatting rules.
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index c2299b56ad..c1d7297260 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,3 +1,19 @@
+*2.3.0/3.0*
+
+* Added default_scope to Base #1381 [Paweł Kondzior]. Example:
+
+ class Person < ActiveRecord::Base
+ default_scope :order => 'last_name, first_name'
+ end
+
+ class Company < ActiveRecord::Base
+ has_many :people
+ end
+
+ Person.all # => Person.find(:all, :order => 'last_name, first_name')
+ Company.find(1).people # => Person.find(:all, :order => 'last_name, first_name', :conditions => { :company_id => 1 })
+
+
*2.2.1 [RC2] (November 14th, 2008)*
* Ensure indices don't flip order in schema.rb #1266 [Jordi Bunster]
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index dcc8277849..68f44ef0f6 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -495,6 +495,10 @@ module ActiveRecord #:nodoc:
superclass_delegating_accessor :store_full_sti_class
self.store_full_sti_class = false
+ # Stores the default scope for the class
+ class_inheritable_accessor :default_scoping, :instance_writer => false
+ self.default_scoping = []
+
class << self # Class methods
# Find operates with four different retrieval approaches:
#
@@ -2016,6 +2020,16 @@ module ActiveRecord #:nodoc:
@@subclasses[self] + extra = @@subclasses[self].inject([]) {|list, subclass| list + subclass.subclasses }
end
+ # Sets the default options for the model. The format of the
+ # <tt>method_scoping</tt> argument is the same as in with_scope.
+ #
+ # class Person < ActiveRecord::Base
+ # default_scope :find => { :order => 'last_name, first_name' }
+ # end
+ def default_scope(options = {})
+ self.default_scoping << { :find => options, :create => options.is_a?(Hash) ? options[:conditions] : {} }
+ end
+
# Test whether the given method and optional key are scoped.
def scoped?(method, key = nil) #:nodoc:
if current_scoped_methods && (scope = current_scoped_methods[method])
@@ -2031,7 +2045,7 @@ module ActiveRecord #:nodoc:
end
def scoped_methods #:nodoc:
- Thread.current[:"#{self}_scoped_methods"] ||= []
+ Thread.current[:"#{self}_scoped_methods"] ||= self.default_scoping.dup
end
def current_scoped_methods #:nodoc:
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index a09f58fc23..9a82ff2ed4 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -925,6 +925,7 @@ module ActiveRecord
end
@fixture_cache = {}
+ @@already_loaded_fixtures ||= {}
# Load fixtures once and begin transaction.
if use_transactional_fixtures?
@@ -939,7 +940,6 @@ module ActiveRecord
# Load fixtures for every test.
else
Fixtures.reset_cache
- @@already_loaded_fixtures ||= {}
@@already_loaded_fixtures[self.class] = nil
load_fixtures
end
diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb
index ff10bfaf3e..4ac0018144 100644
--- a/activerecord/test/cases/method_scoping_test.rb
+++ b/activerecord/test/cases/method_scoping_test.rb
@@ -522,6 +522,67 @@ class HasAndBelongsToManyScopingTest< ActiveRecord::TestCase
end
+class DefaultScopingTest < ActiveRecord::TestCase
+ fixtures :developers
+
+ def test_default_scope
+ expected = Developer.find(:all, :order => 'salary DESC').collect { |dev| dev.salary }
+ received = DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary }
+ assert_equal expected, received
+ end
+
+ def test_default_scoping_with_threads
+ scope = [{:create=>nil, :find=>{:order=>"salary DESC"}}]
+
+ 2.times do
+ Thread.new { assert_equal scope, DeveloperOrderedBySalary.send(:scoped_methods) }.join
+ end
+ end
+
+ def test_default_scoping_with_inheritance
+ scope = [{:create=>nil, :find=>{:order=>"salary DESC"}}]
+
+ # Inherit a class having a default scope and define a new default scope
+ klass = Class.new(DeveloperOrderedBySalary)
+ klass.send :default_scope, {}
+
+ # Scopes added on children should append to parent scope
+ expected_klass_scope = [{:create=>nil, :find=>{:order=>"salary DESC"}}, {:create=>nil, :find=>{}}]
+ assert_equal expected_klass_scope, klass.send(:scoped_methods)
+
+ # Parent should still have the original scope
+ assert_equal scope, DeveloperOrderedBySalary.send(:scoped_methods)
+ end
+
+ def test_method_scope
+ expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary }
+ received = DeveloperOrderedBySalary.all_ordered_by_name.collect { |dev| dev.salary }
+ assert_equal expected, received
+ end
+
+ def test_nested_scope
+ expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary }
+ received = DeveloperOrderedBySalary.with_scope(:find => { :order => 'name DESC'}) do
+ DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary }
+ end
+ assert_equal expected, received
+ end
+
+ def test_nested_exclusive_scope
+ expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary }
+ received = DeveloperOrderedBySalary.with_exclusive_scope(:find => { :limit => 100 }) do
+ DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary }
+ end
+ assert_equal expected, received
+ end
+
+ def test_overwriting_default_scope
+ expected = Developer.find(:all, :order => 'salary').collect { |dev| dev.salary }
+ received = DeveloperOrderedBySalary.find(:all, :order => 'salary').collect { |dev| dev.salary }
+ assert_equal expected, received
+ end
+end
+
=begin
# We disabled the scoping for has_one and belongs_to as we can't think of a proper use case
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index c08476f728..0c20f97502 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -77,3 +77,15 @@ class DeveloperWithBeforeDestroyRaise < ActiveRecord::Base
raise if projects.empty?
end
end
+
+class DeveloperOrderedBySalary < ActiveRecord::Base
+ self.table_name = 'developers'
+ default_scope :order => "salary DESC"
+
+ def self.all_ordered_by_name
+ with_scope(:find => { :order => "name DESC" }) do
+ find(:all)
+ end
+ end
+
+end
diff --git a/activesupport/lib/active_support/inflector.rb b/activesupport/lib/active_support/inflector.rb
index ba52e41c08..ad2660e6c8 100644
--- a/activesupport/lib/active_support/inflector.rb
+++ b/activesupport/lib/active_support/inflector.rb
@@ -134,7 +134,6 @@ module ActiveSupport
# "octopus".pluralize # => "octopi"
# "sheep".pluralize # => "sheep"
# "words".pluralize # => "words"
- # "the blue mailman".pluralize # => "the blue mailmen"
# "CamelOctopus".pluralize # => "CamelOctopi"
def pluralize(word)
result = word.to_s.dup
@@ -154,7 +153,6 @@ module ActiveSupport
# "octopi".singularize # => "octopus"
# "sheep".singluarize # => "sheep"
# "word".singularize # => "word"
- # "the blue mailmen".singularize # => "the blue mailman"
# "CamelOctopi".singularize # => "CamelOctopus"
def singularize(word)
result = word.to_s.dup