Skip to content

Latest commit

 

History

History
220 lines (168 loc) · 13 KB

6_lecture.md

File metadata and controls

220 lines (168 loc) · 13 KB

6. Уводзіны у аб'ектна-арыентаванае праграмаванне. Асновы мовы Ruby

Аб'ектна-арыентаваная мова Ruby

УСЁ, з чым вы працуеце у Ruby - гэта аб'екты. Вынік дзеянняў над аб'ектамі - таксама аб'екты.

Калі мы ствараем web-прыкладанне, мы працуем з паняткам мадэлі, якая мае адлюстраванне ў рэальнасці. У працэссе мадэлявання мы сутыкаемся з катэгорыямі, якія павінны быць прадстаўлены у нашым кодзе. Напрыклад, катэгорыя водгука карыстальніка. Каб прадставіць такую катэгорыю у Ruby, мы павінны вызначыць клас. І гэты клас (напрыклад Testimonial) мы выкарыстоўваем для таго, каб ствараць аб'екты - экземпляры класа.

Паглядзіце экшн new кантроллера Testimonials:

# app/controllers/testimonials_controller.rb
def new
  @testimonial = Testimonial.new
end

Метады Ruby і блокі кода

Мы ствараем экземпляр класа Testimonial праз выклік канструктара new(), які звязаны з класам. У класах арганізуюцца метады Ruby.

Давайце глянем на мадэль Testimonial:

#app/models/testimonial.rb
class Testimonial < ActiveRecord::Base
  validates :user_name, :feedback, presence: true
end

Тут клас Testimonial вызначаны як падклас, які адносіцца да класа Base, які знаходзіцца у модулі ActiveRecord. Пры гэтым для абъектаў класа Testimonial даступныя усе метады ActiveRecord. Гэта прыклад наследавання у Ruby. Наследаванне - адна з асноўных асаблівасцяў ААП.

Другой важкай асаблівасцю з'яўляецца інкапсуляцыя (схаванне рэалізацыі логікі прыкладання). Адной з магчымасцяў, якую дае інкапсуляцыя у Ruby з'яўляецца магчымасць хавання метадаў і надавання ім тыпа бачнасці. Памятаеце, private метад testimonial_params?

Трэцім кітом ААП з'яўляецца палімарфізм. Палімарфізм - гэта магчымасць падобных класаў (напрыклад, спадкаемцаў) мець розную рэалізацыю аднаго метада. Падрабязней чытайце тут.

Метады выклікаюцца праз адпраўку паведамлення аб'екту. У выпадку Testimonial.new мы проста перадаем імя метада. Таксама паведамленне можа утрымліваць аргументы метада. Для параўнання паглядзіце метад create у гэтым жа кантроллеры: @testimonial = Testimonial.new(testimonial_params). У якасці аргумента мы перадаем параметры водгука з формы.

Давайце нададзім нашай форме для водгукаў больш прыдатны выгляд. Для гэтага скарыстаемся Bootstrap-класамі. Іх можна перадаць у якасці аргумента class:

# app/views/testimonials/new.html.erb
<%= form_for @testimonial, html: {class: 'form-horizontal center'} do |f| %>

    <div class="form-group">
      <%= f.label :user_name, class: 'col-md-4 control-label' %>
      <div class="col-md-6">
        <%= f.text_field :user_name, class: 'form-control' %>
      </div>
    </div>

    <div class="form-group">
      <%= f.label :feedback, class: 'col-md-4 control-label' %>
      <div class="col-md-6">
        <%= f.text_area :feedback, class: 'form-control' %>
      </div>
    </div>

    <%= f.submit 'Create testimonial', class: 'btn btn-large btn-primary' %>
<% end %>

Давайце зараз больш асэнсавана зірнем на форму: мы звязалі форму праз метад form_for і аб'ект мадэлі Testimonial. Менавіта у Ruby-аб'ект @testimonial мы кладзем параметры з формы. У дадзеным выпадку мы выклікалі метад і перадалі аргументы без дужак - так можна рабіць у Ruby. Сінтаксіс даволі гнуткі.

У кодзе формы можна пабачыць блок кода - ён знаходзіцца паміж ключавымі словамі do ... end і перадаецца метаду form_for пасля аргументаў метада.

Тыпы дадзеных Ruby і логіка

Мы ўжо крыху знаемыя з тыпамі дадзеных, напрыклад ведаем аб'екты-радкі, якія знаходзяцца у апострафах, альбо двукоссях, калі патрэбна інтэрпаляцыя.

Масівы і хэшы у Ruby - гэта індэксаваныя калекцыі аб'ектаў. У іх захоўваюцца сукупнасці аб'ектаў, якія даступны праз выкарыстанне ключа. У масівах ключ - гэта цэлая лічба, у хэшах ключом можа быць любы аб'ект. Крыху ніжэй мы пабачым на практыцы, як можна працаваць з масівам на прыкладзе памылак валідацыі.

Мы зрабілі валідацыі наяўнасці user_name і feedback, і зараз, калі мы адпраўляем пустую форму - водгук не захоўваецца. Пасля такой спробы зноў рэндэрыцца форма водгука. Давайце зробім гэтую форму больш user-friendly i адлюструем памылкі, каб пазбегнуць зацыклівання.

