Сегодня я расскажу вам, как создать банковское приложение. Наш стек технологий будет: Ruby On Rails, Haml, PostgreSQL и jQuery. В этом руководстве мы не будем иметь дело с реальными деньгами, но в этой серии мы будем расширяться. Это очень длинный учебник, поэтому мы будем использовать различные шаблоны дизайна для организации нашего кода. Во второй части этого руководства мы создадим наш собственный слой API для проверки и выполнения наших транзакций. Если вы хотите сразу перейти к коду, репозиторий находится здесь https://github.com/jalenjackson/bankingAppTutorial

Посетите brainflop.com для революционной викторины! Сначала мы начнем с настройки нашей базы данных PostgreSQL для работы в нашей среде разработки.

Для начала запустите postgres --version в терминале и проверьте, какую версию PostgreSQL вы используете. Если у вас установлен PostgreSQL, вы должны увидеть следующее.

Если у вас Mac, у вас автоматически должен быть установлен PostgreSQL, но если у вас его нет, вы можете легко запустить brew install postgresql

Следующим шагом нам нужно войти в PostgreSQL. В корневом каталоге вашего терминала запустите sudo su postgres -c psql После этого вам будет предложено ввести пароль. Введите свой пароль, и вы должны войти в систему. Вы должны увидеть postgres=# в ожидании следующей команды.

Теперь нам нужно создать нашу базу данных. С терминала запустить CREATE DATABASE banking_app_dev;

После этого вы должны увидеть ответ CREATE DATABASE

После создания базы данных давайте создадим нового пользователя для внесения изменений в базу данных. CREATE USER admin WITH PASSWORD ‘6x59cwtwf6r’; Это вернет CREATE ROLE. Теперь у нас есть пользователь в базе данных, но нам нужно предоставить ему права, чтобы пользователь мог вносить изменения в базу данных. Выполните команду GRANT ALL PRIVILEGES ON DATABASE banking_app_dev TO admin. Это позволит пользователю вносить изменения в базу данных в нашем приложении rails. Большой! Теперь мы можем создать наше новое приложение rails.

Начнем с выполнения команды rails new banking_application — database=postgresql -T -B

Отлично, мы создали приложение rails для работы на PostgreSQL. сейчас cd или смените каталог на banking_application. Теперь откройте свое приложение в своем любимом текстовом редакторе и перейдите к своему Gemfile. Вы должны увидеть драгоценный камень ‘pg’, который представляет собой PostgreSQL. Теперь перейдите к/config/database.yml. В этом файле вы увидите сильно прокомментированный файл с кодом для настройки базы данных. Без комментариев вы должны увидеть

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: banking_application_development

test:
  <<: *default
  database: banking_application_test

production:
  <<: *default
  database: banking_application_production
  username: banking_application
  password: <%= ENV['BANKING_APPLICATION_DATABASE_PASSWORD'] %>

Нам нужно изменить этот файл, чтобы настроить нашу базу данных. Все, что нам нужно сделать, это добавить наши port, username, password и name of our database. Код будет выглядеть так

default: &default
  adapter: postgresql
  encoding: unicode
  port: 5432
  username: admin
  password: 6x59cwtwf6r
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: banking_app_dev

test:
  <<: *default
  database: banking_app_dev

production:
  <<: *default
  database: banking_application_production
  username: banking_application
  password: <%= ENV['BANKING_APPLICATION_DATABASE_PASSWORD'] %>

Если мы хотим запустить это приложение в производственной среде, мы должны заключить информацию о нашей базе данных в Environment Variables. Наш код должен выглядеть так

default: &default
  adapter: postgresql
  encoding: unicode
  port: <%= ENV["DATABASE_PORT"] %>
  username: <%= ENV["DATABASE_USERNAME"] %>
  password: <%= ENV["DATABASE_PASSWORD"] %>
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: <%= ENV["DATABASE_NAME"] %>

