2010-10-15 5 views
65

Tôi đã sử dụng các kỹ thuật RESTful để tạo mô hình (trên thực tế, tôi đang sử dụng đá quý Devise, điều đó cho tôi) và tôi đã thêm các trường mới gọi là first_name và last_name cho mô hình. Di chuyển đã ổn. Tôi đã thêm attr_accessor: first_name,: last_name vào mô hình và dự kiến ​​nó sẽ hoạt động. Nhưng khi tôi cố gắng đại diện cho các trường hợp mới với Doctor.create ({: first_name => "MyName"}) vv, tôi nhận được lỗi nói rằng tôi không thể gán các thuộc tính được bảo vệ theo khối lượng."CẢNH BÁO: Không thể gán số lượng lớn các thuộc tính được bảo vệ"

Tôi nghĩ rằng toàn bộ điểm sử dụng attr_accessor là để có được xung quanh sự bảo vệ của các lĩnh vực của một mô hình. Bạn có thể giúp tôi hiểu được thông điệp này không?

Chỉnh sửa: oh, và nhân tiện các bản ghi cũng không được tạo. Tôi nghĩ rằng họ nên được vì đây chỉ là một cảnh báo, nhưng họ không phải trên cơ sở dữ liệu.

Edit2: đây là mô hình của tôi

class Doctor < User 
    has_many :patients 
    has_many :prescriptions, :through=> :patients 

    validates_presence_of :invitations, :on => :create, :message => "can't be blank" 

    attr_accessor :invitations 
end 

và giản đồ, mà không có first_name và last_name vì họ được tạo ra trong bảng người dùng, đó là tổ tiên của các bác sĩ. Tôi đã sử dụng thừa kế bảng đơn.

create_table :doctors do |t| 
    t.integer :invitations 

    t.timestamps 
end 

và đây là sự di cư để thay đổi bảng người dùng

add_column :users, :first_name, :string 
add_column :users, :last_name, :string 
add_column :users, :type, :string 

EDIT: đây là file giống. Tôi không bao gồm phương thức truncate_db_table, nhưng nó hoạt động.

%w{doctors patients}.each do |m| 
    truncate_db_table(m) 
end 

Doctor.create(:invitations=>5, :email=>"[email protected]", :first_name=>"Name", :last_name=>"LastName") 
Patient.create(:doctor_id=>1, :gender=>"male", :date_of_birth=>"1991-02-24") 
+0

Tôi không hiểu lắm về Rails 4 nhưng tôi nghĩ câu hỏi này là câu hỏi Rails 3. Cấu hình mã hóa mặc định trong 'config/application.rb' trong Rails 4 là trống! –

+0

http://apidock.com/rails/ActiveRecord/Base/attr_accessible/class – shilovk

Trả lời

139

Đừng nhầm lẫn attr_accessor với attr_accessible. Accessor được xây dựng trong Ruby và định nghĩa một phương thức getter - model_instance.foo # returns something - và một phương thức setter - model_instance.foo = 'bar'.

Quyền truy cập được xác định bởi Rails và làm cho thuộc tính có thể chuyển nhượng hàng loạt (ngược lại với attr_protected).

Nếu first_name là một trường trong bảng cơ sở dữ liệu của mô hình của bạn, thì Rails đã xác định getters và setters cho thuộc tính đó. Tất cả những gì bạn cần làm là thêm attr_accessible :first_name.

+0

Bây giờ tôi nhận được lỗi "thuộc tính không xác định" trên lời mời khi tôi cào tệp hạt giống. Tôi biết tôi có lĩnh vực này trong cơ sở dữ liệu, mặc dù; nó nằm trong tệp di chuyển ... – picardo

+0

Nó nằm trong tệp di chuyển, nhưng bạn có chạy các di chuyển không? Đăng tập tin hạt giống của bạn. –

+0

Bạn đã cập nhật nội dung khác chưa? Bạn vẫn có attr_accessor trong mô hình của mình mặc dù điều đó sai. –

1

Không sử dụng attr_accessor tại đây. ActiveRecord tự động tạo các mô hình đó trên mô hình. Ngoài ra, ActiveRecord sẽ không tạo bản ghi nếu lỗi xác thực hoặc gán khối lượng được ném.

