หลายคนในชุดข้อความนี้และบน google อธิบายได้ดีมากซึ่งattr_accessibleระบุรายการที่อนุญาตของแอตทริบิวต์ที่ได้รับอนุญาตให้อัปเดตเป็นกลุ่ม ( คุณลักษณะทั้งหมดของรูปแบบวัตถุพร้อมกันในเวลาเดียวกัน ) เป็นส่วนใหญ่ (และเท่านั้น) เพื่อปกป้องแอปพลิเคชันของคุณ จากการใช้ประโยชน์จากโจรสลัด "การมอบหมายจำนวนมาก"
นี่คือคำอธิบายที่นี่ในเอกสารทางรถไฟอย่างเป็นทางการ: การมอบหมายจำนวนมาก
attr_accessorเป็นรหัสทับทิมเพื่อ (อย่างรวดเร็ว) สร้างเมธอดและทะเยอทะยานในคลาส นั่นคือทั้งหมดที่
ตอนนี้สิ่งที่ขาดหายไปตามคำอธิบายก็คือเมื่อคุณสร้างลิงก์ระหว่างโมเดล (Rails) กับตารางฐานข้อมูลคุณไม่จำเป็นไม่จำเป็นต้องใช้attr_accessorโมเดลของคุณในการสร้าง setters และ getters เพื่อที่จะสามารถปรับเปลี่ยน บันทึกของตาราง
นี่เป็นเพราะโมเดลของคุณสืบทอดวิธีการทั้งหมดจากActiveRecord::BaseClass ซึ่งกำหนด accessors CRUD พื้นฐาน (สร้าง, อ่าน, อัปเดต, ลบ) ให้คุณแล้ว นี่คือคำอธิบายในเอกสารอย่างเป็นทางการที่นี่Rails Modelและที่นี่การเขียนทับค่าเริ่มต้น accessor (เลื่อนลงไปที่บท "Overwrite default accessor")
พูดเช่น: เรามีตารางฐานข้อมูลชื่อ "ผู้ใช้" ที่มีสามคอลัมน์ "ชื่อ", "นามสกุล" และ "บทบาท":
คำแนะนำ SQL:
CREATE TABLE users (
  firstname string,
  lastname string
  role string
);
ฉันสันนิษฐานว่าคุณตั้งค่าตัวเลือกconfig.active_record.whitelist_attributes = trueใน config / environment / production.rb เพื่อป้องกันแอปพลิเคชันของคุณจากการใช้ประโยชน์จากการมอบหมายจำนวนมาก นี่คือคำอธิบายที่นี่: การมอบหมายจำนวนมาก
โมเดล Rails ของคุณจะทำงานกับ Model ได้อย่างสมบูรณ์ด้านล่าง:
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 ของคุณ:
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รายการเนื่องจากคุณจะไม่ให้ผู้ใช้กำหนดบทบาทของตนเอง (เช่นผู้ดูแลระบบ) คุณทำสิ่งนี้ด้วยตัวคุณเองบนมุมมองผู้ดูแลระบบพิเศษอื่น
แม้ว่ามุมมองผู้ใช้ของคุณจะไม่แสดงฟิลด์ "บทบาท" แต่โจรสลัดอาจส่งคำขอ HTTP POST ที่รวมถึง "บทบาท" ในแฮช params ได้อย่างง่ายดาย แอตทริบิวต์ "role" ที่หายไปattr_accessibleคือการปกป้องแอปพลิเคชันของคุณ
คุณยังคงสามารถแก้ไขแอตทริบิวต์ user.role ของคุณเองได้เหมือนด้านล่าง แต่ไม่สามารถใช้ร่วมกับแอตทริบิวต์ทั้งหมดได้
@user.role = DEFAULT_ROLE
ทำไมนรกคุณจะใช้attr_accessor?
ในกรณีนี้ผู้ใช้ของคุณจะแสดงเขตข้อมูลที่ไม่มีอยู่ในตารางผู้ใช้ของคุณเป็นคอลัมน์
ตัวอย่างเช่นสมมติว่ามุมมองผู้ใช้ของคุณแสดงฟิลด์ "Please-tell-the-admin-that-I'm-in-here" คุณไม่ต้องการจัดเก็บข้อมูลนี้ในตารางของคุณ คุณเพียงแค่ต้องการให้ Rails ส่งอีเมลเตือนคุณว่ามีผู้ใช้ "คนบ้า" ;-) สมัครรับข้อมูล
เพื่อให้สามารถใช้ประโยชน์จากข้อมูลนี้ได้คุณจะต้องเก็บมันไว้ชั่วคราว อะไรจะง่ายไปกว่าการกู้คืนในuser.peekabooแอตทริบิวต์
ดังนั้นคุณเพิ่มฟิลด์นี้ในโมเดลของคุณ:
class User < ActiveRecord::Base
  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo
end
ดังนั้นคุณจะสามารถใช้user.peekabooคุณสมบัติที่มีการศึกษาเพื่อควบคุมการส่งอีเมลหรือทำสิ่งที่คุณต้องการ
ActiveRecord จะไม่บันทึกแอตทริบิวต์ "peekaboo" ในตารางของคุณเมื่อคุณทำuser.saveเพราะเธอไม่เห็นคอลัมน์ใด ๆ ที่ตรงกับชื่อนี้ในรูปแบบของเธอ
               
              
attr_accessorใช้ในการสร้างวิธีการทะเยอทะยานและ Setter โปรดดูคำตอบของฉันสำหรับคำถามก่อนหน้านี้สำหรับคำอธิบายที่ครอบคลุมมากของattr_accessible: stackoverflow.com/questions/2652907/ …จากนั้นอัปเดตคำถามของคุณหากคุณต้องการรายละเอียดเฉพาะอื่น ๆ หลังจากนั้น