attr_accessorとattr_accessibleの違い


235

Railsでは、違いは何であるattr_accessorとはattr_accessible?私の理解では、をattr_accessor使用してその変数のゲッターメソッドとセッターメソッドを作成し、Object.variableまたはのような変数にアクセスできるようにしますObject.variable = some_value

私はそれを読んでattr_accessible、その特定の変数を外の世界にアクセスできるようにします。誰かが違いを教えてください


4
attr_accessorgetterメソッドとsetterメソッドの生成に使用されているのはあなたです。かなり包括的な説明については、前の質問に私の答えを参照してくださいattr_accessiblestackoverflow.com/questions/2652907/...あなたはその後、他の特定の詳細を必要とするならば、あなたの質問を更新します。
mikej

2
attr_accessibleあなたがするトップの答えに従って、protected_attributesの宝石を使用しない限り、もはやレール4でサポートされてstackoverflow.com/questions/17371334/...(2014年7月)
エメリー

回答:


258

attr_accessorゲッターとセッターを作成するRubyメソッドです。attr_accessibleは、値を一括割り当てに渡すことができるRailsメソッドです:new(attrs)またはupdate_attributes(attrs)

ここに大量の割り当てがあります:

Order.new({ :type => 'Corn', :quantity => 6 })

たとえば、注文に割引コードが含まれていると想像できます:price_off。あなたがタグをしない場合:price_offattr_accessibleそうのように行うことができることから、悪質なコードを停止します。

Order.new({ :type => 'Corn', :quantity => 6, :price_off => 30 })

フォームにのフィールドがなくても、フォームが:price_offモデルにある場合は、デフォルトで使用できます。これは、細工されたPOSTがそれを設定できることを意味します。attr_accessibleホワイトを使用すると、一括割り当てできるものがリストされます。


2
attr_accessibleRailsのドキュメントにないのはなぜですか?api.rubyonrails.org
Chloe

19
Rails4には新しい方法があるようです。:この回答を参照してくださいstackoverflow.com/questions/17371334/...
ポール・ルベル

1
強いパラメータがattr_accessible edgeguides.rubyonrails.org/…の
Imran Ahmad

173

このスレッドとグーグルの多くの人々はattr_accessible、一括で更新できる属性のホワイトリストを指定することを非常によく説明しています(同時にオブジェクトモデルのすべての属性)これは主に(そして唯一)アプリケーションを保護するためです「大量の割り当て」からの海賊の悪用。

これについては、Railsの公式ドキュメント:Mass Assignmentで説明しています。

attr_accessorクラスにセッターメソッドとゲッターメソッドを(すばやく)作成するRubyコードです。それで全部です。

(Rails)モデルとデータベーステーブルの間のリンクを何らかの方法で作成するときattr_accessorに、モデルを変更できるようにするために、モデルにセッターとゲッターを作成する必要はありません。テーブルのレコード。

これは、モデルが、ActiveRecord::Base基本的なCRUDアクセサー(作成、読み取り、更新、削除)を既に定義しているクラスからすべてのメソッドを継承するためです。これは、こちらのRailsモデルとこちらのデフォルトのアクセサの上書きの公式ドキュメントで説明されています(「デフォルトのアクセサの上書き」の章までスクロールしてください)

たとえば、「users」というデータベーステーブルがあり、「firstname」、「lastname」、「role」の3つの列があるとします。

SQL指示:

CREATE TABLE users (
  firstname string,
  lastname string
  role string
);

私はconfig.active_record.whitelist_attributes = true、あなたがconfig / environment / production.rbでオプションを設定して、アプリケーションを大量割り当ての悪用から保護することを想定しました。これはここで説明されています:一括割り当て

Railsモデルは、以下のモデルと完全に連携します。

class User < ActiveRecord::Base

end

ただし、フォームのビューを機能させるには、コントローラーでユーザーの各属性を個別に更新する必要があります。

def update
    @user = User.find_by_id(params[:id])
    @user.firstname = params[:user][:firstname]
    @user.lastname = params[:user][:lastname]

    if @user.save
        # Use of I18 internationalization t method for the flash message
        flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
    end

    respond_with(@user)
end

さて、あなたの人生を楽にするために、あなたはユーザーモデルのために複雑なコントローラーを作りたくないでしょう。したがってattr_accessible、クラスモデルで特別なメソッドを使用します。

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname

end

したがって、「ハイウェイ」(質量割り当て)を使用して更新できます。

def update
    @user = User.find_by_id(params[:id])

    if @user.update_attributes(params[:user])
        # Use of I18 internationlization t method for the flash message
        flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
    end

    respond_with(@user)
end

に「ロール」属性を追加しなかった attr_accessibleユーザーが自分でロール(adminなど)を設定できないようにするためリストに。これは、別の特別な管理ビューで自分で行います。