EDIT: Bạn không cần bảng bác sĩ, bạn cần bảng người dùng có cột loại để xử lý Rails Single Table Inheritance. Lời mời sẽ nằm trên bảng người dùng. Ah, tôi thấy trong mẫu mã đã thêm của bạn, bạn có loại trên người dùng. Loại bỏ bảng bác sĩ, chuyển lời mời đến người dùng và tôi nghĩ bạn nên ổn. Cũng loại bỏ attr_accessor. Không cần thiết.

Hãy nhớ rằng đường ray STI sử dụng cùng một bảng cho tất cả các lớp và lớp con của một mô hình cụ thể. Tất cả hồ sơ Bác sĩ của bạn sẽ là các hàng trong bảng người dùng có loại 'doctor'

EDIT: Ngoài ra, bạn có chắc chắn chỉ muốn xác thực sự hiện diện của lời mời khi tạo và không cập nhật không?

+0

Khi tôi không sử dụng nó, tuy nhiên, Rails nói với tôi "phương pháp không tìm thấy" như tôi đang cào các tập tin hạt giống. Tôi nên làm gì trong trường hợp đó? – picardo

+0

Bạn có thể đăng mã mẫu và công việc cào của mình không? Ngoài ra việc di chuyển đã tạo ra mô hình. Đảm bảo rằng các cột đó được tạo trong db. –

11

Để hack ứng dụng của bạn với nhau theo cách không an toàn hoàn toàn không phù hợp với chế độ sản xuất:

Đi tới/config/application.rb Cuộn xuống phía cuối nơi bạn sẽ tìm thấy

{config.active_record.whitelist_attributes = true} 

Đặt thành false.

EDIT/btw (sau 4 tháng làm việc ruby ​​chuyên sâu bao gồm một hội thảo 11 tuần): DHH tin rằng, cho noobies (lời nói của ông), "và chạy" quan trọng hơn "rất an toàn" .

ĐƯỢC TƯ VẤN: Mặc dù câu trả lời này (đầu tiên tôi dựa trên lưu lượng truy cập mà tôi nghĩ) hiện ở mức +6, thấp đến -4 trong lịch sử của nó, ý nghĩa của điều đó là rất nhiều nhà phát triển có kinh nghiệm cảm thấy rất đam mê về không phải muốn bạn làm điều này.

UPDATE: 3 năm sau, một cách khác để làm điều này - một lần nữa, không an toàn, nhưng tốt hơn so với các giải pháp trên có lẽ là bởi vì bạn phải làm điều đó cho mỗi mô hình

class ModelName < ActiveRecord::Base 
    column_names.each do |col| 
    attr_accessible col.to_sym 
    end 
    ... 
end 
+32

Đó là lời khuyên thực sự tồi tệ ngay cả với báo trước "viết mã sớm". Khi nào các nhà phát triển có cơ hội quay lại và cấu trúc lại toàn bộ ứng dụng của họ? Làm điều đó đúng từ đầu. – toxaq

+4

"ghi nhớ đây là một lỗ hổng bảo mật nhưng bạn có thể xử lý nó sau" Khi bạn có kế hoạch đối phó với nó? Sau đó, khi nó được sản xuất? Tôi vừa thêm "ý kiến ​​của bạn về attr_accessible là gì?" vào danh sách câu hỏi phỏng vấn của tôi. – toxaq

+0

Tôi có thể đề xuất chỉnh sửa để làm rõ câu trả lời của bạn không? Từ bài viết của bạn, nó không phải là hoàn toàn rõ ràng rằng giá trị mặc định là cách an toàn hơn, và thay đổi nó thành false cho phép dễ dàng truy cập vào các thuộc tính mô hình nhưng mở lỗ hổng bảo mật xấu. – Excalibur

0

Thêm attr_accessible : variable1, variable2 để bạn tệp tuyến đường bảng.

0

Đồng ý với câu trả lời @Robert Speicher Nhưng tôi thực sự khuyên bạn nên sử dụng Strong parameter thay vì attr_accessible để bảo vệ khỏi việc sắp xếp hàng loạt.

Chúc mừng!