test:
  <<: *default
  database: <%= ENV["DATABASE_NAME"] %>

production:
  <<: *default
  database: banking_application_production
  username: banking_application
  password: <%= ENV['BANKING_APPLICATION_DATABASE_PASSWORD'] %>

Затем мы можем использовать эти Environment Variables для размещения значений вне приложения. Теперь давайте подключимся к нашей базе данных с помощью GUI. Давайте воспользуемся PSequel для просмотра нашей базы данных в графическом интерфейсе. Перейдите на http://www.psequel.com/ и загрузите последнюю версию PSequel. Затем откройте PSequel. Тебе следует увидеть

Нам нужно ввести правильные значения для доступа к нашей базе данных. Наш Хост - localhost. Помните, что мы создали user с именем admin, а я выбрал password 6x59cwtwf6r. Имя базы данных - banking_app_dev. Порт - 5432. После добавления этих значений нажмите кнопку Connect. Мы должны увидеть

Теперь, чтобы убедиться, что все правильно настроено, давайте создадим запись в базе данных. Запустите rails g scaffold post name:string в терминале. Теперь run rails db:migrate Это создало таблицу posts и добавило столбец name с типом string.

Теперь давайте создадим пост из базы данных. Введите в терминале rails c, что является сокращением от rails console. Запустите команду Post.create(name: “new post”)

Это создаст новую запись в вашей базе данных. Теперь откройте PSequel. Нажмите значок перезагрузки в левом нижнем углу.

Теперь вы должны увидеть

Вот наша таблица сообщений и запись, которую мы добавили «новое сообщение» с id 1. Теперь наша база данных настроена правильно, мы можем перейти к созданию нашего банковского приложения. Но сначала перейдите к db/migrate и удалите файл миграции, который мы создали при запуске генератора шаблонов для сообщений. Затем запустите rails db:rollback, чтобы откатить таблицу сообщений, поскольку это было для примера.

Затем запустите rails db:migrate, и ничего не должно произойти. хороший. Теперь мы готовы приступить к созданию сути нашего приложения.

Теперь давайте начнем с добавления драгоценного камня Devise. Этот драгоценный камень позволяет очень быстро создавать логику регистрации пользователей. Https://github.com/plataformatec/devise

Перейдите в свой Gemfile и добавьте gem ‘devise’

Затем перейдите в свой терминал и запустите bundle, чтобы установить этот драгоценный камень. Затем нам нужно запустить rails g devise:install, чтобы установить devise в наше приложение.

Теперь, как вы можете видеть, следующим шагом будет запуск rails g devise:views, при этом будут созданы файлы для представления регистрации пользователя. При следующем запуске rails g devise User будет создана модель Пользователь, перенос и маршруты для регистрации пользователя.

Теперь, если мы откроем app/views, мы должны увидеть папку с именем devise, в которой размещены представления для регистрации пользователя. Теперь запустите rails db:migrate, чтобы внести эти изменения.

Пришло время запустить наш сервер и убедиться, что наше приложение работает правильно. Подойдите к терминалу и запустите rails s, сокращенно от rails server. Это запустит сервер.

Теперь, когда у нас запущен сервер, перейдите к localhost:3000 в браузере, чтобы просмотреть свое приложение.

Вы должны увидеть это приветственное сообщение! Поскольку мы также настроили Devise, вы сможете перейти к localhost:3000/users/sign_up. Вы должны увидеть полнофункциональную форму регистрации.

Большой! Теперь проверьте подписку, чтобы убедиться, что она работает. При регистрации вы должны быть перенаправлены обратно на домашнюю страницу, и никаких ошибок не должно возникать. Теперь давайте создадим несколько моделей, которые нам понадобятся для нашего банковского приложения. В терминале запускаем rails g model BankAccount user:references balance:decimal account_number:string

Будет создана Модель банковского счета, на которую ссылается Пользователь Модель, с балансом и номером счета. . запустить rails db:migrate

