УСЁ, з чым вы працуеце у Ruby - гэта аб'екты. Вынік дзеянняў над аб'ектамі - таксама аб'екты.
Калі мы ствараем web-прыкладанне, мы працуем з паняткам мадэлі, якая мае адлюстраванне ў рэальнасці. У працэссе мадэлявання мы сутыкаемся з катэгорыямі, якія павінны быць прадстаўлены у нашым кодзе. Напрыклад, катэгорыя водгука карыстальніка. Каб прадставіць такую катэгорыю у Ruby, мы павінны вызначыць клас. І гэты клас (напрыклад Testimonial) мы выкарыстоўваем для таго, каб ствараць аб'екты - экземпляры класа.
Паглядзіце экшн new кантроллера Testimonials:
# app/controllers/testimonials_controller.rb
def new
@testimonial = Testimonial.new
end
Мы ствараем экземпляр класа 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 - гэта індэксаваныя калекцыі аб'ектаў. У іх захоўваюцца сукупнасці аб'ектаў, якія даступны праз выкарыстанне ключа. У масівах ключ - гэта цэлая лічба, у хэшах ключом можа быць любы аб'ект. Крыху ніжэй мы пабачым на практыцы, як можна працаваць з масівам на прыкладзе памылак валідацыі.
Мы зрабілі валідацыі наяўнасці 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;
}
}
Зараз мы чотка бачым, што робім няправільна, калі адпраўляем пустую форму:
Вернемся да нашага прыкладання. Давайце адлюструем на 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 :)
Наш курс - гэта перш за ўсё практыка і пабудова web-прыкладання. Я не стаўлю за мэту навучыць студэнтаў праграмаваць, пра гэта было сказана на самым пачатку курса. Таму я наўмысна не даю вам абстрактных прыкладаў для вывучэння Ruby, а толькі канкрэтныя прыклады нашага прыкладання, якія будуць ахопліваць розныя аспекты Ruby падчас далейшай распрацоўкі.
Але кожны Rails-распрацоўшчык абавязаны добра ведаць Ruby, таму дома трэба вельмі актыўна вывучаць іншыя крыніцы і дакументацыю