Różnica między attr accessor a attr accessor

W Rails, jaka jest różnica między attr_accessor a attr_accessible? Z mojego zrozumienia, użycie attr_accessor jest używane do tworzenia metod getter i setter dla tej zmiennej, tak że możemy uzyskać dostęp do zmiennej jak Object.variable lub Object.variable = some_value.

Czytałem, że attr_accessible czyni tę specyficzną zmienną dostępną dla świata zewnętrznego. Czy ktoś może mi powiedzieć jaka jest różnica

Author: Jordan Running, 2010-06-28

6 answers

attr_accessor jest metodą Ruby, która tworzy getter i setter. {[3] } jest metodą Rails, która pozwala przekazać wartości do przypisania masy: new(attrs) lub update_attributes(attrs).

Oto zadanie masowe:

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

Możesz sobie wyobrazić, że zamówienie może mieć również kod rabatowy, powiedzmy :price_off. Jeśli nie oznaczysz :price_off jako attr_accessible, powstrzymasz złośliwy kod przed wykonywaniem takich czynności:

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

Nawet jeśli twój formularz nie ma pola dla :price_off, jeśli jest w twoim modelu jest dostępny przez default. Oznacza to, że spreparowany POST nadal może go ustawić. Używając białej listy attr_accessible te rzeczy, które można przypisać masowo.

 261
Author: Paul Rubel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-15 23:24:04

Wiele osób w tym wątku i w google wyjaśnia bardzo dobrze, że attr_accessible określa białą listę atrybutów, które mogą być aktualizowane zbiorczo ( wszystkie atrybuty modelu obiektowego razem w tym samym czasie ) Służy to głównie (i tylko) ochronie aplikacji przed" masowym przypisaniem " pirackiego exploita.

To jest wyjaśnione tutaj na oficjalnym Rails doc : Mass assign

attr_accessor jest kodem ruby do (szybkiego) tworzenia metod setter i getter w klasy. To wszystko.

Teraz brakuje wyjaśnienia, że kiedy tworzysz w jakiś sposób połączenie pomiędzy modelem (Rails) z tabelą bazy danych, nigdy, nigdy, nigdy nie potrzebujesz attr_accessor w swoim modelu, aby tworzyć settery i gettery, aby móc modyfikować rekordy tabeli.

Dzieje się tak dlatego, że twój model dziedziczy wszystkie metody z klasy ActiveRecord::Base, która już definiuje podstawowe Accesory CRUD (Create, Read, Update, Delete). Wyjaśniono to w oficjalnym dokumencie tutaj Rails Model i tutaj nadpisywanie domyślnego accesora (przewiń w dół do rozdziału "nadpisywanie domyślnego accesora")

Powiedzmy na przykład, że: mamy tabelę bazy danych o nazwie "users", która zawiera trzy kolumny "firstname", "lastname" i "role":

Instrukcje SQL:

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

Założyłem, że ustawiłeś opcję config.active_record.whitelist_attributes = true w swoim config / environment / production.rb w celu ochrony Twojej aplikacji przed masowym przypisaniem exploita. Jest to wyjaśnione tutaj : Przypisanie Masy

Twój model Rails będzie doskonale współpracować z Modelem tutaj poniżej:

class User < ActiveRecord::Base

end

Jednak będziesz musiał zaktualizować każdy atrybut użytkownika osobno w kontrolerze, aby Widok formularza działał :

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

Teraz, aby ułatwić sobie życie, nie chcesz robić skomplikowanego kontrolera dla swojego modelu użytkownika. Więc użyjesz attr_accessible specjalnej metody w swoim modelu klasowym:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname

end

Więc możesz użyć "highway" (Mass assignment), aby zaktualizować :

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

Nie dodałeś atrybutów "rola" do listy attr_accessible, ponieważ nie pozwalasz użytkownikom samodzielnie ustawiać swojej roli (np. admin). Robisz to sam na innym specjalnym widoku administratora.

Chociaż widok użytkownika nie pokazuje pola "rola", pirat może łatwo wysłać żądanie HTTP POST, które zawiera "rolę" w hash params. Brakujący atrybut "rola" na attr_accessible ma chronić Twoją aplikację przed tym.

Nadal możesz modyfikować swojego użytkownika.atrybut roli samodzielnie jak poniżej, ale nie ze wszystkimi atrybutami razem.

@user.role = DEFAULT_ROLE

Po jaką cholerę miałbyś używać attr_accessor?

Cóż, byłoby tak w przypadku, gdy formularz użytkownika pokazuje pole, które nie istnieje w tabeli użytkowników jako kolumna.