Теперь нам нужно создать Модель для транзакций нашей учетной записи. Беги rails g model AccountTransaction amount:decimal transaction_type:string bank_account:references transaction_number:string and run rails db:migrate

Теперь у нас есть модели, необходимые для нашего приложения, давайте включим все необходимые драгоценные камни, которые нам понадобятся для этого проекта. Нам нужно будет добавить следующие драгоценные камни в наш Gemfile

gem 'bootstrap-sass'
gem 'haml'
gem 'jquery-rails'

Мы хотим, чтобы в нашем приложении были bootstrap, jQuery и Haml. Теперь запустите bundle в терминале, чтобы установить эти драгоценные камни. Теперь, когда у нас есть эти жемчужины, давайте добавим несколько столбцов в нашу таблицу Пользователь. В настоящее время у нас есть только email и password. Я хочу, чтобы столбцы first_name last_name и middle_initial были добавлены в нашу таблицу User. В терминале запустите команду rails g migration add_name_to_users first_name:string middle_initial:string last_name:string. Теперь запустите rails db:migrate, чтобы добавить эти изменения.

Теперь нам нужно добавить Разработать строгие параметры, чтобы убедиться, что мы можем добавить эти новые столбцы в нашу базу данных из браузера. Перейдите на app/controllers/application_controller.rb, вы должны увидеть…

Теперь давайте добавим наши Разработать строгие параметры. Добавьте следующее…

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :middle_initial, :last_name])
    devise_parameter_sanitizer.permit(:sign_in, keys: [:first_name, :middle_initial, :last_name])
    devise_parameter_sanitizer.permit(:account_update, keys: [:first_name, :middle_initial, :last_name])
  end
end

Здесь мы добавляем наши новые столбцы, которые мы создали first_name last_name и middle_initial, в Разработать строгие параметры, чтобы мы могли успешно сохранить в базе данных. Теперь перейдите к app/views/devise/registrations/new, вы должны увидеть…

Отлично! Теперь добавьте в новые поля first_name middle_initial и last_name

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true %>
  </div>
  <div class="field">
    <%= f.label :first_name %><br />
    <%= f.text_field :first_name, autofocus: true %>
  </div>
  <div class="field">
    <%= f.label :middle_initial %><br />
    <%= f.text_field :middle_initial, autofocus: true %>
  </div>
  <div class="field">
    <%= f.label :last_name %><br />
    <%= f.text_field :last_name, autofocus: true %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

Отлично, теперь у нас есть новые поля для добавления полного имени пользователя, но я бы предпочел, чтобы этот код был написан на Haml, а не на ERB. Давайте преобразуем этот файл в файл Haml. Измените файл new.html.erb на new.html.haml. Формат всего изменится. В ERB у вас есть <%=, а в Haml просто =. В ERB у вас есть <%, что в Haml просто-. Если вам нужен <h2>, вы можете использовать %h2 в Haml. Вы можете найти документацию Haml здесь http://haml.info/docs.html. В результате конечный файл будет выглядеть намного чище.

%h2 Sign up

= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
  = devise_error_messages!
  .form-group
    = f.label :email
    = f.email_field :email, autofocus: true, class: 'form-control'
  .form-group
    = f.label :first_name
    = f.text_field :first_name, autofocus: true, class: 'form-control'
  .form-group
    = f.label :middle_initial
    = f.text_field :middle_initial, autofocus: true, class: 'form-control'
  .form-group
    = f.label :last_name
    = f.text_field :last_name, autofocus: true, class: 'form-control'

  .form-group
    = f.label :password
    - if @minimum_password_length
      %em
        (
        = @minimum_password_length
        characters minimum)
    %br
    = f.password_field :password, autocomplete: "off", class: 'form-control'
  .form-group
    = f.label :password_confirmation
    = f.password_field :password_confirmation, autocomplete: "off", class: 'form-control'

  .actions
    = f.submit "Sign up", class: 'btn btn-primary'
