新手问题 单表继承问题

bill_yang1016 · 2015年07月03日 · 最后由 bill_yang1016 回复于 2015年07月08日 · 1750 次阅读

我原来只有 Test 类

class Test< ActiveRecord::Base
  ...
end

但是我要增加一个类 SuperTest,如果这个类继承自 Test,就比较怪异,所以新增了一个基类 BaseTest,让两者都继承自 BaseTest

class BaseTest < ActiveRecord::Base
  self.table_name = "tests"

  belongs_to :project

end

class Test < BaseTest
  belongs_to :super_test, class_name: "SuperTest", foreign_key: "test_id"
  ...
end

class SuperTest < BaseTest
  has_many :tests, class_name: "Test", dependent: :destroy, foreign_key: "test_id"
  ...
end


class Project < ActiveRecord::Base
  has_many :tests, dependent: :destroy
  has_many :super_tests, dependent: :destroy
  ...
end

@test = Test.new(tests[:index0])
(rdb:1) tests[:index0]
{"source_project_id"=>"274", "source_branch"=>"master", "project_id"=>"108", "target_branch"=>"master"}

(rdb:1) @test.project

这个是能找到对应的 project 的

但是对于

@super_test = SuperTest.new(submodule_tests[:index0])
(rdb:1) @super_test .project
nil

另外,是否需要在 routes.rb 中增加 resources :super_tests?

补充: 跟了下代码,发现@super_test = SuperTest.new(submodule_tests[:index0]) 之后,@super_test的 project_id 字段还是 nil,所以@super_test.project也是 nil

[6, 15] in ruby/1.9.1/gems/activemodel-3.2.11/lib/active_model/mass_assignment_security/sanitizer.rb
   6        def initialize(target=nil)
   7        end
   8  
   9        # Returns all attributes not denied by the authorizer.
   10        def sanitize(attributes, authorizer)
=> 11          sanitized_attributes = attributes.reject { |key, value| authorizer.deny?(key) }
   12          debug_protected_attribute_removal(attributes, sanitized_attributes)
   13          sanitized_attributes
   14        end

11 行 authorizer.deny?(key) 返回的都是 true,现在不明白为什么是 true,这个地方导致 sanitized_attributes 为 nil,所以最终赋值为 nil;

[24, 33] in  ruby/1.9.1/gems/activemodel-3.2.11/lib/active_model/mass_assignment_security/permission_set.rb
   24      end
   25  
   26      class WhiteList < PermissionSet
   27  
   28        def deny?(key)
=> 29          !include?(key)
   30        end
   31      end

结论:原来放在 Test 中的 attr_accessible 没有移到新增的基类中,所以导致字段赋值失败;

  1. 你定义了 @super_test ,但是使用了 @test ruby @super_test = SuperTest.new(submodule_tests[:index0]) (rdb:1) @test.project nil
  2. routes.rb 要不要使用 resources :super_tests 看你需不需要 controllers 跟你增加了一个 SuperTest Model 没关系
  3. (纯吐槽) 几个月后你真的搞的清楚这几个 Model 的关系吗?

楼主,慎用 sti,后期维护特别头大

有时候多态是个更好的替代方案。

http://railscasts.com/episodes/394-sti-and-polymorphic-associations

#1 楼 @zlx_star 上面是我的笔误,@super_test .project 也是返回 nil

结论:原来放在 Test 中的 attr_accessible 没有移到新增的基类中,所以导致字段赋值失败;移到基类中就 OK 了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号