Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #3005: association-duplicate-names-prevent-v2.patch

File association-duplicate-names-prevent-v2.patch, 4.8 kB (added by François Beausoleil <francois.beausoleil@gmail.com>, 3 years ago)

Refactored for post-[3213]

  • activerecord/test/associations_test.rb

    old new  
    258258    assert_equal a, firm.account 
    259259    assert_equal a, firm.account(true) 
    260260  end 
     261 
     262  def test_prevent_naming_association_with_existing_name 
     263    firm = Firm.new 
     264    assert_raise ActiveRecord::Reflection::ReflectionNameAlreadyTaken do 
     265      class << firm 
     266        has_one :quote 
     267      end 
     268    end 
     269  end 
    261270end 
    262271 
    263272 
     
    736745    assert_equal 2, firm.clients.length 
    737746    assert firm.clients.include?(companies(:second_client)) 
    738747  end 
     748 
     749  def test_prevent_naming_association_with_existing_name 
     750    firm = Firm.new 
     751    assert_raise ActiveRecord::Reflection::ReflectionNameAlreadyTaken do 
     752      class << firm 
     753        has_many :methods 
     754      end 
     755    end 
     756  end 
    739757end 
    740758 
    741759class BelongsToAssociationsTest < Test::Unit::TestCase 
     
    9921010    # the author id of the post should be the id we set 
    9931011    assert_equal post.author_id, author2.id 
    9941012  end 
    995    
     1013 
     1014  def test_prevent_naming_association_with_existing_name 
     1015    firm = Firm.new 
     1016    assert_raise ActiveRecord::Reflection::ReflectionNameAlreadyTaken do 
     1017      class << firm 
     1018        belongs_to :quote 
     1019      end 
     1020    end 
     1021  end 
    9961022end 
    9971023 
    9981024 
     
    14071433    assert_equal 1, developer.connection.select_one("SELECT count(*) FROM developers_projects WHERE  
    14081434      project_id = #{project.id} AND developer_id = #{developer.id}")["count(*)"].to_i 
    14091435  end 
     1436 
     1437  def test_prevent_naming_association_with_existing_name 
     1438    firm = Firm.new 
     1439    assert_raise ActiveRecord::Reflection::ReflectionNameAlreadyTaken do 
     1440      class << firm 
     1441        has_and_belongs_to_many :methods 
     1442      end 
     1443    end 
     1444  end 
    14101445end 
  • activerecord/test/aggregations_test.rb

    old new  
    4444    assert_equal "39", customers(:david).gps_location.latitude 
    4545    assert_equal "-110", customers(:david).gps_location.longitude 
    4646  end 
     47 
     48  def test_prevent_naming_aggregation_with_existing_name 
     49    assert_raise ActiveRecord::Reflection::ReflectionNameAlreadyTaken do 
     50      class << customers(:david) 
     51        composed_of :methods, :class_name => 'Money' 
     52      end 
     53    end 
     54  end 
    4755end 
  • activerecord/lib/active_record/reflection.rb

    old new  
    11module ActiveRecord 
    22  module Reflection # :nodoc: 
     3    class ReflectionNameAlreadyTaken < ActiveRecord::ConfigurationError; end 
     4 
    35    def self.included(base) 
    46      base.extend(ClassMethods) 
    57    end 
     
    1113    # You can find the interface for the AggregateReflection and AssociationReflection classes in the abstract MacroReflection class. 
    1214    module ClassMethods 
    1315      def create_reflection(macro, name, options, active_record) 
     16        guard_against_already_used_method_name(name, active_record) 
    1417        case macro 
    1518          when :has_many, :belongs_to, :has_one, :has_and_belongs_to_many 
    1619            reflections[name] = AssociationReflection.new(macro, name, options, active_record) 
     
    4447      def reflect_on_association(association) 
    4548        reflections[association].is_a?(AssociationReflection) ? reflections[association] : nil 
    4649      end 
     50 
     51      protected 
     52        def guard_against_already_used_method_name(name, active_record) 
     53          # We cast a very wide net here, maybe we should not case such as wide one ? 
     54          methods = [ActiveRecord::Base.instance_methods, ActiveRecord::Base.methods, 
     55                    active_record.instance_methods].flatten.compact.uniq 
     56          return unless methods.include?(name.to_s) 
     57          raise ReflectionNameAlreadyTaken, "`#{name}' is the name of an existing method in #{active_record.name}.  You will have to rename your association." 
     58        end 
    4759    end 
    4860 
    4961 
  • activerecord/lib/active_record/aggregations.rb

    old new  
    125131        class_name  = options[:class_name] || name_to_class_name(name) 
    126132        mapping     = options[:mapping] || [ name, name ] 
    127133 
     134        create_reflection(:composed_of, part_id, options, self) 
     135 
    128136        reader_method(name, class_name, mapping) 
    129137        writer_method(name, class_name, mapping) 
    130          
    131         create_reflection(:composed_of, part_id, options, self) 
    132138      end 
    133139 
    134140      private