diff options
25 files changed, 546 insertions, 132 deletions
@@ -51,9 +51,27 @@ desc "Generate documentation for the Rails framework" RDoc::Task.new do |rdoc| RDOC_MAIN = 'RDOC_MAIN.rdoc' + # This is a hack. + # + # Backslashes are needed to prevent RDoc from autolinking "Rails" to the + # documentation of the Rails module. On the other hand, as of this + # writing README.rdoc is displayed in the front page of the project in + # GitHub, where backslashes are shown and look weird. + # + # The temporary solution is to have a README.rdoc without backslashes for + # GitHub, and gsub it to generate the main page of the API. + # + # The idea for the future is to have totally different files, since the + # API is no longer a generic entry point to Rails and deserves a + # dedicated main page specifically thought as an API entry point. rdoc.before_running_rdoc do rdoc_main = File.read('README.rdoc') - rdoc_main.gsub!(/\b(?=Rails)\b/) { '\\' } + + # The ^(?=\S) assertion prevents code blocks from being processed, + # since no autolinking happens there and RDoc displays the backslash + # otherwise. + rdoc_main.gsub!(/^(?=\S).*?\b(?=Rails)\b/) { "#$&\\" } + File.open(RDOC_MAIN, 'w') do |f| f.write(rdoc_main) end @@ -72,7 +90,7 @@ RDoc::Task.new do |rdoc| rdoc.rdoc_files.include('railties/MIT-LICENSE') rdoc.rdoc_files.include('railties/README.rdoc') rdoc.rdoc_files.include('railties/lib/**/*.rb') - rdoc.rdoc_files.exclude('railties/lib/rails/generators/**/templates/*') + rdoc.rdoc_files.exclude('railties/lib/rails/generators/**/templates/**/*.rb') rdoc.rdoc_files.include('activerecord/README.rdoc') rdoc.rdoc_files.include('activerecord/CHANGELOG') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 1965906df9..f4b6464bdc 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,10 @@ *Rails 3.2.0 (unreleased)* +* Generate hidden input before select with :multiple option set to true. + This is useful when you rely on the fact that when no options is set, + the state of select will be sent to rails application. Without hidden field + nothing is sent according to HTML spec [Bogdan Gusiev] + * Refactor ActionController::TestCase cookies [Andrew White] Assigning cookies for test cases should now use cookies[], e.g: diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 4aa45c8bf0..1e54f0174c 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -15,6 +15,7 @@ class UrlHelperTest < ActiveSupport::TestCase routes.draw do match "/" => "foo#bar" match "/other" => "foo#other" + match "/article/:id" => "foo#article", :as => :article end include routes.url_helpers @@ -264,6 +265,13 @@ class UrlHelperTest < ActiveSupport::TestCase assert_equal '<a href="/">Example site</a>', out end + def test_link_tag_with_html_safe_string + assert_dom_equal( + "<a href=\"/article/Gerd_M%C3%BCller\">Gerd Müller</a>", + link_to("Gerd Müller", article_path("Gerd_Müller".html_safe)) + ) + end + def test_link_to_unless assert_equal "Showing", link_to_unless(true, "Showing", url_hash) diff --git a/activemodel/CHANGELOG b/activemodel/CHANGELOG index b1ad315c46..c38349b95e 100644 --- a/activemodel/CHANGELOG +++ b/activemodel/CHANGELOG @@ -2,6 +2,9 @@ *Rails 3.1.0 (unreleased)* +* Alternate I18n namespace lookup is no longer supported. + Instead of "activerecord.models.admins.post", do "activerecord.models.admins/post" instead [José Valim] + * attr_accessible and friends now accepts :as as option to specify a role [Josh Kalderimis] * Add support for proc or lambda as an option for InclusionValidator, diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index c7b9c41f46..4c1a82f413 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -21,7 +21,7 @@ module ActiveModel @partial_path = "#{@collection}/#{@element}".freeze @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural).freeze - @i18n_key = self.underscore.tr('/', '.').to_sym + @i18n_key = self.underscore.to_sym end # Transform the model name into a more humane format, using I18n. By default, @@ -35,9 +35,8 @@ module ActiveModel @klass.respond_to?(:i18n_scope) defaults = @klass.lookup_ancestors.map do |klass| - [klass.model_name.i18n_key, - klass.model_name.i18n_key.to_s.tr('.', '/').to_sym] - end.flatten + klass.model_name.i18n_key + end defaults << options[:default] if options[:default] defaults << @human diff --git a/activemodel/lib/active_model/translation.rb b/activemodel/lib/active_model/translation.rb index c615311692..6d64c81b5f 100644 --- a/activemodel/lib/active_model/translation.rb +++ b/activemodel/lib/active_model/translation.rb @@ -44,9 +44,8 @@ module ActiveModel # Specify +options+ with additional translating options. def human_attribute_name(attribute, options = {}) defaults = lookup_ancestors.map do |klass| - [:"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key}.#{attribute}", - :"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key.to_s.tr('.', '/')}.#{attribute}"] - end.flatten + :"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key}.#{attribute}" + end defaults << :"attributes.#{attribute}" defaults << options.delete(:default) if options[:default] diff --git a/activemodel/test/cases/translation_test.rb b/activemodel/test/cases/translation_test.rb index 838956bc98..1b1d972d5c 100644 --- a/activemodel/test/cases/translation_test.rb +++ b/activemodel/test/cases/translation_test.rb @@ -76,15 +76,5 @@ class ActiveModelI18nTests < ActiveModel::TestCase Person.model_name.human(options) assert_equal({:default => 'person model'}, options) end - - def test_alternate_namespaced_model_attribute_translation - I18n.backend.store_translations 'en', :activemodel => {:attributes => {:person => {:gender => {:attribute => 'person gender attribute'}}}} - assert_equal 'person gender attribute', Person::Gender.human_attribute_name('attribute') - end - - def test_alternate_namespaced_model_translation - I18n.backend.store_translations 'en', :activemodel => {:models => {:person => {:gender => 'person gender model'}}} - assert_equal 'person gender model', Person::Gender.model_name.human - end end diff --git a/activerecord/RUNNING_UNIT_TESTS b/activerecord/RUNNING_UNIT_TESTS index 8fe9a357b4..6a2e23b01f 100644 --- a/activerecord/RUNNING_UNIT_TESTS +++ b/activerecord/RUNNING_UNIT_TESTS @@ -32,3 +32,8 @@ By default the tests run with the Identity Map turned off. But all tests should not the identity map is on or off. You can turn it on using the IM env variable: $ IM=true ruby -Itest test/case/base_test.rb + +== Config file + +By default, the config file is expected to be at the path test/config.yml. You can specify a +custom location with the ARCONFIG environment variable. diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 7e1a41e84d..337a0d48f1 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -114,19 +114,13 @@ module ActiveRecord # Add +records+ to this association. Returns +self+ so method calls may be chained. # Since << flattens its argument list and inserts each record, +push+ and +concat+ behave identically. def concat(*records) - result = true load_target if owner.new_record? - transaction do - records.flatten.each do |record| - raise_on_type_mismatch(record) - add_to_target(record) do |r| - result &&= insert_record(record) unless owner.new_record? - end - end + if owner.new_record? + concat_records(records) + else + transaction { concat_records(records) } end - - result && records end # Starts a transaction in the association class's database connection. @@ -295,14 +289,10 @@ module ActiveRecord other_array.each { |val| raise_on_type_mismatch(val) } original_target = load_target.dup - transaction do - delete(target - other_array) - - unless concat(other_array - target) - @target = original_target - raise RecordNotSaved, "Failed to replace #{reflection.name} because one or more of the " \ - "new records could not be saved." - end + if owner.new_record? + replace_records(other_array, original_target) + else + transaction { replace_records(other_array, original_target) } end end @@ -444,14 +434,20 @@ module ActiveRecord records.each { |record| raise_on_type_mismatch(record) } existing_records = records.reject { |r| r.new_record? } - transaction do - records.each { |record| callback(:before_remove, record) } + if existing_records.empty? + remove_records(existing_records, records, method) + else + transaction { remove_records(existing_records, records, method) } + end + end - delete_records(existing_records, method) if existing_records.any? - records.each { |record| target.delete(record) } + def remove_records(existing_records, records, method) + records.each { |record| callback(:before_remove, record) } - records.each { |record| callback(:after_remove, record) } - end + delete_records(existing_records, method) if existing_records.any? + records.each { |record| target.delete(record) } + + records.each { |record| callback(:after_remove, record) } end # Delete the given records from the association, using one of the methods :destroy, @@ -460,6 +456,29 @@ module ActiveRecord raise NotImplementedError end + def replace_records(new_target, original_target) + delete(target - new_target) + + unless concat(new_target - target) + @target = original_target + raise RecordNotSaved, "Failed to replace #{reflection.name} because one or more of the " \ + "new records could not be saved." + end + end + + def concat_records(records) + result = true + + records.flatten.each do |record| + raise_on_type_mismatch(record) + add_to_target(record) do |r| + result &&= insert_record(record) unless owner.new_record? + end + end + + result && records + end + def callback(method, record) callbacks_for(method).each do |callback| case callback diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 2f283ff6bc..08cccf1da2 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1717,10 +1717,13 @@ MSG attributes.each do |k, v| if k.include?("(") multi_parameter_attributes << [ k, v ] - elsif respond_to?("#{k}=") - send("#{k}=", v) else - raise(UnknownAttributeError, "unknown attribute: #{k}") + method_name = "#{k}=" + if respond_to?(method_name) + method(method_name).arity == -2 ? send(method_name, v, options) : send(method_name, v) + else + raise(UnknownAttributeError, "unknown attribute: #{k}") + end end end diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 08b27b6a8e..f51fd21077 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -276,15 +276,15 @@ module ActiveRecord type = (reflection.collection? ? :collection : :one_to_one) - # def pirate_attributes=(attributes) - # assign_nested_attributes_for_one_to_one_association(:pirate, attributes) + # def pirate_attributes=(attributes, assignment_opts = {}) + # assign_nested_attributes_for_one_to_one_association(:pirate, attributes, assignment_opts) # end class_eval <<-eoruby, __FILE__, __LINE__ + 1 if method_defined?(:#{association_name}_attributes=) remove_method(:#{association_name}_attributes=) end - def #{association_name}_attributes=(attributes) - assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes) + def #{association_name}_attributes=(attributes, assignment_opts = {}) + assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes, assignment_opts) end eoruby else @@ -319,21 +319,21 @@ module ActiveRecord # If the given attributes include a matching <tt>:id</tt> attribute, or # update_only is true, and a <tt>:_destroy</tt> key set to a truthy value, # then the existing record will be marked for destruction. - def assign_nested_attributes_for_one_to_one_association(association_name, attributes) + def assign_nested_attributes_for_one_to_one_association(association_name, attributes, assignment_opts = {}) options = self.nested_attributes_options[association_name] attributes = attributes.with_indifferent_access if (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) && (options[:update_only] || record.id.to_s == attributes['id'].to_s) - assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy]) unless call_reject_if(association_name, attributes) + assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy], assignment_opts) unless call_reject_if(association_name, attributes) - elsif attributes['id'].present? + elsif attributes['id'].present? && !assignment_opts[:without_protection] raise_nested_attributes_record_not_found(association_name, attributes['id']) elsif !reject_new_record?(association_name, attributes) method = "build_#{association_name}" if respond_to?(method) - send(method, attributes.except(*UNASSIGNABLE_KEYS)) + send(method, attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) else raise ArgumentError, "Cannot build association #{association_name}. Are you trying to build a polymorphic one-to-one association?" end @@ -367,7 +367,7 @@ module ActiveRecord # { :name => 'John' }, # { :id => '2', :_destroy => true } # ]) - def assign_nested_attributes_for_collection_association(association_name, attributes_collection) + def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {}) options = self.nested_attributes_options[association_name] unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array) @@ -401,7 +401,7 @@ module ActiveRecord if attributes['id'].blank? unless reject_new_record?(association_name, attributes) - association.build(attributes.except(*UNASSIGNABLE_KEYS)) + association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) end elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s } unless association.loaded? || call_reject_if(association_name, attributes) @@ -418,8 +418,10 @@ module ActiveRecord end if !call_reject_if(association_name, attributes) - assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) + assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy], assignment_opts) end + elsif assignment_opts[:without_protection] + association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) else raise_nested_attributes_record_not_found(association_name, attributes['id']) end @@ -428,8 +430,8 @@ module ActiveRecord # Updates a record with the +attributes+ or marks it for destruction if # +allow_destroy+ is +true+ and has_destroy_flag? returns +true+. - def assign_to_or_mark_for_destruction(record, attributes, allow_destroy) - record.attributes = attributes.except(*UNASSIGNABLE_KEYS) + def assign_to_or_mark_for_destruction(record, attributes, allow_destroy, assignment_opts) + record.assign_attributes(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) record.mark_for_destruction if has_destroy_flag?(attributes) && allow_destroy end @@ -458,5 +460,9 @@ module ActiveRecord def raise_nested_attributes_record_not_found(association_name, record_id) raise RecordNotFound, "Couldn't find #{self.class.reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}" end + + def unassignable_keys(assignment_opts) + assignment_opts[:without_protection] ? UNASSIGNABLE_KEYS - %w[id] : UNASSIGNABLE_KEYS + end end end diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb index c61428e104..ffe9b08dce 100644 --- a/activerecord/lib/active_record/test_case.rb +++ b/activerecord/lib/active_record/test_case.rb @@ -31,27 +31,30 @@ module ActiveRecord end def assert_sql(*patterns_to_match) - $queries_executed = [] + ActiveRecord::SQLCounter.log = [] yield - $queries_executed + ActiveRecord::SQLCounter.log ensure failed_patterns = [] patterns_to_match.each do |pattern| - failed_patterns << pattern unless $queries_executed.any?{ |sql| pattern === sql } + failed_patterns << pattern unless ActiveRecord::SQLCounter.log.any?{ |sql| pattern === sql } end - assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map{ |p| p.inspect }.join(', ')} not found.#{$queries_executed.size == 0 ? '' : "\nQueries:\n#{$queries_executed.join("\n")}"}" + assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map{ |p| p.inspect }.join(', ')} not found.#{ActiveRecord::SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{ActiveRecord::SQLCounter.log.join("\n")}"}" end def assert_queries(num = 1) - $queries_executed = [] + ActiveRecord::SQLCounter.log = [] yield ensure - %w{ BEGIN COMMIT }.each { |x| $queries_executed.delete(x) } - assert_equal num, $queries_executed.size, "#{$queries_executed.size} instead of #{num} queries were executed.#{$queries_executed.size == 0 ? '' : "\nQueries:\n#{$queries_executed.join("\n")}"}" + assert_equal num, ActiveRecord::SQLCounter.log.size, "#{ActiveRecord::SQLCounter.log.size} instead of #{num} queries were executed.#{ActiveRecord::SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{ActiveRecord::SQLCounter.log.join("\n")}"}" end def assert_no_queries(&block) + prev_ignored_sql = ActiveRecord::SQLCounter.ignored_sql + ActiveRecord::SQLCounter.ignored_sql = [] assert_queries(0, &block) + ensure + ActiveRecord::SQLCounter.ignored_sql = prev_ignored_sql end def with_kcode(kcode) diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 49999630b6..9af1f7249f 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -537,6 +537,25 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal 3, companies(:first_firm).clients_of_firm(true).size end + def test_transactions_when_adding_to_persisted + good = Client.new(:name => "Good") + bad = Client.new(:name => "Bad", :raise_on_save => true) + + begin + companies(:first_firm).clients_of_firm.concat(good, bad) + rescue Client::RaisedOnSave + end + + assert !companies(:first_firm).clients_of_firm(true).include?(good) + end + + def test_transactions_when_adding_to_new_record + assert_no_queries do + firm = Firm.new + firm.clients_of_firm.concat(Client.new("name" => "Natural Company")) + end + end + def test_new_aliased_to_build company = companies(:first_firm) new_client = assert_no_queries { company.clients_of_firm.new("name" => "Another Client") } @@ -778,6 +797,29 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal 0, companies(:first_firm).clients_of_firm(true).size end + def test_transaction_when_deleting_persisted + good = Client.new(:name => "Good") + bad = Client.new(:name => "Bad", :raise_on_destroy => true) + + companies(:first_firm).clients_of_firm = [good, bad] + + begin + companies(:first_firm).clients_of_firm.destroy(good, bad) + rescue Client::RaisedOnDestroy + end + + assert_equal [good, bad], companies(:first_firm).clients_of_firm(true) + end + + def test_transaction_when_deleting_new_record + assert_no_queries do + firm = Firm.new + client = Client.new("name" => "New Client") + firm.clients_of_firm << client + firm.clients_of_firm.destroy(client) + end + end + def test_clearing_an_association_collection firm = companies(:first_firm) client_id = firm.clients_of_firm.first.id @@ -1111,6 +1153,27 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal orig_accounts, firm.accounts end + def test_transactions_when_replacing_on_persisted + good = Client.new(:name => "Good") + bad = Client.new(:name => "Bad", :raise_on_save => true) + + companies(:first_firm).clients_of_firm = [good] + + begin + companies(:first_firm).clients_of_firm = [bad] + rescue Client::RaisedOnSave + end + + assert_equal [good], companies(:first_firm).clients_of_firm(true) + end + + def test_transactions_when_replacing_on_new_record + assert_no_queries do + firm = Firm.new + firm.clients_of_firm = [Client.new("name" => "New Client")] + end + end + def test_get_ids assert_equal [companies(:first_client).id, companies(:second_client).id], companies(:first_firm).client_ids end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 8f55b7ebe6..4ad2cdfc7e 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -837,7 +837,7 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase @pirate.parrots.each { |parrot| parrot.mark_for_destruction } assert @pirate.save - assert_no_queries do + assert_queries(0) do assert @pirate.save end end diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index d0dc9cb03d..6735bc521b 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -58,15 +58,15 @@ end module ActiveRecord class SQLCounter - IGNORED_SQL = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/] + cattr_accessor :ignored_sql + self.ignored_sql = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/] # FIXME: this needs to be refactored so specific database can add their own # ignored SQL. This ignored SQL is for Oracle. - IGNORED_SQL.concat [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im] + ignored_sql.concat [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im] - def initialize - $queries_executed = [] - end + cattr_accessor :log + self.log = [] def call(name, start, finish, message_id, values) sql = values[:sql] @@ -74,10 +74,11 @@ module ActiveRecord # FIXME: this seems bad. we should probably have a better way to indicate # the query was cached unless 'CACHE' == values[:name] - $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r } + self.class.log << sql unless self.class.ignored_sql.any? { |r| sql =~ r } end end end + ActiveSupport::Notifications.subscribe('sql.active_record', SQLCounter.new) end diff --git a/activerecord/test/cases/mass_assignment_security_test.rb b/activerecord/test/cases/mass_assignment_security_test.rb index 33737e12a8..ef35f3341e 100644 --- a/activerecord/test/cases/mass_assignment_security_test.rb +++ b/activerecord/test/cases/mass_assignment_security_test.rb @@ -384,81 +384,81 @@ class MassAssignmentSecurityBelongsToRelationsTest < ActiveRecord::TestCase # build - def test_has_one_build_with_attr_protected_attributes + def test_belongs_to_build_with_attr_protected_attributes best_friend = @person.build_best_friend_of(attributes_hash) assert_default_attributes(best_friend) end - def test_has_one_build_with_attr_accessible_attributes + def test_belongs_to_build_with_attr_accessible_attributes best_friend = @person.build_best_friend_of(attributes_hash) assert_default_attributes(best_friend) end - def test_has_one_build_with_admin_role_with_attr_protected_attributes + def test_belongs_to_build_with_admin_role_with_attr_protected_attributes best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end - def test_has_one_build_with_admin_role_with_attr_accessible_attributes + def test_belongs_to_build_with_admin_role_with_attr_accessible_attributes best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end - def test_has_one_build_without_protection + def test_belongs_to_build_without_protection best_friend = @person.build_best_friend_of(attributes_hash, :without_protection => true) assert_all_attributes(best_friend) end # create - def test_has_one_create_with_attr_protected_attributes + def test_belongs_to_create_with_attr_protected_attributes best_friend = @person.create_best_friend_of(attributes_hash) assert_default_attributes(best_friend, true) end - def test_has_one_create_with_attr_accessible_attributes + def test_belongs_to_create_with_attr_accessible_attributes best_friend = @person.create_best_friend_of(attributes_hash) assert_default_attributes(best_friend, true) end - def test_has_one_create_with_admin_role_with_attr_protected_attributes + def test_belongs_to_create_with_admin_role_with_attr_protected_attributes best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_admin_role_with_attr_accessible_attributes + def test_belongs_to_create_with_admin_role_with_attr_accessible_attributes best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_without_protection + def test_belongs_to_create_without_protection best_friend = @person.create_best_friend_of(attributes_hash, :without_protection => true) assert_all_attributes(best_friend) end # create! - def test_has_one_create_with_bang_with_attr_protected_attributes + def test_belongs_to_create_with_bang_with_attr_protected_attributes best_friend = @person.create_best_friend!(attributes_hash) assert_default_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_attr_accessible_attributes + def test_belongs_to_create_with_bang_with_attr_accessible_attributes best_friend = @person.create_best_friend!(attributes_hash) assert_default_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes + def test_belongs_to_create_with_bang_with_admin_role_with_attr_protected_attributes best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes + def test_belongs_to_create_with_bang_with_admin_role_with_attr_accessible_attributes best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_bang_without_protection + def test_belongs_to_create_with_bang_without_protection best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true) assert_all_attributes(best_friend) end @@ -472,83 +472,328 @@ class MassAssignmentSecurityHasManyRelationsTest < ActiveRecord::TestCase # build - def test_has_one_build_with_attr_protected_attributes + def test_has_many_build_with_attr_protected_attributes best_friend = @person.best_friends.build(attributes_hash) assert_default_attributes(best_friend) end - def test_has_one_build_with_attr_accessible_attributes + def test_has_many_build_with_attr_accessible_attributes best_friend = @person.best_friends.build(attributes_hash) assert_default_attributes(best_friend) end - def test_has_one_build_with_admin_role_with_attr_protected_attributes + def test_has_many_build_with_admin_role_with_attr_protected_attributes best_friend = @person.best_friends.build(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end - def test_has_one_build_with_admin_role_with_attr_accessible_attributes + def test_has_many_build_with_admin_role_with_attr_accessible_attributes best_friend = @person.best_friends.build(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end - def test_has_one_build_without_protection + def test_has_many_build_without_protection best_friend = @person.best_friends.build(attributes_hash, :without_protection => true) assert_all_attributes(best_friend) end # create - def test_has_one_create_with_attr_protected_attributes + def test_has_many_create_with_attr_protected_attributes best_friend = @person.best_friends.create(attributes_hash) assert_default_attributes(best_friend, true) end - def test_has_one_create_with_attr_accessible_attributes + def test_has_many_create_with_attr_accessible_attributes best_friend = @person.best_friends.create(attributes_hash) assert_default_attributes(best_friend, true) end - def test_has_one_create_with_admin_role_with_attr_protected_attributes + def test_has_many_create_with_admin_role_with_attr_protected_attributes best_friend = @person.best_friends.create(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_admin_role_with_attr_accessible_attributes + def test_has_many_create_with_admin_role_with_attr_accessible_attributes best_friend = @person.best_friends.create(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_without_protection + def test_has_many_create_without_protection best_friend = @person.best_friends.create(attributes_hash, :without_protection => true) assert_all_attributes(best_friend) end # create! - def test_has_one_create_with_bang_with_attr_protected_attributes + def test_has_many_create_with_bang_with_attr_protected_attributes best_friend = @person.best_friends.create!(attributes_hash) assert_default_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_attr_accessible_attributes + def test_has_many_create_with_bang_with_attr_accessible_attributes best_friend = @person.best_friends.create!(attributes_hash) assert_default_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes + def test_has_many_create_with_bang_with_admin_role_with_attr_protected_attributes best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes + def test_has_many_create_with_bang_with_admin_role_with_attr_accessible_attributes best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_bang_without_protection + def test_has_many_create_with_bang_without_protection best_friend = @person.best_friends.create!(attributes_hash, :without_protection => true) assert_all_attributes(best_friend) end end + + +class MassAssignmentSecurityNestedAttributesTest < ActiveRecord::TestCase + include MassAssignmentTestHelpers + + def nested_attributes_hash(association, collection = false, except = [:id]) + if collection + { :first_name => 'David' }.merge(:"#{association}_attributes" => [attributes_hash.except(*except)]) + else + { :first_name => 'David' }.merge(:"#{association}_attributes" => attributes_hash.except(*except)) + end + end + + # build + + def test_has_one_new_with_attr_protected_attributes + person = LoosePerson.new(nested_attributes_hash(:best_friend)) + assert_default_attributes(person.best_friend) + end + + def test_has_one_new_with_attr_accessible_attributes + person = TightPerson.new(nested_attributes_hash(:best_friend)) + assert_default_attributes(person.best_friend) + end + + def test_has_one_new_with_admin_role_with_attr_protected_attributes + person = LoosePerson.new(nested_attributes_hash(:best_friend), :as => :admin) + assert_admin_attributes(person.best_friend) + end + + def test_has_one_new_with_admin_role_with_attr_accessible_attributes + person = TightPerson.new(nested_attributes_hash(:best_friend), :as => :admin) + assert_admin_attributes(person.best_friend) + end + + def test_has_one_new_without_protection + person = LoosePerson.new(nested_attributes_hash(:best_friend, false, nil), :without_protection => true) + assert_all_attributes(person.best_friend) + end + + def test_belongs_to_new_with_attr_protected_attributes + person = LoosePerson.new(nested_attributes_hash(:best_friend_of)) + assert_default_attributes(person.best_friend_of) + end + + def test_belongs_to_new_with_attr_accessible_attributes + person = TightPerson.new(nested_attributes_hash(:best_friend_of)) + assert_default_attributes(person.best_friend_of) + end + + def test_belongs_to_new_with_admin_role_with_attr_protected_attributes + person = LoosePerson.new(nested_attributes_hash(:best_friend_of), :as => :admin) + assert_admin_attributes(person.best_friend_of) + end + + def test_belongs_to_new_with_admin_role_with_attr_accessible_attributes + person = TightPerson.new(nested_attributes_hash(:best_friend_of), :as => :admin) + assert_admin_attributes(person.best_friend_of) + end + + def test_belongs_to_new_without_protection + person = LoosePerson.new(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true) + assert_all_attributes(person.best_friend_of) + end + + def test_has_many_new_with_attr_protected_attributes + person = LoosePerson.new(nested_attributes_hash(:best_friends, true)) + assert_default_attributes(person.best_friends.first) + end + + def test_has_many_new_with_attr_accessible_attributes + person = TightPerson.new(nested_attributes_hash(:best_friends, true)) + assert_default_attributes(person.best_friends.first) + end + + def test_has_many_new_with_admin_role_with_attr_protected_attributes + person = LoosePerson.new(nested_attributes_hash(:best_friends, true), :as => :admin) + assert_admin_attributes(person.best_friends.first) + end + + def test_has_many_new_with_admin_role_with_attr_accessible_attributes + person = TightPerson.new(nested_attributes_hash(:best_friends, true), :as => :admin) + assert_admin_attributes(person.best_friends.first) + end + + def test_has_many_new_without_protection + person = LoosePerson.new(nested_attributes_hash(:best_friends, true, nil), :without_protection => true) + assert_all_attributes(person.best_friends.first) + end + + # create + + def test_has_one_create_with_attr_protected_attributes + person = LoosePerson.create(nested_attributes_hash(:best_friend)) + assert_default_attributes(person.best_friend, true) + end + + def test_has_one_create_with_attr_accessible_attributes + person = TightPerson.create(nested_attributes_hash(:best_friend)) + assert_default_attributes(person.best_friend, true) + end + + def test_has_one_create_with_admin_role_with_attr_protected_attributes + person = LoosePerson.create(nested_attributes_hash(:best_friend), :as => :admin) + assert_admin_attributes(person.best_friend, true) + end + + def test_has_one_create_with_admin_role_with_attr_accessible_attributes + person = TightPerson.create(nested_attributes_hash(:best_friend), :as => :admin) + assert_admin_attributes(person.best_friend, true) + end + + def test_has_one_create_without_protection + person = LoosePerson.create(nested_attributes_hash(:best_friend, false, nil), :without_protection => true) + assert_all_attributes(person.best_friend) + end + + def test_belongs_to_create_with_attr_protected_attributes + person = LoosePerson.create(nested_attributes_hash(:best_friend_of)) + assert_default_attributes(person.best_friend_of, true) + end + + def test_belongs_to_create_with_attr_accessible_attributes + person = TightPerson.create(nested_attributes_hash(:best_friend_of)) + assert_default_attributes(person.best_friend_of, true) + end + + def test_belongs_to_create_with_admin_role_with_attr_protected_attributes + person = LoosePerson.create(nested_attributes_hash(:best_friend_of), :as => :admin) + assert_admin_attributes(person.best_friend_of, true) + end + + def test_belongs_to_create_with_admin_role_with_attr_accessible_attributes + person = TightPerson.create(nested_attributes_hash(:best_friend_of), :as => :admin) + assert_admin_attributes(person.best_friend_of, true) + end + + def test_belongs_to_create_without_protection + person = LoosePerson.create(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true) + assert_all_attributes(person.best_friend_of) + end + + def test_has_many_create_with_attr_protected_attributes + person = LoosePerson.create(nested_attributes_hash(:best_friends, true)) + assert_default_attributes(person.best_friends.first, true) + end + + def test_has_many_create_with_attr_accessible_attributes + person = TightPerson.create(nested_attributes_hash(:best_friends, true)) + assert_default_attributes(person.best_friends.first, true) + end + + def test_has_many_create_with_admin_role_with_attr_protected_attributes + person = LoosePerson.create(nested_attributes_hash(:best_friends, true), :as => :admin) + assert_admin_attributes(person.best_friends.first, true) + end + + def test_has_many_create_with_admin_role_with_attr_accessible_attributes + person = TightPerson.create(nested_attributes_hash(:best_friends, true), :as => :admin) + assert_admin_attributes(person.best_friends.first, true) + end + + def test_has_many_create_without_protection + person = LoosePerson.create(nested_attributes_hash(:best_friends, true, nil), :without_protection => true) + assert_all_attributes(person.best_friends.first) + end + + # create! + + def test_has_one_create_with_bang_with_attr_protected_attributes + person = LoosePerson.create!(nested_attributes_hash(:best_friend)) + assert_default_attributes(person.best_friend, true) + end + + def test_has_one_create_with_bang_with_attr_accessible_attributes + person = TightPerson.create!(nested_attributes_hash(:best_friend)) + assert_default_attributes(person.best_friend, true) + end + + def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes + person = LoosePerson.create!(nested_attributes_hash(:best_friend), :as => :admin) + assert_admin_attributes(person.best_friend, true) + end + + def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes + person = TightPerson.create!(nested_attributes_hash(:best_friend), :as => :admin) + assert_admin_attributes(person.best_friend, true) + end + + def test_has_one_create_with_bang_without_protection + person = LoosePerson.create!(nested_attributes_hash(:best_friend, false, nil), :without_protection => true) + assert_all_attributes(person.best_friend) + end + + def test_belongs_to_create_with_bang_with_attr_protected_attributes + person = LoosePerson.create!(nested_attributes_hash(:best_friend_of)) + assert_default_attributes(person.best_friend_of, true) + end + + def test_belongs_to_create_with_bang_with_attr_accessible_attributes + person = TightPerson.create!(nested_attributes_hash(:best_friend_of)) + assert_default_attributes(person.best_friend_of, true) + end + + def test_belongs_to_create_with_bang_with_admin_role_with_attr_protected_attributes + person = LoosePerson.create!(nested_attributes_hash(:best_friend_of), :as => :admin) + assert_admin_attributes(person.best_friend_of, true) + end + + def test_belongs_to_create_with_bang_with_admin_role_with_attr_accessible_attributes + person = TightPerson.create!(nested_attributes_hash(:best_friend_of), :as => :admin) + assert_admin_attributes(person.best_friend_of, true) + end + + def test_belongs_to_create_with_bang_without_protection + person = LoosePerson.create!(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true) + assert_all_attributes(person.best_friend_of) + end + + def test_has_many_create_with_bang_with_attr_protected_attributes + person = LoosePerson.create!(nested_attributes_hash(:best_friends, true)) + assert_default_attributes(person.best_friends.first, true) + end + + def test_has_many_create_with_bang_with_attr_accessible_attributes + person = TightPerson.create!(nested_attributes_hash(:best_friends, true)) + assert_default_attributes(person.best_friends.first, true) + end + + def test_has_many_create_with_bang_with_admin_role_with_attr_protected_attributes + person = LoosePerson.create!(nested_attributes_hash(:best_friends, true), :as => :admin) + assert_admin_attributes(person.best_friends.first, true) + end + + def test_has_many_create_with_bang_with_admin_role_with_attr_accessible_attributes + person = TightPerson.create!(nested_attributes_hash(:best_friends, true), :as => :admin) + assert_admin_attributes(person.best_friends.first, true) + end + + def test_has_many_create_with_bang_without_protection + person = LoosePerson.create!(nested_attributes_hash(:best_friends, true, nil), :without_protection => true) + assert_all_attributes(person.best_friends.first) + end + +end diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index e0b30efd51..c1f7a4171a 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -124,6 +124,18 @@ class Client < Company has_many :accounts, :through => :firm belongs_to :account + class RaisedOnSave < RuntimeError; end + attr_accessor :raise_on_save + before_save do + raise RaisedOnSave if raise_on_save + end + + class RaisedOnDestroy < RuntimeError; end + attr_accessor :raise_on_destroy + before_destroy do + raise RaisedOnDestroy if raise_on_destroy + end + # Record destruction so we can test whether firm.clients.clear has # is calling client.destroy, deleting from the database, or setting # foreign keys to NULL. diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index a58c9bf572..967a3625aa 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -59,8 +59,9 @@ class LoosePerson < ActiveRecord::Base has_one :best_friend, :class_name => 'LoosePerson', :foreign_key => :best_friend_id belongs_to :best_friend_of, :class_name => 'LoosePerson', :foreign_key => :best_friend_of_id - has_many :best_friends, :class_name => 'LoosePerson', :foreign_key => :best_friend_id + + accepts_nested_attributes_for :best_friend, :best_friend_of, :best_friends end class LooseDescendant < LoosePerson; end @@ -70,11 +71,14 @@ class TightPerson < ActiveRecord::Base attr_accessible :first_name, :gender attr_accessible :first_name, :gender, :comments, :as => :admin + attr_accessible :best_friend_attributes, :best_friend_of_attributes, :best_friends_attributes + attr_accessible :best_friend_attributes, :best_friend_of_attributes, :best_friends_attributes, :as => :admin has_one :best_friend, :class_name => 'TightPerson', :foreign_key => :best_friend_id belongs_to :best_friend_of, :class_name => 'TightPerson', :foreign_key => :best_friend_of_id - has_many :best_friends, :class_name => 'TightPerson', :foreign_key => :best_friend_id + + accepts_nested_attributes_for :best_friend, :best_friend_of, :best_friends end class TightDescendant < TightPerson; end
\ No newline at end of file diff --git a/activerecord/test/support/config.rb b/activerecord/test/support/config.rb index 3b1598e368..c7ac077599 100644 --- a/activerecord/test/support/config.rb +++ b/activerecord/test/support/config.rb @@ -10,13 +10,16 @@ module ARTest private + def config_file + Pathname.new(ENV['ARCONFIG'] || TEST_ROOT + '/config.yml') + end + def read_config - unless File.exist?(TEST_ROOT + '/config.yml') - FileUtils.cp TEST_ROOT + '/config.example.yml', TEST_ROOT + '/config.yml' + unless config_file.exist? + FileUtils.cp TEST_ROOT + '/config.example.yml', config_file end - raw = File.read(TEST_ROOT + '/config.yml') - erb = Erubis::Eruby.new(raw) + erb = Erubis::Eruby.new(config_file.read) expand_config(YAML.parse(erb.result(binding)).transform) end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 20e40fe40f..8b8aa2b380 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -103,6 +103,10 @@ module ActiveSupport #:nodoc: self end + def to_param + to_str + end + def encode_with(coder) coder.represent_scalar nil, to_str end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 32675c884a..7a8cda160d 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -251,7 +251,7 @@ class StringInflectionsTest < Test::Unit::TestCase # And changes the original string: assert_equal original, expected end - + def test_string_inquiry assert "production".inquiry.production? assert !"production".inquiry.development? @@ -451,6 +451,12 @@ class OutputSafetyTest < ActiveSupport::TestCase assert !'ruby'.encoding_aware? end end + + test "call to_param returns a normal string" do + string = @string.html_safe + assert string.html_safe? + assert !string.to_param.html_safe? + end end class StringExcludeTest < ActiveSupport::TestCase diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 807350316c..7c0a2b9cf4 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -11,15 +11,15 @@ module Rails def app if mountable? directory "app" - template "#{app_templates_dir}/app/views/layouts/application.html.erb.tt", + template "app/views/layouts/application.html.erb.tt", "app/views/layouts/#{name}/application.html.erb" - empty_directory_with_gitkeep "app/assets/images" + empty_directory_with_gitkeep "app/assets/images/#{name}" elsif full? empty_directory_with_gitkeep "app/models" empty_directory_with_gitkeep "app/controllers" empty_directory_with_gitkeep "app/views" empty_directory_with_gitkeep "app/helpers" - empty_directory_with_gitkeep "app/assets/images" + empty_directory_with_gitkeep "app/assets/images/#{name}" end end @@ -108,9 +108,9 @@ task :default => :test def stylesheets if mountable? copy_file "#{app_templates_dir}/app/assets/stylesheets/application.css", - "app/assets/stylesheets/application.css" + "app/assets/stylesheets/#{name}/application.css" elsif full? - empty_directory_with_gitkeep "app/assets/stylesheets" + empty_directory_with_gitkeep "app/assets/stylesheets/#{name}" end end @@ -119,9 +119,9 @@ task :default => :test if mountable? template "#{app_templates_dir}/app/assets/javascripts/application.js.tt", - "app/assets/javascripts/application.js" + "app/assets/javascripts/#{name}/application.js" elsif full? - empty_directory_with_gitkeep "app/assets/javascripts" + empty_directory_with_gitkeep "app/assets/javascripts/#{name}" end end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/application.html.erb.tt new file mode 100644 index 0000000000..01550dec2f --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/application.html.erb.tt @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> + <title><%= camelized %></title> + <%%= stylesheet_link_tag "<%= name %>/application" %> + <%%= javascript_include_tag "<%= name %>/application" %> + <%%= csrf_meta_tags %> +</head> +<body> + +<%%= yield %> + +</body> +</html> diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb index aa4db6e12a..8c2c079fb8 100644 --- a/railties/test/application/initializers/i18n_test.rb +++ b/railties/test/application/initializers/i18n_test.rb @@ -52,7 +52,7 @@ module ApplicationTests end test "locale files should be added to the load path" do - app_file "config/another_locale.yml", "" + app_file "config/another_locale.yml", "en:\nfoo: ~" add_to_config <<-RUBY config.i18n.load_path << config.root.join("config/another_locale.yml").to_s @@ -131,7 +131,7 @@ en: # Fallbacks test "not using config.i18n.fallbacks does not initialize I18n.fallbacks" do - I18n.backend = Class.new { include I18n::Backend::Base }.new + I18n.backend = Class.new(I18n::Backend::Simple).new load_app assert_no_fallbacks end @@ -145,7 +145,7 @@ en: test "config.i18n.fallbacks = true initializes I18n.fallbacks with default settings even when backend changes" do I18n::Railtie.config.i18n.fallbacks = true - I18n::Railtie.config.i18n.backend = Class.new { include I18n::Backend::Base }.new + I18n::Railtie.config.i18n.backend = Class.new(I18n::Backend::Simple).new load_app assert I18n.backend.class.included_modules.include?(I18n::Backend::Fallbacks) assert_fallbacks :de => [:de, :en] diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 283d99dd9e..9ef0533979 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -101,19 +101,19 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_skipping_javascripts_without_mountable_option run_generator - assert_no_file "app/assets/javascripts/application.js" + assert_no_file "app/assets/javascripts/bukkits/application.js" assert_no_file "vendor/assets/javascripts/jquery.js" assert_no_file "vendor/assets/javascripts/jquery_ujs.js" end def test_javascripts_generation run_generator [destination_root, "--mountable"] - assert_file "app/assets/javascripts/application.js" + assert_file "app/assets/javascripts/bukkits/application.js" end def test_jquery_is_the_default_javascript_library run_generator [destination_root, "--mountable"] - assert_file "app/assets/javascripts/application.js" do |contents| + assert_file "app/assets/javascripts/bukkits/application.js" do |contents| assert_match %r{^//= require jquery}, contents assert_match %r{^//= require jquery_ujs}, contents end @@ -124,7 +124,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_other_javascript_libraries run_generator [destination_root, "--mountable", '-j', 'prototype'] - assert_file "app/assets/javascripts/application.js" do |contents| + assert_file "app/assets/javascripts/bukkits/application.js" do |contents| assert_match %r{^//= require prototype}, contents assert_match %r{^//= require prototype_ujs}, contents end @@ -135,7 +135,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_skip_javascripts run_generator [destination_root, "--skip-javascript", "--mountable"] - assert_no_file "app/assets/javascripts/application.js" + assert_no_file "app/assets/javascripts/bukkits/application.js" assert_no_file "vendor/assets/javascripts/jquery.js" assert_no_file "vendor/assets/javascripts/jquery_ujs.js" end @@ -161,9 +161,9 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_creating_engine_in_full_mode run_generator [destination_root, "--full"] - assert_file "app/assets/javascripts" - assert_file "app/assets/stylesheets" - assert_file "app/assets/images" + assert_file "app/assets/javascripts/bukkits" + assert_file "app/assets/stylesheets/bukkits" + assert_file "app/assets/images/bukkits" assert_file "app/models" assert_file "app/controllers" assert_file "app/views" @@ -180,15 +180,19 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_create_mountable_application_with_mountable_option run_generator [destination_root, "--mountable"] - assert_file "app/assets/javascripts" - assert_file "app/assets/stylesheets" - assert_file "app/assets/images" + assert_file "app/assets/javascripts/bukkits" + assert_file "app/assets/stylesheets/bukkits" + assert_file "app/assets/images/bukkits" assert_file "config/routes.rb", /Bukkits::Engine.routes.draw do/ assert_file "lib/bukkits/engine.rb", /isolate_namespace Bukkits/ assert_file "test/dummy/config/routes.rb", /mount Bukkits::Engine => "\/bukkits"/ assert_file "app/controllers/bukkits/application_controller.rb", /module Bukkits\n class ApplicationController < ActionController::Base/ assert_file "app/helpers/bukkits/application_helper.rb", /module Bukkits\n module ApplicationHelper/ - assert_file "app/views/layouts/bukkits/application.html.erb", /<title>Bukkits<\/title>/ + assert_file "app/views/layouts/bukkits/application.html.erb" do |contents| + assert_match "<title>Bukkits</title>", contents + assert_match /stylesheet_link_tag\s+['"]bukkits\/application['"]/, contents + assert_match /javascript_include_tag\s+['"]bukkits\/application['"]/, contents + end end def test_creating_gemspec |