Attr_accessor ve attr_accessible arasındaki fark


235

Rails'te attr_accessorve arasındaki fark attr_accessiblenedir? Anladığım kadarıyla, kullanma attr_accessorbu değişken için alıcı ve ayarlayıcı yöntemleri oluşturmak için kullanılır, böylece Object.variableveya gibi değişkene erişebiliriz Object.variable = some_value.

Bu attr_accessibledeğişkenin dış dünya tarafından erişilebilir olmasını sağladım. Birisi bana farkın ne olduğunu söyleyebilir mi?


4
attr_accessorGetter ve setter yöntemleri oluşturmak için kullanılan haklısınız . Oldukça kapsamlı bir açıklama için lütfen bir önceki soruya verdiğim cevaba bakın attr_accessible: stackoverflow.com/questions/2652907/… daha sonra başka spesifik ayrıntılara ihtiyacınız varsa sorunuzu güncelleyin.
mikej

2
stackoverflow.com/questions/17371334/… (Temmuz 2014) için en iyi yanıta göre, korunan_attributes gemini kullanmadığınız sürece attr_accessible artık Rails 4'te desteklenmemektedir
emery

Yanıtlar:


258

attr_accessorbir alıcı ve ayarlayıcı yapan Ruby yöntemidir. attr_accessible, değerleri bir toplu atamaya geçirmenize izin veren bir Rails yöntemidir: new(attrs)veya update_attributes(attrs).

İşte toplu bir ödev:

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

Siparişin bir indirim koduna da sahip olabileceğini düşünebilirsiniz :price_off. Etiketi yoksa :price_offolduğu gibi attr_accessiblebunu sevmiyorum edememek kötü niyetli kod durdurulur:

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

Formunuz için bir alan :price_offolmasa bile, modelinizde varsa varsayılan olarak kullanılabilir. Bu, hazırlanmış bir POST'un yine de ayarlayabileceği anlamına gelir. Kullanılması attr_accessiblebeyaz listeleri kitle atanabilir böyle şeyler.


2
Neden attr_accessibleRails belgelerinde yok? api.rubyonrails.org
Chloe

19
Görünüşe göre Rails4 bir şeyler yapmak için yeni bir yol var. Bu yanıta bakın: stackoverflow.com/questions/17371334/…
Paul Rubel

1
Çünkü güçlü parametre attr_accessible edgeguides.rubyonrails.org/… '
İmran Ahmad

173

Bu iş parçacığı ve Google'daki birçok kişi, attr_accessibletoplu olarak güncellenmesine izin verilen özelliklerin bir beyaz listesini (bir nesne modelinin tüm özellikleri aynı anda bir arada) belirten çok iyi açıklıyor ) Bu, uygulamanızı korumak için temel olarak (ve yalnızca) "Toplu görev" korsan sömürüsünden.

Bu, burada resmi Rails belgesinde açıklanmıştır: Toplu Atama

attr_accessorbir Sınıfta ayarlayıcı ve alıcı yöntemleri (hızlı bir şekilde) oluşturmak için bir yakut koddur. Bu kadar.

Şimdi, açıklama olarak eksik olan şey, bir veritabanı tablosuyla bir (Rails) modeli arasında bir şekilde bir bağlantı oluşturduğunuzda, ASLA, ASLA, ASLA ihtiyacınız yoktur. attr_accessor , modelinizde değişiklik yapabilmek için seterler ve alıcılar oluşturmak için . tablonun kayıtları.

Bunun nedeni, modelinizin sizin için ActiveRecord::Basetemel CRUD erişimcilerini (Oluşturma, Okuma, Güncelleme, Silme) zaten tanımlayan tüm yöntemleri Sınıftan devralmasıdır. Bu resmi doc burada açıklanmıştır Raylar Modeli burada ve varsayılan erişimci üzerine yazma (bölüm "Üzerine Yaz varsayılan erişimci" na inin)

