edge
Daugiau informacijos rubyonrails.org: Daugiau apie Ruby on Rails

Aktyvaus modelio pagrindai

Šis vadovas turėtų suteikti jums viską, ko reikia, norint pradėti naudoti modelio klases. Aktyvus modelis leidžia Action Pack pagalbininkams sąveikauti su paprastais Ruby objektais. Aktyvus modelis taip pat padeda kurti pasirinktinius ORMs, skirtus naudoti už „Rails“ pagrindo.

Po šio vadovo perskaitymo žinosite:

1 Kas yra aktyvusis modelis?

Aktyvusis modelis yra biblioteka, kurioje yra įvairūs moduliai, naudojami kurti klases, kuriose reikalingos kai kurios funkcijos, esančios aktyviame įraše. Kai kurie iš šių modulių yra paaiškinti žemiau.

1.1 API

ActiveModel::API suteikia galimybę klasėms iš karto dirbti su Action Pack ir Action View.

class EmailContact
  include ActiveModel::API

  attr_accessor :name, :email, :message
  validates :name, :email, :message, presence: true

  def deliver
    if valid?
      # išsiųsti el. laišką
    end
  end
end

Įtraukus ActiveModel::API, gaunate tam tikrų funkcijų, pvz.:

  • modelio pavadinimo introspekcija
  • konversijos
  • vertimai
  • patikrinimai

Tai taip pat suteikia galimybę sukuriant objektą su atributų maiša, panašiai kaip bet kuris aktyvusis įrašo objektas.

irb> email_contact = EmailContact.new(name: 'David', email: '[email protected]', message: 'Hello World')
irb> email_contact.name
=> "David"
irb> email_contact.email
=> "[email protected]"
irb> email_contact.valid?
=> true
irb> email_contact.persisted?
=> false

Bet kuri klasė, kuri įtraukia ActiveModel::API, gali būti naudojama su form_with, render ir bet kuriais kitais Action View pagalbininkų metodais, kaip ir aktyvūs įrašų objektai.

1.2 Atributo metodai

ActiveModel::AttributeMethods modulis gali pridėti pasirinktinius priešdėlius ir priesagos metodus klasės metodams. Jis naudojamas apibrėžiant priešdėlius ir priesagas bei nurodant, kurie objekto metodai juos naudos.

class Person
  include ActiveModel::AttributeMethods

  attribute_method_prefix 'reset_'
  attribute_method_suffix '_highest?'
  define_attribute_methods 'age'

  attr_accessor :age

  private
    def reset_attribute(attribute)
      send("#{attribute}=", 0)
    end

    def attribute_highest?(attribute)
      send(attribute) > 100
    end
end
irb> person = Person.new
irb> person.age = 110
irb> person.age_highest?
=> true
irb> person.reset_age
=> 0
irb> person.age_highest?
=> false

1.3 Atgaliniai iškvietimai

ActiveModel::Callbacks suteikia galimybę naudoti aktyvaus įrašo stiliaus atgalinius iškvietimus. Tai leidžia apibrėžti atgalinius iškvietimus, kurie vykdomi tinkamu metu. Apibrėžus atgalinius iškvietimus, juos galima apgaubti prieš, po ir aplink pasirinktinius metodus.

class Person
  extend ActiveModel::Callbacks

  define_model_callbacks :update

  before_update :reset_me

  def update
    run_callbacks(:update) do
      # Šis metodas yra iškviestas, kai objekte yra iškviestas atnaujinimas.
    end
  end

  def reset_me
    # Šis metodas yra iškviestas, kai objekte yra iškviestas atnaujinimas kaip prieš atnaujinimo atgalinis iškvietimas.
  end
end

1.4 Konversija

Jei klasė apibrėžia persisted? ir id metodus, tada galite įtraukti ActiveModel::Conversion modulį į tą klasę ir šios klasės objektuose naudoti „Rails“ konversijos metodus.

class Person
  include ActiveModel::Conversion

  def persisted?
    false
  end

  def id
    nil
  end