= render "devise/shared/links"

Отлично, теперь перейдите на localhost:3000/users/sign_up, и вы должны увидеть свою форму регистрации.

Если вас перенаправляют обратно на главную страницу, перейдите на localhost:3000/users/edit , нажмите отменить мою учетную запись и повторите попытку.

Теперь попробуйте зарегистрироваться, и все должно быть успешно. Чтобы проверить, успешно ли был создан пользователь, откройте PSequel, и после перезагрузки вы должны увидеть…

Отлично, теперь у нас есть возможность добавить ваше полное имя. давайте добавим для него проверки. Перейдите к app/models/user.rb, который вы должны увидеть.

Мы хотим убедиться, что пользователь ввел имя и фамилию с validates_presence_of. Код будет выглядеть следующим образом

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  validates_presence_of :first_name
  validates_presence_of :last_name

  before_save :format_name

  has_many :bank_accounts

  def format_name
    self.first_name      = self.first_name.upcase
    self.middle_initial  = self.middle_initial.upcase
    self.last_name       = self.last_name.upcase
  end

  def full_name
    "#{last_name}, #{first_name} #{middle_initial}"
  end
end

Здесь мы проверяем наличие first_name и last_name при создании нового пользователя. Перед сохранением пользователя мы хотим запустить метод format_name. format_name собирается преобразовать имя пользователя в прописные буквы. Мы также хотим указать, что пользователь has_many bank_accounts и банковский счет будут belong_to пользователем. Мы также добавили метод full_name, чтобы мы могли легко вызвать отформатированное полное имя пользователя

Теперь давайте проверим BankAccount Модель. Перейдите к app/models/bank_account.rb. Нам нужно будет написать код как таковой

class BankAccount < ApplicationRecord
  belongs_to :user

  validates :user, presence: true
  validates :account_number, presence: true, uniqueness: true
  validates :balance, presence: true, numericality: true

  has_many :account_transactions

  before_validation :load_defaults

  def load_defaults
      if self.new_record?
        self.balance = 0.00
      end
  end

  def to_s
    account_number
  end
end

Здесь мы проверяем присутствие пользователя при добавлении банковского счета, а также номер счета и баланс. Мы хотим, чтобы номер счета всегда был уникальным, и мы хотим, чтобы баланс был числом. Мы также хотим убедиться, что указали, что банковский счет has_many транзакции по счету, и перед проверкой мы хотим запустить метод load_defaults. Этот метод проверяет, был ли создан new_record?, и, если да, устанавливает баланс на 0.

Теперь давайте проверим AccountTransaction Model. Перейдите к app/models/account_transaction.rb. Нам понадобится следующий код

class AccountTransaction < ApplicationRecord
  belongs_to :bank_account

  TRANSACTION_TYPES = %w(withdrawal deposit)

  validates :bank_account, presence: true
  validates :amount, presence: true, numericality: true
  validates :transaction_type, presence: true, inclusion: { in: TRANSACTION_TYPES }
  validates :transaction_number, presence: true, uniqueness: true

  before_validation :load_defaults

  def load_defaults
    if self.new_record?
      self.transaction_number = SecureRandom.uuid
    end
  end
end

Здесь мы указываем, что транзакция по счету belongs_to является банковским счетом точно так же, как транзакции по банковскому счету has_many по счету. Мы проверяем наличие банковского счета вместе с суммой, типом транзакции и номером транзакции. Мы хотим, чтобы сумма была только числом, а тип транзакции, который мы используем, inclusion: { in: TRANSACTION_TYPES }. Этот код гарантирует, что тип транзакции может содержать только значения в constant TRANSACTION_TYPE, который представляет собой массив, содержащий «снятие средств. » или« депозит ». И перед запуском проверки мы загружаем метод load_defauilts. Этот метод проверяет, был ли new_record? и если есть, мы хотим установить номер транзакции в строку SecureRandom. Теперь давайте настроим bootstrap для работы в нашем приложении.