Rails аўтаматычна стварае паведамленні пра памылкі на аснове валідацый. Давайце паглядзім, як гэта працуе:

$ rails c
> testimonial = Testimonial.new
> testimonial.save
> errors_array = testimonial.errors.full_messages

Апошні радок вяртае нам масіў з памылкамі. Кожную памылку можна атрымаць праз ключ, напрыклад:

> errors_array[0]

Звярніце увагу, што нумерацыя пачынаецца з нуля.

Памылкі звязаныя з аб'ектам @testimonial. Дадамо у форму панэль са спісам памылак:

# app/views/testimonials/new.html.erb
<% if @testimonial.errors.any? %>
  <div class="alert alert-danger">
    <b><%= pluralize(@testimonial.errors.count, "error") %> on form.</b>
    <ul>
      <% @testimonial.errors.full_messages.each do |message| %>
          <li>* <%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

Спачатку мы робім праверку, ці ёсць хоць адна памылка ў аб'екта @testimonial з дапамогай метада-прэдыката any?. Імёны такіх метадў сканчаюцца пытальнікам, а сам метад вяртае true альбо false. Мы адлюстроўваем панэль, толькі калі першы радок вяртае true. Мы ужо бачылі падобную структуру у create экшне Testimonials кантроллера, калі правяралі, ці захаваўся аб'ект і у залежнасці ад выканання логікі перанакіроўвалі на іншую старонку ці рэндэрылі форму. Звярніце увагу, што блокі з кіруючымі паслядоўнасцямі павінны сканчацца ключавым словам end.

Далей мы выкарыстоўваем тэкставы метад pluralize каб паведамленне адлюстроўвалася пісменна. Аб'ект @testimonial.errors.full_messages - гэта масіў паведамленняў пра памылкі. Мы змяшчаем гэты масіў у ітэратар each do ... і перадаем кожнае паведамленне з масіва у элемент

  • .

    Давайце трохі стылізуем інпуты. Зрабіць гэта вельмі проста, таму што Rails абарочвае палі з памылкамі у клас field_with_errors.

    #app/stylesheets/custom.scss
    
    .field_with_errors {
      input, textarea {
      border-color: red;
      }
    
      label {
        color: red;
      }
    }
    

    Зараз мы чотка бачым, што робім няправільна, калі адпраўляем пустую форму:

    testimonials-routes

    Вернемся да нашага прыкладання. Давайце адлюструем на index старонцы ўсе водгукі. Для гэтага масіў з водгукамі трэба перш за ўсё пакласці у зменную экземпляра кантроллера Testimonials у адпаведным метадзе:

    # app/controllers/testimonials_controller.rb
    def index
      @testimonials = Testimonial.all
    end
    

    Зараз водгукі даступныя ў index view, давайце выкарыстаем веды Ruby і Bootstrap, каб прыгожа іх адлюстраваць. Таксама дададзім спасылку на стварэнне новага водгука.

    # app/views/testimonials/index.html.erb
    <div class="panel panel-default">
      <div class="panel-body">
        <%= link_to 'Add new testimonial', new_testimonial_path, class: 'btn btn-primary btn-lg' %>
      </div>
    </div>
    
    <div class="list-group">
      <%= render @testimonials %>
    </div>
    

    Усе водгукі мы адрэндэрым унутры элемента <div class="list-group"></div>. Таксама дададзім спасылку на старонку кожнага водгука. Для гэтага трэба стварыць частковы шаблон:

    # app/views/testimonial/_testimonial.html.erb
    <a href="<%= testimonial_path(testimonial) %>" class="list-group-item">
      <blockquote>
        <p><%= testimonial.feedback %></p>
        <footer>
          <%= testimonial.user_name %>
          <span><%= time_ago_in_words(testimonial.created_at) %> ago</span>
        </footer>
      </blockquote>
    </a>
    

    Тут мы выкарысталі Rails-метад time_ago_in_words каб адлюстраваць у словах час стварэння водгука. Звярніце увагу, што у гэтым шаблоне мы працуем непасрэдна з канкрэтным водгукам бо для кожнага водгука са зменнай @testimonials рэндэрыцца асобны partial.

    Дарэчы, можаце дадаваць водгукі пра наш курс у нашым жа дэма-прыкладанні: https://course-app.herokuapp.com/testimonials :)

    Вывучэнне Ruby

    Наш курс - гэта перш за ўсё практыка і пабудова web-прыкладання. Я не стаўлю за мэту навучыць студэнтаў праграмаваць, пра гэта было сказана на самым пачатку курса. Таму я наўмысна не даю вам абстрактных прыкладаў для вывучэння Ruby, а толькі канкрэтныя прыклады нашага прыкладання, якія будуць ахопліваць розныя аспекты Ruby падчас далейшай распрацоўкі.

    Але кожны Rails-распрацоўшчык абавязаны добра ведаць Ruby, таму дома трэба вельмі актыўна вывучаць іншыя крыніцы і дакументацыю

    << папярэдні занятак наступны занятак >>