end
irb> person = Person.new
irb> person.to_model == person
=> true
irb> person.to_key
=> nil
irb> person.to_param
=> nil

1.5 Dirty

Objektas tampa „dirty“, kai jis patyrė vieną ar daugiau pakeitimų savo atributuose ir nebuvo išsaugotas. ActiveModel::Dirty suteikia galimybę patikrinti, ar objektas buvo pakeistas ar ne. Tai taip pat turi atributo pagrindinius prieigos metodus. Pagalvokime apie „Person“ klasę su atributais „first_name“ ir „last_name“:

class Person
  include ActiveModel::Dirty
  define_attribute_methods :first_name, :last_name

  def first_name
    @first_name
  end

  def first_name=(value)
    first_name_will_change!
    @first_name = value
  end

  def last_name
    @last_name
  end

  def last_name=(value)
    last_name_will_change!
    @last_name = value
  end

  def save
    # atlikti išsaugojimo darbą...
    changes_applied
  end
end

1.5.1 Tiesioginio objekto užklausimas dėl jo visų pakeistų atributų sąrašo

irb> person = Person.new
irb> person.changed?
=> false

irb> person.first_name = "First Name"
irb> person.first_name
=> "First Name"

# Grąžina „true“, jei bet kuris iš atributų turi neišsaugotų pakeitimų.
irb> person.changed?
=> true

# Grąžina sąrašą atributų, kurie buvo pakeisti prieš išsaugojimą.
irb> person.changed
=> ["first_name"]

# Grąžina „Hash“, kuriame yra pakeistų atributų su jų pradinėmis reikšmėmis.
irb> person.changed_attributes
=> {"first_name"=>nil}

# Grąžina pakeitimų „Hash“, kurio atributų pavadinimai yra raktai, o reikšmės yra masyvas, kuriame yra senosios ir naujosios reikšmės šiam laukui.
irb> person.changes
=> {"first_name"=>[nil, "First Name"]}

1.5.2 Atributo pagrindiniai prieigos metodai

Stebėkite, ar konkretus atributas buvo pakeistas ar ne. ```irb irb> person.first_name => "Vardas"

attr_name_changed?

irb> person.first_name_changed? => true ```

Sekite atributo ankstesnės reikšmės.

# attr_name_was accessor
irb> person.first_name_was
=> nil

Sekite ankstesnę ir dabartinę pakeistos savybės reikšmes. Grąžina masyvą, jei pakeista, kitu atveju grąžina nil.

# attr_name_change
irb> person.first_name_change
=> [nil, "Vardas"]
irb> person.last_name_change
=> nil

1.6 Validacijos

ActiveModel::Validations modulis suteikia galimybę tikrinti objektus kaip Active Record.

class Person
  include ActiveModel::Validations

  attr_accessor :name, :email, :token

  validates :name, presence: true
  validates_format_of :email, with: /\A([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})\z/i
  validates! :token, presence: true
end
irb> person = Person.new
irb> person.token = "2b1f325"
irb> person.valid?
=> false
irb> person.name = 'vishnu'
irb> person.email = 'me'
irb> person.valid?
=> false
irb> person.email = '[email protected]'
irb> person.valid?
=> true
irb> person.token = nil
irb> person.valid?
ActiveModel::StrictValidationFailed

1.7 Pavadinimai

ActiveModel::Naming prideda keletą klasės metodų, kurie palengvina pavadinimų ir maršrutų valdymą. Modulis apibrėžia model_name klasės metodą, kuris apibrėžia keletą priėjimo būdų naudojant ActiveSupport::Inflector metodus.

class Person
  extend ActiveModel::Naming
end

Person.model_name.name                # => "Person"
Person.model_name.singular            # => "person"
Person.model_name.plural              # => "people"
Person.model_name.element             # => "person"
Person.model_name.human               # => "Person"
Person.model_name.collection          # => "people"
Person.model_name.param_key           # => "person"
Person.model_name.i18n_key            # => :person
Person.model_name.route_key           # => "people"
Person.model_name.singular_route_key  # => "person"