Перейдите к app/assets/application.js Нам потребуются эти четыре строки

//= require rails-ujs
//= require jquery
//= require jquery_ujs 
//= require bootstrap

Теперь перейдите к app/assets/stylesheets, измените файл application.css на application.scss и импортируйте библиотеку начальной загрузки.

@import "bootstrap-sprockets";
@import "bootstrap";

Теперь давайте проверим, что это работает. Перейти к app/views/devise/registraions/new.html.haml. Мы добавим в форму несколько классов начальной загрузки.

%h2 Sign up

= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
  = devise_error_messages!
  .form-group
    = f.label :email
    = f.email_field :email, autofocus: true, class: 'form-control'
  .form-group
    = f.label :first_name
    = f.text_field :first_name, autofocus: true, class: 'form-control'
  .form-group
    = f.label :middle_initial
    = f.text_field :middle_initial, autofocus: true, class: 'form-control'
  .form-group
    = f.label :last_name
    = f.text_field :last_name, autofocus: true, class: 'form-control'

  .form-group
    = f.label :password
    - if @minimum_password_length
      %em
        (
        = @minimum_password_length
        characters minimum)
    %br
    = f.password_field :password, autocomplete: "off", class: 'form-control'
  .form-group
    = f.label :password_confirmation
    = f.password_field :password_confirmation, autocomplete: "off", class: 'form-control'

  .actions
    = f.submit "Sign up", class: 'btn btn-primary'
= render "devise/shared/links"

Теперь, когда мы перейдем к localhost:3000/users/sign_up, мы должны увидеть

Отлично, у нас есть bootstrap. Теперь давайте добавим вокруг него контейнер. Внутри app/views/layouts/application.html.haml нам понадобятся следующие

!!!
%html
  %head
    %title= yield(:title)
    = csrf_meta_tags
    = stylesheet_link_tag    'application', media: 'all'
    = javascript_include_tag 'application'

  %body
    .container
      = yield

Мы обертываем тегом container все содержимое на каждой странице, чтобы обеспечить хорошее заполнение. Мы также добавляем динамический заголовок для каждой страницы с %title= yield(:title), таким образом, мы можем сказать = content_for(:title, ‘what we want in the title’) на любой странице, и мы можем изменить заголовок. Теперь форма должна выглядеть так

Большой! Теперь давайте настроим несколько маршрутов. Перейдите к config/routes.rb, нам нужно будет добавить

Rails.application.routes.draw do
  devise_for :users
  root to: 'pages#index'
end

Мы устанавливаем корневой путь так, чтобы он указывал на контроллер индекса страниц. Теперь нам нужно настроить контроллер под названием страницы. В каталоге контроллеры создайте новый файл с именем pages_controller.rb. Внутри вашего pages_controller.rb файла вам понадобятся следующие

class PagesController < ApplicationController
  before_action :authenticate_user

  def index
  end

  def authenticate_user
    unless current_user
      redirect_to '/users/sign_up'
    end
  end
end

Все, что мы здесь делали, - это всякий раз, когда пользователь нажимает на корневое действие, мы проверяем, вошел ли пользователь в систему. Если они вошли в систему, то показать страницу индекса страниц, если не перенаправить их на страница регистрации. Теперь, конечно, нам понадобится представление, поэтому перейдите к app/views и создайте каталог под названием pages. внутри страниц создайте файл с именем index.html.haml. Теперь на главной странице мы хотим показать общее количество учетных записей и общее количество пользователей. Мы просто покажем всех пользователей в базе данных и все учетные записи для простоты. В следующем уроке мы свяжем творения с Пользователи. Перейдите к app/helpers/application_helper.rb Нам понадобится следующее…

module ApplicationHelper
  def number_of_accounts
    BankAccount.count
  end

  def number_of_users
    User.count
  end