Örneğin şunu söyleyin: "firstname", "lastname" ve "role" sütunlarından oluşan "users" adlı bir veritabanı tablonuz var:

SQL talimatları:

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

config.active_record.whitelist_attributes = trueUygulamanızı Toplu atama istismarından korumak için config / environment / production.rb dosyasındaki seçeneği ayarladığınızı varsaydım . Bu burada açıklanmaktadır: Toplu Atama

Rails modeliniz aşağıdaki Model ile mükemmel şekilde çalışacaktır:

class User < ActiveRecord::Base

end

Ancak, formunuzun Görünümünün çalışması için her bir kullanıcı özelliğini denetleyicinizde ayrı olarak güncellemeniz gerekir:

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

Artık hayatınızı kolaylaştırmak için Kullanıcı modeliniz için karmaşık bir denetleyici yapmak istemezsiniz. attr_accessibleSınıf modelinizde özel yöntemi kullanacaksınız :

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname

end

Böylece güncellemek için "otoyol" (toplu atama) kullanabilirsiniz:

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

"Rol" özelliklerini attr_accessible listeye çünkü kullanıcılarınızın rollerini kendileri (yönetici gibi) belirlemelerine izin vermezsiniz. Bunu başka bir özel Yönetici Görünümünde kendiniz yaparsınız.

Kullanıcı görünümünüzde bir "rol" alanı görünmese de, bir korsan params karmasına "rol" içeren bir HTTP POST isteği gönderebilir. Üzerindeki eksik "rol" özelliğiattr_accessible uygulamanızı bundan korumaktır.

Yine de user.role özniteliğinizi aşağıdaki gibi kendi başınıza değiştirebilirsiniz, ancak tüm özniteliklerle birlikte değiştiremezsiniz.

@user.role = DEFAULT_ROLE

Neden cehennemi kullanıyorsun attr_accessor?

Bu, kullanıcı formunuzun, kullanıcılar tablonuzda bir sütun olarak bulunmayan bir alanı göstermesi durumunda olur.

Örneğin, kullanıcı görünümünüzün "burada olduğumuzu lütfen söyleyin" alanını gösterdiğini varsayalım. Bu bilgileri masanızda saklamak istemezsiniz. Sadece Rails size bir "çılgın" ;-) kullanıcı abone olduğunu size bir e-posta göndermek istiyorum.

Bu bilgileri kullanabilmek için geçici olarak bir yerde saklamanız gerekir. Bir user.peekabooözellikte kurtarmaktan daha kolay ne olabilir ?

Böylece bu alanı modelinize eklersiniz:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo

end

Böylece user.peekaboo, e-posta göndermek veya istediğinizi yapmak için kumandanızdaki bir yerde bu özelliği eğitimli bir şekilde kullanabilirsiniz .

ActiveRecord, user.savemodelinde bu adla eşleşen hiçbir sütun görmediğinden , yaptığınızda "peekaboo" özniteliğini tablonuza kaydetmez .


48

attr_accessoraynı ada sahip bir örnek değişkenine ayarlayıcı ve alıcı yöntemleri veren bir Ruby yöntemidir. Yani eşdeğer

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

attr_accessible kütle atamasında hangi değişkenlerin ayarlanabileceğini belirleyen bir Rails yöntemidir.

Bir form gönderdiğinizde ve MyModel.new params[:my_model] sahip olduğunuzda, insanların daha fazla kontrol sahibi olmasını istersiniz, böylece insanlar sizin istemediğiniz şeyleri gönderemez.

Sen yapabilir attr_accessible :emailbirileri onların hesabını güncelleyen, onlar kendi e-posta adresini değiştirmek, böylece. Ama yapmazsınız attr_accessible :email, :salaryçünkü o zaman bir kişi maaşını form göndererek ayarlayabilir. Başka bir deyişle, zam yapmak için yollarını kesebilirler.