1.8 Modelis

ActiveModel::Model leidžia kurti modelius, panašius į ActiveRecord::Base.

class EmailContact
  include ActiveModel::Model

  attr_accessor :name, :email, :message
  validates :name, :email, :message, presence: true

  def deliver
    if valid?
      # pristatyti el. laišką
    end
  end
end

Įtraukus ActiveModel::Model, gaunate visas funkcijas iš ActiveModel::API.

1.9 Serializacija

ActiveModel::Serialization suteikia pagrindinę objekto serializaciją. Turite apibrėžti atributų Hash, kuriame yra atributai, kuriuos norite serializuoti. Atributai turi būti eilutės, o ne simboliai.

class Person
  include ActiveModel::Serialization

  attr_accessor :name

  def attributes
    { 'name' => nil }
  end
end

Dabar galite pasiekti objekto serializuotą Hash naudodami serializable_hash metodą.

irb> person = Person.new
irb> person.serializable_hash
=> {"name"=>nil}
irb> person.name = "Bob"
irb> person.serializable_hash
=> {"name"=>"Bob"}

1.9.1 ActiveModel::Serializers

Active Model taip pat suteikia ActiveModel::Serializers::JSON modulį JSON serializavimui / deserializavimui. Šis modulis automatiškai įtraukia ankstesniai aptartą ActiveModel::Serialization modulį.

1.9.1.1 ActiveModel::Serializers::JSON

Norėdami naudoti ActiveModel::Serializers::JSON, turite pakeisti įtraukiamą modulį iš ActiveModel::Serialization į ActiveModel::Serializers::JSON.

class Person
  include ActiveModel::Serializers::JSON

  attr_accessor :name

  def attributes
    { 'name' => nil }
  end
end

as_json metodas, panašiai kaip serializable_hash, suteikia modelio atitinkančią Hash reprezentaciją.

irb> person = Person.new
irb> person.as_json
=> {"name"=>nil}
irb> person.name = "Bob"
irb> person.as_json
=> {"name"=>"Bob"}

Taip pat galite apibrėžti atributus modeliui iš JSON eilutės. Tačiau turite apibrėžti attributes= metodą savo klasėje:

class Person
  include ActiveModel::Serializers::JSON

  attr_accessor :name

  def attributes=(hash)
    hash.each do |key, value|
      send("#{key}=", value)
    end
  end

  def attributes
    { 'name' => nil }
  end
end

Dabar galima sukurti Person objekto instanciją ir nustatyti atributus naudojant from_json.

irb> json = { name: 'Bob' }.to_json
irb> person = Person.new
irb> person.from_json(json)
=> #<Person:0x00000100c773f0 @name="Bob">
irb> person.name
=> "Bob"

1.10 Vertimas

ActiveModel::Translation suteikia integraciją tarp jūsų objekto ir „Rails“ tarptautinės (i18n) sistemos.

class Person
  extend ActiveModel::Translation
end

Naudojant human_attribute_name metodą, galite paversti atributo pavadinimus į žmogui skaitytines formatus. Žmogui skaitytinas formatas yra apibrėžtas jūsų lokalizacijos failuose.

  • config/locales/app.pt-BR.yml
pt-BR:
  activemodel:
    attributes:
      person:
        name: 'Nome'
Person.human_attribute_name('name') # => "Nome"

1.11 Lint testai

ActiveModel::Lint::Tests leidžia patikrinti, ar objektas atitinka Active Model API.

  • app/models/person.rb

    class Person
      include ActiveModel::Model
    end
    
  • test/models/person_test.rb

    require "test_helper"
    
    class PersonTest < ActiveSupport::TestCase
      include ActiveModel::Lint::Tests
    
      setup do
        @model = Person.new
      end
    end
    
$ bin/rails test

Run options: --seed 14596

# Running:

......

Finished in 0.024899s, 240.9735 runs/s, 1204.8677 assertions/s.

6 runs, 30 assertions, 0 failures, 0 errors, 0 skips