end

Здесь мы просто получаем счет для всех банковских счетов и пользователей. Теперь в app/views/pages/index.html.haml нам понадобится

= content_for(:title, 'Welcome To Your Online Banking')

%h1
  My Bank

.row
  .col-md-12
    %h2
      Number Of Accounts #{number_of_accounts}
    %h2
      Number Of Clients #{number_of_users}

.row
  .col-md-12
    = link_to bank_accounts_path do
      %i.fa.fa-building
      Bank Accounts

Если вы запустите это, вы должны получить сообщение об ошибке undefined bank_accounts_path. Нам нужно перейти к config/routes.rb и добавить resources :bank_accounts, only: [:index, :show]

Отлично, теперь в браузере мы должны увидеть…

Теперь нам нужно создать наш контроллер банковских счетов, поэтому в каталоге контроллеры создайте файл bank_accounts_controller.rb.

class BankAccountsController < ApplicationController
  def index
    @bank_accounts = BankAccount.all
  end

  def show
    @bank_account = BankAccount.find_by_id(params[:id])
  end
end

Все, что мы здесь делаем, - это устанавливаем для index переменной экземпляра @bank_account значение, равное всем записям банковского счета, и если показать действие , мы найдем конкретный банковский счет с данным идентификатором в параметрах в URL-адресе. Теперь нам понадобятся наши представления, поэтому в app/views создайте новый каталог с именем bank_accounts и добавьте index.html.haml и show.html.haml

Теперь в index.html.haml мы хотим представить таблицу, показывающую номер счета, баланс и действие.

%h1
  Bank Accounts

%table.table.table-bordered
  %thead
    %tr
      %th Account Number
      %th Balance
      %th Action
  %tbody
    - @bank_accounts.each do |bank_account|
      %tr
        %td #{bank_account.account_number}
        %td #{number_to_currency(bank_account.balance)}
        %td
          = link_to bank_account_path(bank_account.id), class: 'btn btn-primary' do
            %i.fa.fa-building
            Show

Затем мы должны увидеть в браузере…

Теперь, если мы перейдем к rails console и запустим BankAccount.create(user: User.first, account_number: “00000001”)

Мы должны открыть браузер и увидеть…

Отлично, теперь давайте настроим страницу отображения банковских счетов

%h1
  Account Number: #{@bank_account.account_number}
  %small
    #{@bank_account.user.full_name}

= button_tag :new_transaction, id: 'btn-transaction', class: 'btn btn-primary' do
  New Transaction

%table.table.table-bordered
  %thead
    %tr
      %th Date Of Transaction
      %th Transaction Type
      %th Amount
  %tbody
    - @bank_account.account_transactions.each do |t|
      %tr
        %td #{t.created_at}
        %td #{t.transaction_type}
        %td #{number_to_currency(t.amount)}
    %tr
      %th
      %th Balance
      %th #{number_to_currency(@bank_account.balance)}

#parameters{data: {bank_account_id: @bank_account.id}}
#modal-transaction.modal.fade.modal-fade
  .modal-dialog
    .modal-content
      .modal-header
        %button.close{type:'button', data:{dismiss:'modal'}}
          %span{aria:{hidden:'true'}}
            %i.fa.fa-close
          %span.sr-only Close
        %h4.modal-title
          New Transaction
      .modal-body
        .row
          .col-md-12
            .notification
        .row
          .col-md-6
            %label
              Amount
            = text_field_tag :amount, 0.00, id: 'input-amount', class: 'form-control'
          .col-md-6
            %label
              Transaction Type
            = select_tag :transaction_type, options_for_select(AccountTransaction::TRANSACTION_TYPES), id: 'select-transaction-type', class: 'form-control'
      .modal-footer
        %button.btn.btn-default{type:'button', data:{dismiss:'modal'}} Close
        %button#btn-save.btn.btn-primary{type:'button'} Save

