Rails - sử dụng loại cột không có STI?


81

Tôi muốn sử dụng một cột được gọi typemà không gọi Kế thừa Bảng Đơn (STI) - Tôi chỉ muốn typelà một cột bình thường chứa a String.

Làm thế nào tôi có thể làm điều này mà không cần Rails mong đợi tôi có thừa kế bảng duy nhất và ném một ngoại lệ The single-table inheritance mechanism failed to locate the subclass...This error is raised because the column 'type' is reserved for storing the class in case of inheritance.?

Có ý tưởng nào để làm việc này không?

Câu trả lời:


134

Trong Rails 3.1 set_inheritance_columnkhông được dùng nữa, bạn cũng có thể sử dụng nillàm tên, như sau:

class Pancakes < ActiveRecord::Base
    self.inheritance_column = nil
    #...
end

Trên thực tế, có vẻ như điều đó đã thay đổi rails 3.2. Theo apidock : 'Phương pháp này không được chấp nhận hoặc chuyển sang phiên bản ổn định mới nhất. Phiên bản hiện có cuối cùng (v3.1.0) được hiển thị ở đây. ' Cảm ơn các mẹo mặc dù!
Batkins

Nó được tán thành trong 3.1 và loại bỏ trong 3.2, tôi nghĩ
Valentin Nemcev

2
@Batkins Người inheritance_columnđọc bị di chuyển (do đó thông báo "không được chấp nhận hoặc đã di chuyển"). Việc sử dụng đặt inheritance_columntrực tiếp biến phiên bản là có chủ đích và không bị phản đối.
lulalala

Làm việc trong đường ray 5.1
John Bachir

21

Bạn có thể ghi đè tên cột STI bằng cách sử dụng set_inheritance_column:

class Pancakes < ActiveRecord::Base
    set_inheritance_column 'something_you_will_not_use'
    #...
end

Vì vậy, hãy chọn một số tên cột mà bạn sẽ không sử dụng cho bất kỳ thứ gì và cung cấp cho nó set_inheritance_column.


2
tôi có cần thực sự tạo cột đã nói trong cơ sở dữ liệu của mình không?
Kvass

Cảm ơn bạn, điều này đã làm việc. Một khuôn khổ KHÔNG BAO GIỜ nên !!!!! KHÔNG BAO GIỜ!!!! ra lệnh cho trường bảng không thể được đặt tên. Điều đó thật tệ đối với các tập dữ liệu kế thừa.
Jon

5
@Jon: Rails không thực sự quan tâm đến dữ liệu cũ hay chơi đẹp với những người khác, Rails có thái độ quá đáng với điều đó. Bạn có thể làm cho nó tự hoạt động với một số nỗ lực nhưng cuối cùng bạn luôn phải chiến đấu một chút nếu bạn cần làm điều gì đó mà Rails chưa lên kế hoạch (tiếc là bao gồm nhiều khái niệm cơ sở dữ liệu cơ bản). OTOH, tôi là một kẻ dị giáo chuyên nghiệp nên Rails người khác chắc chắn sẽ khó chịu với tôi đã chỉ ra những vấn đề tư tưởng :)
mu quá ngắn

10
Tôi nghĩ ý tưởng là Rails / Ruby thích quy ước hơn cấu hình, vì vậy họ cố gắng tối ưu hóa nó cho các trường hợp sử dụng mà họ cảm thấy là đúng.
Ibrahim

21

Tôi biết câu hỏi này khá cũ và điều này hơi lệch so với câu hỏi bạn đang hỏi, nhưng điều tôi luôn làm bất cứ khi nào tôi cảm thấy thôi thúc đặt tên cho một loại cột hoặc một cái gì đó_type là tôi tìm kiếm một từ đồng nghĩa của loại và sử dụng nó thay thế:

Dưới đây là một số lựa chọn thay thế: loại, sắp xếp, đa dạng, danh mục, bộ, thể loại, loài, thứ tự, v.v.


10

Đường ray 4.x

Tôi đã gặp sự cố trong một Rails 4ứng dụng, nhưng trong Rails 4 , set_inheritance_columnphương thức này hoàn toàn không tồn tại nên bạn không thể sử dụng nó.

Các giải pháp mà làm việc cho tôi là để vô hiệu hóa các thừa kế bảng duy nhất bằng cách ghi đè ActiveRecord's inheritance_columnphương pháp, như thế này:

class MyModel < ActiveRecord::Base

  private

  def self.inheritance_column
    nil
  end

end

Hy vọng nó giúp!


8
Phiên bản đơn giản: class MyModel < ActiveRecord::Base self.inheritance_column = nil end. Tham khảo: apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/…
Benj

1
Làm việc cho tôi trong đường ray 4.2.2. Có lẽ bạn đã không khởi động lại máy chủ hoặc mùa xuân sau khi thực hiện thay đổi?
Benj

1
Và những người dùng khác có thể thấy hữu ích với phiên bản đơn giản hơn mà tôi đã nhận xét. Đối với vấn đề tải lại, tôi không phải là chuyên gia nhưng sẽ có ý nghĩa đối với tôi nếu thuộc tính lớp không tự động tải lại mà không cần dỡ và tải lại định nghĩa lớp.
Benj

2
Tôi không hiểu phản ứng của bạn, tôi chỉ đang cố gắng bổ sung hữu ích cho câu trả lời của bạn. Tại sao bạn cảm thấy bị xúc phạm? Tôi đến trong hòa bình
Benj

2
@Benj Có vẻ như họ đã xóa bất kỳ (các) nhận xét nào mà bạn đang đề cập đến nên bây giờ có vẻ như bạn đang tranh cãi với chính mình. ;)
Joshua Pinter

0

Nếu bạn muốn thực hiện việc này cho tất cả các kiểu máy, bạn có thể gắn nó vào trình khởi tạo.

ActiveSupport.on_load(:active_record) do
  class ::ActiveRecord::Base
    # disable STI to allow columns named "type"
    self.inheritance_column = :_type_disabled
  end
end

Hoặc tốt hơn - trong ApplicationRecord .
Alexander
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.