Objektui nereikia įgyvendinti visų API, kad veiktų su Action Pack. Šis modulis tik siekia padėti, jei norite visų funkcijų iškart.

1.12 SecurePassword

ActiveModel::SecurePassword suteikia būdą saugiai saugoti bet kokį slaptažodį užšifruotoje formoje. Įtraukus šį modulį, yra pateikiamas has_secure_password klasės metodas, kuris apibrėžia password priėjimo būdą su tam tikromis numatytomis tikrinimais. ```

1.12.1 Reikalavimai

ActiveModel::SecurePassword priklauso nuo bcrypt, todėl įtraukite šią juostą į savo Gemfile, kad teisingai naudotumėte ActiveModel::SecurePassword. Tam, kad tai veiktų, modelyje turi būti prieigos teikėjas, pavadinimu XXX_digest. Čia XXX yra jūsų norimo slaptažodžio atributo pavadinimas. Automatiškai pridedami šie patikrinimai:

  1. Slaptažodis turi būti pateiktas.
  2. Slaptažodis turi būti lygus jo patvirtinimui (jei perduodamas XXX_confirmation).
  3. Slaptažodžio maksimalus ilgis yra 72 (reikalaujama bcrypt, nuo kurio priklauso ActiveModel::SecurePassword).

1.12.2 Pavyzdžiai

class Person
  include ActiveModel::SecurePassword
  has_secure_password
  has_secure_password :recovery_password, validations: false

  attr_accessor :password_digest, :recovery_password_digest
end
irb> person = Person.new

# Kai slaptažodis yra tuščias.
irb> person.valid?
=> false

# Kai patvirtinimas nesutampa su slaptažodžiu.
irb> person.password = 'aditya'
irb> person.password_confirmation = 'nomatch'
irb> person.valid?
=> false

# Kai slaptažodžio ilgis viršija 72.
irb> person.password = person.password_confirmation = 'a' * 100
irb> person.valid?
=> false

# Kai pateikiamas tik slaptažodis be slaptažodžio patvirtinimo.
irb> person.password = 'aditya'
irb> person.valid?
=> true

# Kai visi patikrinimai yra sėkmingi.
irb> person.password = person.password_confirmation = 'aditya'
irb> person.valid?
=> true

irb> person.recovery_password = "42password"

irb> person.authenticate('aditya')
=> #<Person> # == person
irb> person.authenticate('notright')
=> false
irb> person.authenticate_password('aditya')
=> #<Person> # == person
irb> person.authenticate_password('notright')
=> false

irb> person.authenticate_recovery_password('42password')
=> #<Person> # == person
irb> person.authenticate_recovery_password('notright')
=> false

irb> person.password_digest
=> "$2a$04$gF8RfZdoXHvyTjHhiU4ZsO.kQqV9oonYZu31PRE4hLQn3xM2qkpIy"
irb> person.recovery_password_digest
=> "$2a$04$iOfhwahFymCs5weB3BNH/uXkTG65HR.qpW.bNhEjFP3ftli3o5DQC"

Atsiliepimai

Jūs esate skatinami padėti pagerinti šio vadovo kokybę.

Prašome prisidėti, jei pastebite rašybos klaidų ar faktinių klaidų. Norėdami pradėti, galite perskaityti mūsų dokumentacijos prisidėjimo skyrių.

Taip pat gali būti nepilnos informacijos arba informacijos, kuri nėra atnaujinta. Prašome pridėti bet kokią trūkstamą dokumentaciją pagrindiniam. Patikrinkite Edge vadovus pirmiausia, ar problemas jau išspręsta arba ne pagrindinėje šakoje. Patikrinkite Ruby on Rails vadovų gaires dėl stiliaus ir konvencijų.

Jei dėl kokios nors priežasties pastebite kažką, ką reikia ištaisyti, bet negalite patys tai pataisyti, prašome pranešti apie problemą.

Ir galiausiai, bet ne mažiau svarbu, bet koks diskusijos dėl Ruby on Rails dokumentacijos yra labai laukiamos oficialiame Ruby on Rails forume.