При просмотре в браузере мы должны увидеть…

Теперь мы хотим, чтобы кнопка новой транзакции активировала запрограммированное нами модальное окно и создала новую транзакцию. нам нужно будет добавить javascript внизу нашей страницы шоу, добавьте следующее…

= javascript_include_tag('bank_accounts/show')

:javascript
  $(window).on("load", function(){
    Show.init();
  });

Мы будем использовать так называемый шаблон раскрытия в javascript для лучшей организации кода. Внутри app / assets создайте каталог bank_accounts. Внутри этого каталога создайте show.js. Необходимо будет добавить следующий код

var Show = (function(){

    var $btnNewTransaction;
    var $modalTransaction;
    var $btnSave;
    var $inputAmount;
    var $selectTransactionType;
    var $parameters;
    var $notification;

    var bankAccountId;
    var url = '/api/v1/bank_accounts/new_transaction';

    var fetchElements = function(){
        $btnNewTransaction      = $("#btn-transaction");
        $modalTransaction       = $("#modal-transaction");
        $btnSave                = $("#btn-save");
        $inputAmount            = $("#input-amount");
        $selectTransactionType  = $("#select-transaction-type");
        $parameters             = $("#parameters");
        $notification           = $(".notification");

        bankAccountId           = $parameters.data("bank-account-id");
    };

    var disableControls = function(params){
        $btnSave.prop("disabled", true);
        $inputAmount.prop("disabled", true);
        $selectTransactionType.prop("disabled", true);
    };
    var enableControls = function(params){
        $btnSave.prop("disabled", true);
        $inputAmount.prop("disabled", true);
        $selectTransactionType.prop("disabled", true);
    };

    var initializeEvents = function(){
        $btnNewTransaction.click(function(){
            $modalTransaction.modal("show");
        });

        $btnSave.click(function(){
            var amount          = $inputAmount.val();
            var transactionType = $selectTransactionType.val();
            disableControls();

            $notification.html("");
            $.ajax({
                url: url,
                method: 'POST',
                dataType: 'json',
                data: {
                    amount: amount,
                    transaction_type: transactionType,
                    bank_account_id: bankAccountId
                },
                success: function(){
                    window.location.href = "/bank_accounts/" + bankAccountId;
                },
                error: function(response){
                    $notification.html(JSON.parse(response.responseText).errors.join())
                    enableControls();
                }
            })
        });
    };

    var init = function(){
        fetchElements();
        initializeEvents();
    };

    return {
        init: init
    }
})();

Вот краткий обзор всего, что происходит. Для написания этого кода мы используем раскрывающий шаблон в javascript. Мы создаем переменную show, которую в конечном итоге вызываем в файле show.html.haml. Мы указываем, что возвращаем только функцию init. Это позволяет нам писать функции, которые мы не хотим раскрывать, но которые все еще хранятся в объекте show. метод init получит все методы jQuery. а метод initializeEvents покажет модальное окно, возьмет данные из поля ввода и передаст их в ajax запрос для передачи серверу в случае успеха. Если есть ошибка, мы проанализируем ошибки и отобразим их пользователю.

если вы запустите это, вы должны получить сообщение об ошибке. Asset was not declared to be precompiled in production.

Нужно добавить в config/intializers/assets.rb и перезапустить сервер

Rails.application.config.assets.precompile += %w( admin.js admin.css bank_accounts/show.js )

Теперь, если вы нажмете кнопку, должно появиться модальное окно. Затем нам нужно добавить наш API слой для проверки всей информации, которая отправляется обратно на сервер. Мы обсудим шаблон команд и создадим пространства имен для нашего API слоя. Мы обсудим, как получить данные из ajax запроса, проверить его, выполнить транзакцию в ruby ​​и завершить приложение в следующем руководстве! Дождитесь следующего руководства или просмотрите готовый код здесь. Https://github.com/jalenjackson/bankingAppTutorial