Bu tür bilgilerin açıkça ele alınması gerekir. Sadece formdan kaldırmak yeterli değildir. Birisi kundakçı ile gidip maaş alanı göndermek için öğeyi forma ekleyebilir. Denetleyici güncelleme yöntemine yeni bir maaş göndermek için yerleşik kıvrımı kullanabilirler, bu bilgilerle bir gönderi gönderen bir komut dosyası oluşturabilirler.

Yani attr_accessormağaza değişkenlere yöntemleri oluşturma hakkında olduğunu ve attr_accessiblekitle atamaları güvenliği ile ilgili.


2
Bir yazım hatası var, kod bloğundan sonra şunu söylemeliattr_accesible
Chubas

Harika bir yazım, sınıf örneğini seviyorum. Bir açıklama eklemek için ekstra (sahte) bonus puanlar :as!
Ian Vaughan

Model ActiveRecord :: Base tarafından genişletildi. class User < ActiveRecord::Base
Yeşil

18

attr_accessoryakut kodudur ve veritabanınızda sütun bulunmadığında, ancak yine de formlarınızda bir alan göstermek istediğinizde kullanılır. Buna izin vermenin tek yolu, attr_accessor :fieldnamebu alanı Görünümünüzde veya modelinizde, ancak çoğunlukla Görünümünüzde kullanabilirsiniz.

Aşağıdaki örneği ele alalım

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

Burada erişime yönelik attr_reader( okunabilir özellik ) ve attr_writer( yazılabilir özellik ) kullandık. Ancak aynı işlevselliği kullanarak elde edebiliriz attr_accessor. Kısacası, attr_accessor hem alıcı hem de ayarlayıcı yöntemlerine erişim sağlar.

Yani değiştirilmiş kod aşağıdaki gibidir

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

attr_accessibleToplu Atamaya izin vermek istediğiniz tüm sütunları listelemenizi sağlar. Bunun tersi, bu attr_protectedalanın Kitle Atamasına kimsenin izin vermesini istemediğim anlamına gelir. Büyük olasılıkla veritabanınızda kimsenin dolaşmasını istemediğiniz bir alan olacaktır. Bir durum alanı veya benzeri gibi.


2
Bir geçişte alanlar oluşturduysam, bunları attr_accessible kullanarak kullanılabilir hale getirirsem, bir alıcı ve ayarlayıcı oluşturmanıza gerek olmadığını mı söylüyorsunuz? Ancak alan veritabanında değilse, nasıl olur attr_accessible bir alıcı / ayarlayıcı gibi davranmaz? Bir satır "has_secure_password" eklerseniz, attr_accessible, veritabanında olmasalar bile getter / setter: password ve: password_confirmation işlemlerine izin vermek için yeterli olur. Çok karıştı;)
tentimes

2

İki kelimeyle:

attr_accessorolduğu getter, setteryöntemi. oysa attr_accessiblebelirli bir özelliğin erişilebilir ya da erişilebilir olmadığını söylemek. bu kadar.


Eklemek istiyorum , kitlesel atamadan korumak için Güçlü parametresini kullanmalıyız attr_accessible.

Şerefe!


2

Hızlı ve özlü bir farka genel bakış:

attr_accessorsınıfınızda okuma ve yazma erişimcisi oluşturmanın kolay bir yoludur. Veritabanınızda bir sütun olmadığında, ancak yine de formlarınızda bir alan göstermek istediğinizde kullanılır. Bu alan “virtual attribute”bir Rails modelindedir.

sanal özellik - veritabanındaki bir sütuna karşılık gelmeyen bir özellik.

attr_accessible denetleyici yöntemleriniz tarafından erişilebilen öznitelikleri tanımlamak için kullanılır, bir özelliği toplu atama için kullanılabilir hale getirir. Yalnızca belirttiğiniz özniteliklere erişime izin verir, geri kalanını reddeder.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.