Merge branch 'master' of git@github.com:rails/rails

This commit is contained in:
David Heinemeier Hansson 2008-05-01 14:32:50 -05:00
commit e2af713d1c
18 changed files with 228 additions and 88 deletions

@ -1,6 +1,7 @@
require 'cgi'
require 'action_view/helpers/date_helper'
require 'action_view/helpers/tag_helper'
require 'action_view/helpers/form_tag_helper'
module ActionView
module Helpers
@ -51,7 +52,7 @@ module Helpers
#
# If the object name contains square brackets the id for the object will be inserted. For example:
#
# <%= text_field "person[]", "name" %>
# <%= text_field "person[]", "name" %>
#
# ...will generate the following ERb.
#
@ -91,7 +92,7 @@ module FormHelper
#
# Even further, the form_for method allows you to more easily escape the instance variable convention. So while the stand-alone
# approach would require <tt>text_field :person, :name, :object => person</tt>
# to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with
# to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with
# <tt>:person, person</tt> and all subsequent field calls save <tt>:person</tt> and <tt>:object => person</tt>.
#
# Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods
@ -149,7 +150,7 @@ module FormHelper
# ...
# <% end %>
#
# And for namespaced routes, like admin_post_url:
# And for namespaced routes, like admin_post_url:
#
# <% form_for([:admin, @post]) do |f| %>
# ...
@ -337,7 +338,7 @@ def password_field(object_name, method, options = {})
# hash with +options+. These options will be tagged onto the HTML as an HTML element attribute as in the example
# shown.
#
# ==== Examples
# ==== Examples
# hidden_field(:signup, :pass_confirm)
# # => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{@signup.pass_confirm}" />
#
@ -404,7 +405,7 @@ def text_area(object_name, method, options = {})
# is set to 0 which is convenient for boolean values. Since HTTP standards say that unchecked checkboxes don't post anything,
# we add a hidden value with the same name as the checkbox as a work around.
#
# ==== Examples
# ==== Examples
# # Let's say that @post.validated? is 1:
# check_box("post", "validated")
# # => <input type="checkbox" id="post_validated" name="post[validated]" value="1" />
@ -445,7 +446,7 @@ def radio_button(object_name, method, tag_value, options = {})
end
class InstanceTag #:nodoc:
include Helpers::TagHelper
include Helpers::TagHelper, Helpers::FormTagHelper
attr_reader :method_name, :object_name
@ -467,11 +468,13 @@ def initialize(object_name, method_name, template_object, local_binding = nil, o
end
def to_label_tag(text = nil, options = {})
options = options.stringify_keys
name_and_id = options.dup
add_default_name_and_id(name_and_id)
options["for"] = name_and_id["id"]
options.delete("index")
options["for"] ||= name_and_id["id"]
content = (text.blank? ? nil : text.to_s) || method_name.humanize
content_tag("label", content, options)
label_tag(name_and_id["id"], content, options)
end
def to_input_field_tag(field_type, options = {})

@ -24,7 +24,12 @@ def process_view_paths(*view_paths)
view_paths.flatten.compact.each do |dir|
next if @@processed_view_paths.has_key?(dir)
@@processed_view_paths[dir] = []
Dir.glob("#{dir}/**/*/**").each do |file|
#
# Dir.glob("#{dir}/**/*/**") reads all the directories in view path and templates inside those directories
# Dir.glob("#{dir}/**") reads templates residing at top level of view path
#
(Dir.glob("#{dir}/**/*/**") | Dir.glob("#{dir}/**")).each do |file|
unless File.directory?(file)
@@processed_view_paths[dir] << file.split(dir).last.sub(/^\//, '')

@ -23,6 +23,14 @@ def render_hello_world
def render_hello_world_with_forward_slash
render :template => "/test/hello_world"
end
def render_template_in_top_directory
render :template => 'shared'
end
def render_template_in_top_directory_with_slash
render :template => '/shared'
end
def render_hello_world_from_variable
@person = "david"
@ -243,6 +251,18 @@ def test_render_with_forward_slash
get :render_hello_world_with_forward_slash
assert_template "test/hello_world"
end
def test_render_in_top_directory
get :render_template_in_top_directory
assert_template "shared"
assert_equal "Elastica", @response.body
end
def test_render_in_top_directory_with_slash
get :render_template_in_top_directory_with_slash
assert_template "shared"
assert_equal "Elastica", @response.body
end
def test_render_from_variable
get :render_hello_world_from_variable

@ -0,0 +1 @@
Elastica

@ -6,11 +6,11 @@
alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast)
alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
def new_record=(boolean)
@new_record = boolean
end
def new_record?
@new_record
end
@ -36,13 +36,13 @@ class FormHelperTest < ActionView::TestCase
def setup
@post = Post.new
@comment = Comment.new
def @post.errors()
Class.new{
def on(field); "can't be empty" if field == "author_name"; end
def empty?() false end
def @post.errors()
Class.new{
def on(field); "can't be empty" if field == "author_name"; end
def empty?() false end
def count() 1 end
def full_messages() [ "Author name can't be empty" ] end
}.new
def full_messages() [ "Author name can't be empty" ] end
}.new
end
def @post.id; 123; end
def @post.id_before_type_cast; 123; end
@ -72,11 +72,19 @@ def test_label
label("post", "title", nil, :class => 'title_label')
)
end
def test_label_with_symbols
assert_dom_equal('<label for="post_title">Title</label>', label(:post, :title))
end
def test_label_with_for_attribute_as_symbol
assert_dom_equal('<label for="my_for">Title</label>', label(:post, :title, nil, :for => "my_for"))
end
def test_label_with_for_attribute_as_string
assert_dom_equal('<label for="my_for">Title</label>', label(:post, :title, nil, "for" => "my_for"))
end
def test_text_field
assert_dom_equal(
'<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title")
@ -303,7 +311,7 @@ def test_form_for
_erbout.concat f.submit('Create post')
end
expected =
expected =
"<form action='http://www.example.com' id='create-post' method='post'>" +
"<label for='post_title'>Title</label>" +
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
@ -325,7 +333,7 @@ def test_form_for_with_method
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<form action='http://www.example.com' id='create-post' method='post'>" +
"<div style='margin:0;padding:0'><input name='_method' type='hidden' value='put' /></div>" +
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
@ -346,7 +354,7 @@ def test_form_for_without_object
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<form action='http://www.example.com' id='create-post' method='post'>" +
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
@ -367,7 +375,7 @@ def test_form_for_with_index
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<form action='http://www.example.com' method='post'>" +
"<label for=\"post_123_title\">Title</label>" +
"<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" +
@ -423,7 +431,7 @@ def test_fields_for
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
@ -494,7 +502,7 @@ def test_fields_for_without_object
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
@ -511,7 +519,7 @@ def test_fields_for_with_only_object
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
@ -532,6 +540,18 @@ def test_fields_for_object_with_bracketed_name
_erbout
end
def test_fields_for_object_with_bracketed_name_and_index
_erbout = ''
fields_for("author[post]", @post, :index => 1) do |f|
_erbout.concat f.label(:title)
_erbout.concat f.text_field(:title)
end
assert_dom_equal "<label for=\"author_post_1_title\">Title</label>" +
"<input name='author[post][1][title]' size='30' type='text' id='author_post_1_title' value='Hello World' />",
_erbout
end
def test_form_builder_does_not_have_form_for_method
assert ! ActionView::Helpers::FormBuilder.instance_methods.include?('form_for')
end
@ -548,7 +568,7 @@ def test_form_for_and_fields_for
end
end
expected =
expected =
"<form action='http://www.example.com' id='create-post' method='post'>" +
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
@ -571,7 +591,7 @@ def test_form_for_and_fields_for_with_object
end
end
expected =
expected =
"<form action='http://www.example.com' id='create-post' method='post'>" +
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
@ -601,7 +621,7 @@ def test_form_for_with_labelled_builder
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<form action='http://www.example.com' method='post'>" +
"<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" +
"<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" +
@ -623,7 +643,7 @@ def test_default_form_builder
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<form action='http://www.example.com' method='post'>" +
"<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" +
"<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" +
@ -637,39 +657,39 @@ def test_default_form_builder
end
def test_default_form_builder_with_active_record_helpers
_erbout = ''
_erbout = ''
form_for(:post, @post) do |f|
_erbout.concat f.error_message_on('author_name')
_erbout.concat f.error_messages
end
expected = %(<form action='http://www.example.com' method='post'>) +
%(<div class='formError'>can't be empty</div>) +
end
expected = %(<form action='http://www.example.com' method='post'>) +
%(<div class='formError'>can't be empty</div>) +
%(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>) +
%(</form>)
assert_dom_equal expected, _erbout
end
def test_default_form_builder_no_instance_variable
post = @post
@post = nil
_erbout = ''
_erbout = ''
form_for(:post, post) do |f|
_erbout.concat f.error_message_on('author_name')
_erbout.concat f.error_messages
end
expected = %(<form action='http://www.example.com' method='post'>) +
%(<div class='formError'>can't be empty</div>) +
end
expected = %(<form action='http://www.example.com' method='post'>) +
%(<div class='formError'>can't be empty</div>) +
%(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>) +
%(</form>)
assert_dom_equal expected, _erbout
end
# Perhaps this test should be moved to prototype helper tests.
@ -683,7 +703,7 @@ def test_remote_form_for_with_labelled_builder
_erbout.concat f.check_box(:secret)
end
expected =
expected =
%(<form action="http://www.example.com" onsubmit="new Ajax.Request('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" method="post">) +
"<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" +
"<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" +
@ -693,31 +713,31 @@ def test_remote_form_for_with_labelled_builder
assert_dom_equal expected, _erbout
end
def test_fields_for_with_labelled_builder
_erbout = ''
fields_for(:post, @post, :builder => LabelledFormBuilder) do |f|
_erbout.concat f.text_field(:title)
_erbout.concat f.text_area(:body)
_erbout.concat f.check_box(:secret)
end
expected =
expected =
"<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" +
"<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" +
"<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
"<input name='post[secret]' type='hidden' value='0' /><br/>"
assert_dom_equal expected, _erbout
end
def test_form_for_with_html_options_adds_options_to_form_tag
_erbout = ''
form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end
expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\"></form>"
assert_dom_equal expected, _erbout
end
@ -793,16 +813,16 @@ def test_form_for_with_existing_object_and_namespace_in_list
@comment.save
_erbout = ''
form_for([:admin, @post, @comment]) {}
expected = %(<form action="#{admin_comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div></form>)
assert_dom_equal expected, _erbout
end
def test_form_for_with_new_object_and_namespace_in_list
@post.new_record = false
_erbout = ''
form_for([:admin, @post, @comment]) {}
expected = %(<form action="#{admin_comments_path(@post)}" class="new_comment" id="new_comment" method="post"></form>)
assert_dom_equal expected, _erbout
end
@ -819,10 +839,10 @@ def test_form_for_with_existing_object_and_custom_url
def test_remote_form_for_with_html_options_adds_options_to_form_tag
self.extend ActionView::Helpers::PrototypeHelper
_erbout = ''
remote_form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end
expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\" onsubmit=\"new Ajax.Request('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\"></form>"
assert_dom_equal expected, _erbout
end
@ -837,21 +857,21 @@ def comment_path(post, comment)
"/posts/#{post.id}/comments/#{comment.id}"
end
alias_method :post_comment_path, :comment_path
def admin_comments_path(post)
"/admin/posts/#{post.id}/comments"
end
alias_method :admin_post_comments_path, :admin_comments_path
def admin_comment_path(post, comment)
"/admin/posts/#{post.id}/comments/#{comment.id}"
end
alias_method :admin_post_comment_path, :admin_comment_path
def posts_path
"/posts"
end
end
def post_path(post)
"/posts/#{post.id}"
end

@ -21,13 +21,14 @@ def test_should_cache_file_extension_properly
assert_equal ["builder", "erb", "rhtml", "rjs", "rxml", "mab"].sort,
ActionView::TemplateFinder.file_extension_cache[LOAD_PATH_ROOT].values.flatten.uniq.sort
assert_equal Dir.glob("#{LOAD_PATH_ROOT}/**/*/*.{erb,rjs,rhtml,builder,rxml,mab}").size,
assert_equal (Dir.glob("#{LOAD_PATH_ROOT}/**/*/*.{erb,rjs,rhtml,builder,rxml,mab}") |
Dir.glob("#{LOAD_PATH_ROOT}/**.{erb,rjs,rhtml,builder,rxml,mab}")).size,
ActionView::TemplateFinder.file_extension_cache[LOAD_PATH_ROOT].keys.size
end
def test_should_cache_dir_content_properly
assert ActionView::TemplateFinder.processed_view_paths[LOAD_PATH_ROOT]
assert_equal Dir.glob("#{LOAD_PATH_ROOT}/**/*/**").find_all {|f| !File.directory?(f) }.size,
assert_equal (Dir.glob("#{LOAD_PATH_ROOT}/**/*/**") | Dir.glob("#{LOAD_PATH_ROOT}/**")).find_all {|f| !File.directory?(f) }.size,
ActionView::TemplateFinder.processed_view_paths[LOAD_PATH_ROOT].size
end

@ -1,5 +1,7 @@
*SVN*
* Added block-setting of attributes for Base.create like Base.new already has (Adam Meehan) [#39]
* Fixed that pessimistic locking you reference the quoted table name (Josh Susser) [#67]
* Fixed that change_column should be able to use :null => true on a field that formerly had false [Nate Wiger] [#26]

@ -59,14 +59,14 @@ def add_preloaded_record_to_collection(parent_records, reflection_name, associat
def set_association_collection_records(id_to_record_map, reflection_name, associated_records, key)
associated_records.each do |associated_record|
mapped_records = id_to_record_map[associated_record[key].to_i]
mapped_records = id_to_record_map[associated_record[key].to_s]
add_preloaded_records_to_collection(mapped_records, reflection_name, associated_record)
end
end
def set_association_single_records(id_to_record_map, reflection_name, associated_records, key)
associated_records.each do |associated_record|
mapped_records = id_to_record_map[associated_record[key].to_i]
mapped_records = id_to_record_map[associated_record[key].to_s]
mapped_records.each do |mapped_record|
mapped_record.send("set_#{reflection_name}_target", associated_record)
end
@ -78,7 +78,7 @@ def construct_id_map(records)
ids = []
records.each do |record|
ids << record.id
mapped_records = (id_to_record_map[record.id] ||= [])
mapped_records = (id_to_record_map[record.id.to_s] ||= [])
mapped_records << record
end
ids.uniq!
@ -115,7 +115,7 @@ def preload_has_one_association(records, reflection, preload_options={})
source = reflection.source_reflection.name
through_records.first.class.preload_associations(through_records, source)
through_records.each do |through_record|
add_preloaded_record_to_collection(id_to_record_map[through_record[through_primary_key].to_i],
add_preloaded_record_to_collection(id_to_record_map[through_record[through_primary_key].to_s],
reflection.name, through_record.send(source))
end
end
@ -140,7 +140,7 @@ def preload_has_many_association(records, reflection, preload_options={})
source = reflection.source_reflection.name
through_records.first.class.preload_associations(through_records, source)
through_records.each do |through_record|
add_preloaded_records_to_collection(id_to_record_map[through_record[through_primary_key].to_i],
add_preloaded_records_to_collection(id_to_record_map[through_record[through_primary_key].to_s],
reflection.name, through_record.send(source))
end
end
@ -195,18 +195,22 @@ def preload_belongs_to_association(records, reflection, preload_options={})
records.each do |record|
if klass = record.send(polymorph_type)
klass_id = record.send(primary_key_name)
id_map = klasses_and_ids[klass] ||= {}
id_list_for_klass_id = (id_map[klass_id] ||= [])
id_list_for_klass_id << record
if klass_id
id_map = klasses_and_ids[klass] ||= {}
id_list_for_klass_id = (id_map[klass_id.to_s] ||= [])
id_list_for_klass_id << record
end
end
end
klasses_and_ids = klasses_and_ids.to_a
else
id_map = {}
records.each do |record|
mapped_records = (id_map[record.send(primary_key_name)] ||= [])
mapped_records << record
key = record.send(primary_key_name)
if key
mapped_records = (id_map[key.to_s] ||= [])
mapped_records << record
end
end
klasses_and_ids = [[reflection.klass.name, id_map]]
end

@ -603,13 +603,25 @@ def exists?(id_or_conditions)
# ==== Examples
# # Create a single new object
# User.create(:first_name => 'Jamie')
#
# # Create an Array of new objects
# User.create([{:first_name => 'Jamie'}, {:first_name => 'Jeremy'}])
def create(attributes = nil)
#
# # Create a single object and pass it into a block to set other attributes.
# User.create(:first_name => 'Jamie') do |u|
# u.is_admin = false
# end
#
# # Creating an Array of new objects using a block, where the block is executed for each object:
# User.create([{:first_name => 'Jamie'}, {:first_name => 'Jeremy'}]) do |u|
# u.is_admin = false
# end
def create(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create(attr) }
attributes.collect { |attr| create(attr, &block) }
else
object = new(attributes)
yield(object) if block_given?
object.save
object
end

@ -469,8 +469,8 @@ def self.cached_fixtures(connection, keys_to_fetch = nil)
fixtures.size > 1 ? fixtures : fixtures.first
end
def self.cache_fixtures(connection, fixtures)
cache_for_connection(connection).update(fixtures.index_by { |f| f.table_name })
def self.cache_fixtures(connection, fixtures_map)
cache_for_connection(connection).update(fixtures_map)
end
def self.instantiate_fixtures(object, table_name, fixtures, load_instances = true)
@ -526,7 +526,7 @@ def self.create_fixtures(fixtures_directory, table_names, class_names = {})
end
end
cache_fixtures(connection, fixtures)
cache_fixtures(connection, fixtures_map)
end
end
end

@ -873,11 +873,12 @@ def validates_numericality_of(*attr_names)
# Creates an object just like Base.create but calls save! instead of save
# so an exception is raised if the record is invalid.
def create!(attributes = nil)
def create!(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create!(attr) }
attributes.collect { |attr| create!(attr, &block) }
else
object = new(attributes)
yield(object) if block_given?
object.save!
object
end

@ -11,11 +11,14 @@
require 'models/pet'
require 'models/reference'
require 'models/job'
require 'models/subscriber'
require 'models/subscription'
require 'models/book'
class EagerAssociationTest < ActiveRecord::TestCase
fixtures :posts, :comments, :authors, :categories, :categories_posts,
:companies, :accounts, :tags, :taggings, :people, :readers,
:owners, :pets, :author_favorites, :jobs, :references
:owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books
def test_loading_with_one_association
posts = Post.find(:all, :include => :comments)
@ -220,6 +223,24 @@ def test_eager_load_has_many_through_quotes_table_and_column_names
assert_no_queries{ assert_equal jobs(:unicyclist, :magician), michael.jobs.sort_by(&:id) }
end
def test_eager_load_has_many_with_string_keys
subscriptions = subscriptions(:webster_awdr, :webster_rfr)
subscriber =Subscriber.find(subscribers(:second).id, :include => :subscriptions)
assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id)
end
def test_eager_load_has_many_through_with_string_keys
books = books(:awdr, :rfr)
subscriber = Subscriber.find(subscribers(:second).id, :include => :books)
assert_equal books, subscriber.books.sort_by(&:id)
end
def test_eager_load_belongs_to_with_string_keys
subscriber = subscribers(:second)
subscription = Subscription.find(subscriptions(:webster_awdr).id, :include => :subscriber)
assert_equal subscriber, subscription.subscriber
end
def test_eager_association_loading_with_explicit_join
posts = Post.find(:all, :include => :comments, :joins => "INNER JOIN authors ON posts.author_id = authors.id AND authors.name = 'Mary'", :limit => 1, :order => 'author_id')
assert_equal 1, posts.length

@ -251,6 +251,27 @@ def test_create_through_factory
topic = Topic.create("title" => "New Topic")
topicReloaded = Topic.find(topic.id)
assert_equal(topic, topicReloaded)
end
def test_create_through_factory_with_block
topic = Topic.create("title" => "New Topic") do |t|
t.author_name = "David"
end
topicReloaded = Topic.find(topic.id)
assert_equal("New Topic", topic.title)
assert_equal("David", topic.author_name)
end
def test_create_many_through_factory_with_block
topics = Topic.create([ { "title" => "first" }, { "title" => "second" }]) do |t|
t.author_name = "David"
end
assert_equal 2, topics.size
topic1, topic2 = Topic.find(topics[0].id), Topic.find(topics[1].id)
assert_equal "first", topic1.title
assert_equal "David", topic1.author_name
assert_equal "second", topic2.title
assert_equal "David", topic2.author_name
end
def test_update

@ -96,6 +96,10 @@ def test_inserts_with_pre_and_suffix
second_row = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'Mary'")
assert_nil(second_row["author_email_address"])
# This checks for a caching problem which causes a bug in the fixtures
# class-level configuration helper.
assert_not_nil topics, "Fixture data inserted, but fixture objects not returned from create"
ensure
# Restore prefix/suffix to its previous values
ActiveRecord::Base.table_name_prefix = old_prefix

@ -133,6 +133,22 @@ def test_exception_on_create_bang_many
Reply.create!([ { "title" => "OK" }, { "title" => "Wrong Create" }])
end
end
def test_exception_on_create_bang_with_block
assert_raises(ActiveRecord::RecordInvalid) do
Reply.create!({ "title" => "OK" }) do |r|
r.content = nil
end
end
end
def test_exception_on_create_bang_many_with_block
assert_raises(ActiveRecord::RecordInvalid) do
Reply.create!([{ "title" => "OK" }, { "title" => "Wrong Create" }]) do |r|
r.content = nil
end
end
end
def test_scoped_create_without_attributes
Reply.with_scope(:create => {}) do

@ -1,5 +1,7 @@
class Subscriber < ActiveRecord::Base
set_primary_key 'nick'
has_many :subscriptions
has_many :books, :through => :subscriptions
end
class SpecialSubscriber < Subscriber

@ -349,6 +349,11 @@ def create_table(*args, &block)
end
add_index :subscribers, :nick, :unique => true
create_table :subscriptions, :force => true do |t|
t.string :subscriber_id
t.integer :book_id
end
create_table :tasks, :force => true do |t|
t.datetime :starting
t.datetime :ending

@ -423,10 +423,12 @@ def remove_constant(const) #:nodoc:
protected
def log_call(*args)
arg_str = args.collect(&:inspect) * ', '
/in `([a-z_\?\!]+)'/ =~ caller(1).first
selector = $1 || '<unknown>'
log "called #{selector}(#{arg_str})"
if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER && log_activity
arg_str = args.collect(&:inspect) * ', '
/in `([a-z_\?\!]+)'/ =~ caller(1).first
selector = $1 || '<unknown>'
log "called #{selector}(#{arg_str})"
end
end
def log(msg)