ユーザービューには「ロール」フィールドは表示されませんが、海賊版はparamsハッシュに「ロール」を含むHTTP POSTリクエストを簡単に送信できます。に欠落している「役割」属性attr_accessibleアプリケーションをそれから保護するためのものです。

以下のように、user.role属性を単独で変更することはできますが、すべての属性を一緒に変更することはできません。

@user.role = DEFAULT_ROLE

なぜ地獄を使うのattr_accessorですか?

これは、ユーザーフォームにユーザーテーブルに存在しないフィールドが列として表示されている場合です。

たとえば、ユーザービューに「管理者に連絡してください」というフィールドが表示されているとします。この情報をテーブルに保存したくありません。Railsから、「クレイジー」な1人のユーザーがサブスクライブしたことを警告する電子メールを送信してほしいだけです。

この情報を利用するには、一時的にどこかに保存する必要があります。でそれを回復するよりも簡単user.peekaboo属性でですか?

したがって、このフィールドをモデルに追加します。

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo

end

だからあなたは教育を受けた使用をすることができるでしょう user.peekabooコントローラーのどこかで属性して、電子メールを送信したり、必要なことを行うことができます。

ActiveRecordは、「peekaboo」属性をテーブルに保存しuser.saveません。モデルにこの名前に一致する列が表示されないためです。


48

attr_accessor同じ名前のインスタンス変数にセッターメソッドとゲッターメソッドを提供するRubyメソッドです。ですから、

class MyModel
  def my_variable
    @my_variable
  end
  def my_variable=(value)
    @my_variable = value
  end
end

attr_accessible 一括割り当てで設定できる変数を決定するRailsメソッドです。

フォームを送信すると、次のようなものがあります MyModel.new params[:my_model]場合は、もう少し細かく制御して、ユーザーが望まないものを送信できないようにします。

attr_accessible :email誰かが自分のアカウントを更新したときに、彼らが自分のメールアドレスを変更できるようにするかもしれません。しかし、あなたはしませんattr_accessible :email, :salary、その人はフォームの提出を通じて給与を設定できるので、。言い換えれば、彼らは昇給への道をハックすることができました。

この種の情報は明示的に処理する必要があります。フォームから削除するだけでは不十分です。誰かがfirebugを使用して要素をフォームに追加し、給与フィールドを送信できます。ビルトインのcurlを使用して、コントローラーのupdateメソッドに新しい給与を送信し、その情報を含む投稿を送信するスクリプトを作成できます。

そう attr_accessor変数を格納するためのメソッドを作成する程度であり、attr_accessible質量割り当てのセキュリティについてです。


2
あなたはタイプミスを持っています、コードブロックの後にそれは言うべきですattr_accesible
Chubas

すばらしい記事です。クラスの例が好きです。の説明を含むための余分な(偽の)ボーナスポイント:as
Ian Vaughan

モデルはActiveRecord :: Baseによって拡張されます。class User < ActiveRecord::Base
Green

18

attr_accessorrubyコードであり、データベースに列がなくてもフォームにフィールドを表示したい場合に使用されます。これを可能にする唯一の方法はattr_accessor :fieldnameあり、必要に応じてビューまたはモデルでこのフィールドを使用できますが、ほとんどの場合はビューで使用します。

次の例を考えてみましょう

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end

ここでは、目的にアクセスするためにattr_reader読み取り可能な属性)とattr_writer書き込み可能な属性)を使用しています。しかし、を使用して同じ機能を実現できattr_accessorます。つまり、attr_accessorは、getterメソッドとsetterメソッドの両方へのアクセスを提供します。

変更されたコードは次のとおりです

class Address
    attr_accessor :street  
    def initialize
        @street = ""
    end
end

attr_accessible一括割り当てを許可するすべての列を一覧表示できます。これとは逆ですattr_protected。つまり、このフィールドでは、誰にも一括割り当てを許可しないでください。多くの場合、それはデータベース内のフィールドになり、だれもがぶらぶらしたくはありません。ステータスフィールドなど。


2
それで、マイグレーションでフィールドを作成し、attr_accessibleを使用してそれらを使用可能にした場合、ゲッターとセッターを作成する必要がないと言っているのですか?しかし、フィールドがデータベース内にない場合、attr_accessibleがgetter / setterのように機能しないのはなぜですか?「has_secure_password」という行を含めると、attr_accessibleは、getter / setterが:passwordおよび:password_confirmationをデータベースになくても十分に使用できるようになります。非常に混乱しています;)
2012


2

すばやく簡潔な違いの概要:

attr_accessorクラスで読み取りおよび書き込みアクセサーを作成する簡単な方法です。データベースに列がなくてもフォームにフィールドを表示したい場合に使用します。このフィールドは “virtual attribute”Railsモデルのです。

仮想属性 –データベースの列に対応しない属性。

attr_accessible は、コントローラーメソッドからアクセス可能な属性を識別するために使用され、プロパティを一括割り当てできるようにします。指定した属性へのアクセスのみが許可され、残りは拒否されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.