web-dev-qa-db-ja.com

「警告:保護された属性を大量に割り当てることはできません」

RESTful手法を使用してモデルを生成し(実際、Devise gemを使用しています)、first_nameおよびlast_nameという新しいフィールドをモデルに追加しました。移行はうまくいきました。 attr_accessor:first_name、:last_nameをモデルに追加し、それが機能することを期待しました。しかし、Doctor.create({:first_name => "MyName"})などで新しいインスタンスを一括割り当てしようとすると、保護された属性を一括割り当てできないというエラーが表示されます。

Attr_accessorを使用するすべてのポイントは、モデルのフィールドの保護を回避することだと思いました。このメッセージを理解してもらえますか?

編集:ああ、レコードも作成されません。これは単なる警告であるため、そうすべきだと思いましたが、データベースにはありません。

Edit2:これは私のモデルです

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

スキーマ。first_nameとlast_nameは、usersテーブル(医師の祖先)で作成されるため、これらはありません。単一のテーブル継承を使用しました。

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

  t.timestamps
end

これはユーザーテーブルを変更するための移行です

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

編集:これはシードファイルです。 truncate_db_tableメソッドは含まれていませんが、機能します。

%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")
67
picardo

混同しないでくださいattr_accessor with attr_accessible。アクセサーはRubyに組み込まれ、ゲッターメソッドを定義します-model_instance.foo # returns something-およびセッターメソッド-model_instance.foo = 'bar'

AccessibleはRailsで定義され、属性を一括割り当て可能にします(attr_protected)。

first_nameはモデルのデータベーステーブル内のフィールドであり、Railsはその属性のゲッターとセッターを既に定義しています。必要なのはattr_accessible :first_name

140
Robert Speicher

プロダクションモードにはまったく適さない安全でない方法でアプリを一緒にハックするには:

/config/application.rbに移動します

{config.active_record.whitelist_attributes = true}

Falseに設定します。

EDIT/btw(11週間のワークショップを含む4か月のRuby集中作業の後):DHHは、noobiesの場合(彼の言葉)、「稼働中」は「非常に安全」よりも重要であると考えています。

アドバイス:経験豊富な多くのRails開発者はnotこれをやりたいと思うことに非常に情熱を感じています。

更新:3年後、これを行う別の方法-再び、安全ではありませんが、おそらく各モデルで行う必要があるため、上記のソリューションよりも優れています

class ModelName < ActiveRecord::Base
  column_names.each do |col|
    attr_accessible col.to_sym
  end
  ...
end
11
boulder_ruby

ここではattr_accessorを使用しないでください。 ActiveRecordは、モデル上でそれらを自動的に作成します。また、検証エラーまたは一括割り当てエラーがスローされた場合、ActiveRecordはレコードを作成しません。

編集:あなたは医師のテーブルを必要としない、あなたはRails Single Table Inheritance を処理するためのtype列を持つusersテーブルが必要です。招待はユーザーにありますああ、私はあなたがユーザーにタイプを持っているあなたの追加されたコードサンプルを見ます。医師のテーブルを取り除き、ユーザーに招待を移動し、あなたは大丈夫だと思います。またattr_accessorも取り除きます。

Rails STIは特定のモデルのすべてのクラスとサブクラスに同じテーブルを使用します。すべてのDoctorレコードは、 'doctor'タイプのusersテーブルの行になります。

編集:また、更新ではなく、作成時の招待の存在のみを検証しますか?

2
Dave Sims

追加 attr_accessible : variable1, variable2テーブルルートファイルに。

2
Aneez

@Robert Speicherの回答に同意しますが、大量の割り当てから保護するには、attr_accessibleの代わりに Strong parameter を使用することを強くお勧めします。

乾杯!

0

個々のコールの一括割り当て保護を無効にする場合(ただし、グローバルに無効にする場合)、:without_protection => trueオプションを使用できます。これは、移行や、ハッシュのキー/値がハードコードされているか、安全であることがわかっている他の場所で役立ちます。

ここの例(Rails 3.2でも動作します): https://apidock.com/Rails/v3.1.0/ActiveRecord/Base/create/class

0
Kyle McClellan