mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Merge commit 'rails/master'
Conflicts: activerecord/lib/active_record/migration.rb
This commit is contained in:
@@ -872,8 +872,8 @@ module ActionView
|
||||
|
||||
private
|
||||
def add_default_name_and_id_for_value(tag_value, options)
|
||||
if tag_value
|
||||
pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/\W/, "").downcase
|
||||
unless tag_value.nil?
|
||||
pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/\W/, "").downcase
|
||||
specified_id = options["id"]
|
||||
add_default_name_and_id(options)
|
||||
options["id"] += "_#{pretty_tag_value}" unless specified_id
|
||||
|
||||
@@ -79,6 +79,13 @@ module ActionView
|
||||
# # <option>Paris</option><option>Rome</option></select>
|
||||
def select_tag(name, option_tags = nil, options = {})
|
||||
html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
|
||||
if blank = options.delete(:include_blank)
|
||||
if blank.kind_of?(String)
|
||||
option_tags = "<option value=\"\">#{blank}</option>" + option_tags
|
||||
else
|
||||
option_tags = "<option value=\"\"></option>" + option_tags
|
||||
end
|
||||
end
|
||||
content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
|
||||
end
|
||||
|
||||
|
||||
@@ -134,16 +134,14 @@ module ActionView
|
||||
def tag_options(options, escape = true)
|
||||
unless options.blank?
|
||||
attrs = []
|
||||
if escape
|
||||
options.each_pair do |key, value|
|
||||
if BOOLEAN_ATTRIBUTES.include?(key)
|
||||
attrs << %(#{key}="#{key}") if value
|
||||
else
|
||||
attrs << %(#{key}="#{escape_once(value)}") if !value.nil?
|
||||
end
|
||||
options.each_pair do |key, value|
|
||||
if BOOLEAN_ATTRIBUTES.include?(key)
|
||||
attrs << %(#{key}="#{key}") if value
|
||||
elsif !value.nil?
|
||||
final_value = value.is_a?(Array) ? value.join(" ") : value
|
||||
final_value = escape_once(final_value) if escape
|
||||
attrs << %(#{key}="#{final_value}")
|
||||
end
|
||||
else
|
||||
attrs = options.map { |key, value| %(#{key}="#{value}") }
|
||||
end
|
||||
" #{attrs.sort * ' '}" unless attrs.empty?
|
||||
end
|
||||
|
||||
@@ -34,6 +34,10 @@ class RedirectController < ActionController::Base
|
||||
redirect_to({:action => "hello_world"}, {:status => 301})
|
||||
end
|
||||
|
||||
def redirect_with_protocol
|
||||
redirect_to :action => "hello_world", :protocol => "https"
|
||||
end
|
||||
|
||||
def url_redirect_with_status
|
||||
redirect_to("http://www.example.com", :status => :moved_permanently)
|
||||
end
|
||||
@@ -132,6 +136,12 @@ class RedirectTest < ActionController::TestCase
|
||||
assert_equal "http://test.host/redirect/hello_world", redirect_to_url
|
||||
end
|
||||
|
||||
def test_redirect_with_protocol
|
||||
get :redirect_with_protocol
|
||||
assert_response 302
|
||||
assert_equal "https://test.host/redirect/hello_world", redirect_to_url
|
||||
end
|
||||
|
||||
def test_url_redirect_with_status
|
||||
get :url_redirect_with_status
|
||||
assert_response 301
|
||||
|
||||
@@ -307,6 +307,16 @@ class FormHelperTest < ActionView::TestCase
|
||||
)
|
||||
end
|
||||
|
||||
def test_radio_button_with_booleans
|
||||
assert_dom_equal('<input id="post_secret_true" name="post[secret]" type="radio" value="true" />',
|
||||
radio_button("post", "secret", true)
|
||||
)
|
||||
|
||||
assert_dom_equal('<input id="post_secret_false" name="post[secret]" type="radio" value="false" />',
|
||||
radio_button("post", "secret", false)
|
||||
)
|
||||
end
|
||||
|
||||
def test_text_area
|
||||
assert_dom_equal(
|
||||
'<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea>',
|
||||
|
||||
@@ -136,6 +136,18 @@ class FormTagHelperTest < ActionView::TestCase
|
||||
assert_match VALID_HTML_ID, input_elem['id']
|
||||
end
|
||||
|
||||
def test_select_tag_with_include_blank
|
||||
actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>", :include_blank => true
|
||||
expected = %(<select id="places" name="places"><option value=""></option><option>Home</option><option>Work</option><option>Pub</option></select>)
|
||||
assert_dom_equal expected, actual
|
||||
end
|
||||
|
||||
def test_select_tag_with_include_blank_with_string
|
||||
actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>", :include_blank => "string"
|
||||
expected = %(<select id="places" name="places"><option value="">string</option><option>Home</option><option>Work</option><option>Pub</option></select>)
|
||||
assert_dom_equal expected, actual
|
||||
end
|
||||
|
||||
def test_text_area_tag_size_string
|
||||
actual = text_area_tag "body", "hello world", "size" => "20x40"
|
||||
expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>)
|
||||
|
||||
@@ -71,6 +71,19 @@ class TagHelperTest < ActionView::TestCase
|
||||
assert_equal '<p><b>Hello</b></p>', output_buffer
|
||||
end
|
||||
|
||||
def test_content_tag_with_escaped_array_class
|
||||
str = content_tag('p', "limelight", :class => ["song", "play>"])
|
||||
assert_equal "<p class=\"song play>\">limelight</p>", str
|
||||
|
||||
str = content_tag('p', "limelight", :class => ["song", "play"])
|
||||
assert_equal "<p class=\"song play\">limelight</p>", str
|
||||
end
|
||||
|
||||
def test_content_tag_with_unescaped_array_class
|
||||
str = content_tag('p', "limelight", {:class => ["song", "play>"]}, false)
|
||||
assert_equal "<p class=\"song play>\">limelight</p>", str
|
||||
end
|
||||
|
||||
def test_cdata_section
|
||||
assert_equal "<![CDATA[<hello world>]]>", cdata_section("<hello world>")
|
||||
end
|
||||
|
||||
@@ -80,9 +80,14 @@ module ActiveModel
|
||||
|
||||
validates_each(attrs, options) do |record, attr, value|
|
||||
value = options[:tokenizer].call(value) if value.kind_of?(String)
|
||||
unless !value.nil? and value.size.method(validity_checks[option])[option_value]
|
||||
record.errors.add(attr, key, :default => custom_message, :count => option_value)
|
||||
|
||||
valid_value = if option == :maximum
|
||||
value.nil? || value.size.send(validity_checks[option], option_value)
|
||||
else
|
||||
value && value.size.send(validity_checks[option], option_value)
|
||||
end
|
||||
|
||||
record.errors.add(attr, key, :default => custom_message, :count => option_value) unless valid_value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,6 +52,12 @@ class LengthValidationTest < ActiveModel::TestCase
|
||||
assert_equal ["is too short (minimum is 5 characters)"], t.errors["title"]
|
||||
end
|
||||
|
||||
def test_validates_length_of_using_maximum_should_allow_nil
|
||||
Topic.validates_length_of :title, :maximum => 10
|
||||
t = Topic.create
|
||||
assert t.valid?
|
||||
end
|
||||
|
||||
def test_optionally_validates_length_of_using_minimum
|
||||
Topic.validates_length_of :title, :minimum => 5, :allow_nil => true
|
||||
|
||||
@@ -75,9 +81,6 @@ class LengthValidationTest < ActiveModel::TestCase
|
||||
|
||||
t.title = ""
|
||||
assert t.valid?
|
||||
|
||||
t.title = nil
|
||||
assert !t.valid?
|
||||
end
|
||||
|
||||
def test_optionally_validates_length_of_using_maximum
|
||||
|
||||
@@ -8,6 +8,8 @@ module ActiveRecord
|
||||
alias_method :new, :build
|
||||
|
||||
def create!(attrs = nil)
|
||||
ensure_owner_is_not_new
|
||||
|
||||
transaction do
|
||||
self << (object = attrs ? @reflection.klass.send(:with_scope, :create => attrs) { @reflection.create_association! } : @reflection.create_association!)
|
||||
object
|
||||
@@ -15,6 +17,8 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def create(attrs = nil)
|
||||
ensure_owner_is_not_new
|
||||
|
||||
transaction do
|
||||
self << (object = attrs ? @reflection.klass.send(:with_scope, :create => attrs) { @reflection.create_association } : @reflection.create_association)
|
||||
object
|
||||
|
||||
@@ -384,23 +384,11 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def rollback(migrations_path, steps=1)
|
||||
migrator = self.new(:down, migrations_path)
|
||||
start_index = migrator.migrations.index(migrator.current_migration)
|
||||
|
||||
return unless start_index
|
||||
|
||||
finish = migrator.migrations[start_index + steps]
|
||||
down(migrations_path, finish ? finish.version : 0)
|
||||
move(:down, migrations_path, steps)
|
||||
end
|
||||
|
||||
def forward(migrations_path, steps=1)
|
||||
migrator = self.new(:up, migrations_path)
|
||||
start_index = migrator.migrations.index(migrator.current_migration)
|
||||
|
||||
return unless start_index
|
||||
|
||||
finish = migrator.migrations[start_index + steps]
|
||||
up(migrations_path, finish ? finish.version : 0)
|
||||
move(:up, migrations_path, steps)
|
||||
end
|
||||
|
||||
def up(migrations_path, target_version = nil)
|
||||
@@ -437,6 +425,19 @@ module ActiveRecord
|
||||
# Use the Active Record objects own table_name, or pre/suffix from ActiveRecord::Base if name is a symbol/string
|
||||
name.table_name rescue "#{ActiveRecord::Base.table_name_prefix}#{name}#{ActiveRecord::Base.table_name_suffix}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def move(direction, migrations_path, steps)
|
||||
migrator = self.new(direction, migrations_path)
|
||||
start_index = migrator.migrations.index(migrator.current_migration)
|
||||
|
||||
if start_index
|
||||
finish = migrator.migrations[start_index + steps]
|
||||
version = finish ? finish.version : 0
|
||||
send(direction, migrations_path, version)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(direction, migrations_path, target_version = nil)
|
||||
|
||||
@@ -169,6 +169,13 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
||||
assert_equal peeps + 1, posts(:thinking).people.count
|
||||
end
|
||||
|
||||
def test_create_on_new_record
|
||||
p = Post.new
|
||||
|
||||
assert_raises(ActiveRecord::RecordNotSaved) { p.people.create(:first_name => "mew") }
|
||||
assert_raises(ActiveRecord::RecordNotSaved) { p.people.create!(:first_name => "snow") }
|
||||
end
|
||||
|
||||
def test_clear_associations
|
||||
assert_queries(2) { posts(:welcome);posts(:welcome).people(true) }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user