Na przykład, powiedzmy, że twój widok użytkownika pokazuje pole" please-tell-the-admin-that-I 'm-in-here". Nie chcesz przechowywać tych informacji w tabeli. Po prostu chcesz, żeby Rails wysłał Ci e-mail z ostrzeżeniem, że jeden "szalony"; -) użytkownik ma subscribed.

Aby móc skorzystać z tych informacji, musisz je tymczasowo gdzieś przechowywać. Co jest łatwiejsze niż odzyskanie go w atrybucie user.peekaboo?

Więc dodajesz to pole do swojego modelu:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo

end

Więc będziesz mógł wykorzystać atrybut user.peekaboo gdzieś w kontrolerze, aby wysłać e-mail lub zrobić, co chcesz.

ActiveRecord nie zapisze atrybutu "peekaboo" w tabeli po wykonaniu user.save, ponieważ nie widzi żadnego kolumna pasująca do tej nazwy w jej modelu.

 174
Author: Douglas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-02 12:56:58

attr_accessor jest metodą Ruby, która daje metody setter i getter do zmiennej instancji o tej samej nazwie. Jest więc odpowiednikiem

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

attr_accessible jest metodą Rails, która określa, jakie zmienne można ustawić w przypisaniu masowym.

Kiedy przesyłasz formularz i masz coś w rodzaju MyModel.new params[:my_model], chcesz mieć trochę większą kontrolę, aby ludzie nie mogli przesyłać rzeczy, których nie chcesz.

Można zrobić attr_accessible :email tak, że gdy ktoś aktualizuje swoje konto, mogą zmienić swój adres e-mail. Ale nie zrobiłbyś tego, bo wtedy ktoś mógłby ustawić swoją pensję poprzez złożenie formularza. Innymi słowy, mogą zhakować drogę do podwyżki.

Tego rodzaju informacje muszą być wyraźnie obsługiwane. Samo usunięcie go z formularza nie wystarczy. Ktoś mógłby wejść z firebug i dodać element do formularza, aby przesłać pole wynagrodzenia. Mogą wykorzystać wbudowany curl do przesłania nowej pensji do metody aktualizacji kontrolera, oni może utworzyć skrypt, który przesyła post z tymi informacjami.

Więc {[1] } chodzi o tworzenie metod do przechowywania zmiennych, a {[2] } o bezpieczeństwo przypisań masowych.

 49
Author: Joshua Cheek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-12 14:48:48

attr_accessor jest kodem ruby i jest używany, gdy nie masz kolumny w bazie danych, ale nadal chcesz pokazać pole w formularzach. Jedynym sposobem na to jest attr_accessor :fieldname i możesz użyć tego pola w widoku, lub modelu, jeśli chcesz, ale głównie w widoku.

Rozważmy następujący przykład

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

Tutaj użyliśmy attr_reader (atrybut readable ) oraz attr_writer (atrybut zapisywalny ) dla dostępu do celu. Ale możemy osiągnąć tę samą funkcjonalność za pomocą attr_accessor. W skrócie, attr_accessor zapewnia dostęp zarówno do metod getter, jak i setter.

Tak zmodyfikowany kod jest jak poniżej

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

attr_accessible pozwala na wyświetlenie wszystkich kolumn, które chcesz zezwolić na przypisanie masy. Przeciwieństwem tego jest attr_protected, co oznacza, że nie chcę, aby ktokolwiek miał możliwość przypisania masy do tego pola. Bardziej niż prawdopodobne, że będzie to pole w Twojej bazie danych, z którym nie chcesz, aby ktoś się kręcił. Jak Pole statusu, lub tym podobne.

 18
Author: shrikant1712,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 12:09:23

W dwóch słowach:

attr_accessor Na getter, setter metoda. a także mając na uwadze attr_accessible oznacza to, że dany atrybut jest dostępny lub nie. to wszystko.


Chciałbym dodać, że powinniśmy używać silnego parametru zamiast attr_accessible do ochrony przed przesunięciem masy.

Zdrówko!
 2
Author: Manish Shrivastava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-18 11:12:57

Szybki i zwięzły przegląd różnic:

attr_accessor jest łatwym sposobem tworzenia accesorów do odczytu i zapisu w twoja klasa. Jest używany, gdy nie masz kolumny w bazie danych, ale nadal chcesz pokazać pole w formularzach. To pole jest “virtual attribute” w modelu Rails.

Atrybut wirtualny - atrybut nie odpowiadający kolumnie w bazie danych.

attr_accessible służy do identyfikacji atrybutów, które są dostępne przez kontrolera metody udostępnia właściwość dla przydział masowy.. Pozwoli tylko na dostęp do atrybutów, które określ, zaprzeczając reszcie.

 2
Author: Muhammad Yawar Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-31 06:30:45