図書管理システムkaritakkeの製作記です。単なる備忘録です。
過去の投稿は以下から!
モデルの追加
本と貸出明細とログを管理するモデルを追加しておきます。
$ rails g model Book title:string author:string manufacturer:string publication_date:string image:string isbn:string place:string rental_count:integer book_code:string
$ rails g model Rental rental_date:datetime Book:references User:references Log:references
$ rails g model Log rental_date:datetime return_date:datetime book_id:integer user_id:integer
$ rake db:migrate
コントローラーも追加します。
$ rails g controller Books
$ rails g controller Rentals
ルーティングの設定を追加します。config/routes.rb
に以下を追加します。
resources :books
resources :rentals
次にアソシエーションの設定をします。app/models/user.rb
に以下を追加します。
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
enum role: {admin: 'admin', member: 'member'}
# 以下を追加
has_many :rentals
validates :name, presence: true
end
app/models/book.rb
に以下を追加します。
class Book < ActiveRecord::Base
# 以下を追加
has_one :Rental
validates :title, :author, :manufacturer, :publication_date, :isbn, :book_code, presence: true
end
app/models/rental.rb
はすでに以下のようになっていると思います。
class Rental < ActiveRecord::Base
belongs_to :Log
belongs_to :Book
belongs_to :User
end
Viewの編集
先ほど作成したコントローラーに対応するViewを作っていきます。編集したもの全て記載しておきます。
下準備
下準備として新たにboostrap_form
というGemを使えるようにします。Gemfile
に追加して
$ bundle install
を実行したらapp/assets/stylesheets/application.css
に以下を追加します。
*= require rails_bootstrap_forms
さらに、app/assets/stylesheets/rails_bootstrap_forms.css
というファイルを作成します。
.rails-bootstrap-forms-date-select select,
.rails-bootstrap-forms-time-select select,
.rails-bootstrap-forms-datetime-select select {
display: inline-block;
width: auto;
}
.rails-bootstrap-forms-error-summary {
margin-top: 10px;
}
これで下準備は完了です。
books
本一覧を表示し、新しい本を登録できるようにします。
一覧画面
<h1>蔵書一覧</h1>
<%= link_to "本の追加", new_book_path, :class => "btn btn-primary" %><br>
<hr>
<% if @books.any? %>
<table class="table table-bordered table-hover">
<thead>
<tr class="info"><th>ID</th><th>Titile</th><th>Author</th><th>Manufacture</th><th>Release</th><th>Operation</th></tr>
</thead>
<tbody>
<% @books.each do |b| %>
<tr>
<td><%= b.id %></td>
<td><%= b.title %></td>
<td><%= b.author %></td>
<td><%= b.manufacturer %></td>
<td><%= b.publication_date %></td>
<td width="230" align="center">
<div class="btn-group">
<%= link_to 'Show', book_path(b.id), class: "btn btn-info" %>
<%= link_to 'Edit', edit_book_path(b.id), class: "btn btn-success" %>
<%= link_to 'Destroy', book_path(b.id), method: :delete, data: { confirm: "削除してもよろしいですか?" }, :class => "btn btn-danger" %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<h4>No data yet.</h4>
<% end %>
本の追加画面
AmazonAPIを使ってISBNから本の情報を取得できるように後ほどしたいので、検索ボタンを設置しておきます。
<h1>本の追加</h1>
<%= bootstrap_form_for(@book) do |f| %>
<%= f.text_field :isbn %>
<input class="btn btn-danger" type="button" id="info_search_button" value="検索">
<hr>
<%= f.text_field :title %>
<%= f.text_field :author %>
<%= f.text_field :manufacturer %>
<%= f.text_field :publication_date %>
<%= f.text_field :book_code %>
<%= f.primary "本を追加" %>
<% end %>
本の詳細画面
<h1>本の詳細</h1>
<table class="table table-bordered">
<tbody>
<tr>
<td width="100", class="info">タイトル</td> <td><%= @book.title %></td>
</tr>
<tr>
<td width="100", class="info">著者</td> <td><%= @book.author %></td>
</tr>
<tr>
<td width="100", class="info">出版社</td> <td><%= @book.manufacturer %></td>
</tr>
<tr>
<td width="100", class="info">出版日</td> <td><%= @book.publication_date %></td>
</tr>
<tr>
<td width="100", class="info">ISBN</td> <td><%= @book.isbn %></td>
</tr>
<tr>
<td width="100", class="info">管理番号</td> <td><%= @book.book_code %></td>
</tr>
</tbody>
</table>
本の編集画面
<h1>本の編集</h1>
<%= bootstrap_form_for(@book) do |f| %>
<%= f.text_field :isbn %>
<%= f.text_field :title %>
<%= f.text_field :author %>
<%= f.text_field :manufacturer %>
<%= f.text_field :publication_date %>
<%= f.text_field :book_code %>
<%= f.primary "本を編集" %>
<% end %>
Rentals
本の貸出・返却処理をできるようにし、貸出図書一覧を表示できるようにします。
一覧画面
<h1>貸出中図書一覧</h1>
<%= link_to "本の貸出", new_rental_path, class: "btn btn-primary" %>
<hr>
<% if @rentals.any? %>
<table class="table table-bordered table-hover">
<thead>
<tr class="info"><th>#</th><th>タイトル</th><th>貸出日時</th><th>返却処理</th></tr>
</thead>
<tbody>
<% @rentals.each_with_index do |r, i| %>
<tr>
<td><%= i+1 %></td>
<td><%= r.Book.title %></td>
<td><%= r.rental_date.in_time_zone('Tokyo') %></td>
<td width="100" align="center">
<%= link_to '返却', rental_path(r.id), method: :delete, data: { confirm: "この本を返却します。よろしいですか?" }, :class => "btn btn-danger" %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<h4>No data yet.</h4>
<% end %>
新規貸出画面
こちらも本の管理番号(book_code)を入力したらデータベースから該当する本の情報を補完できるように、検索ボタンを設置しておきます。また、エラーメッセージなども表示できるようにしておきます。
<h1>本の貸出</h1>
<%= bootstrap_form_for(@book, :url => rentals_path) do |f| %>
<%= f.text_field :book_code %>
<input class="btn btn-danger" type="button" id="search_button", value="検索">
<b id="error_msg"> </b>
<hr>
<%= f.text_field :title, :readonly => true %>
<%= f.text_field :author, :readonly => true %>
<%= f.text_field :manufacturer, :readonly => true %>
<%= f.text_field :id, :readonly => true %>
<%= f.primary "貸出", id: "rental_button", disabled: "disabled" %>
<% end %>
Controllerの編集
Books
Bookモデルに対応するコントローラです。destroyメソッドで削除しようとしている本が貸出中の場合は削除できないようにしています。
AmazonAPIから情報を取得する部分は次回実装します。
class BooksController < ApplicationController
before_action :set_book, only: [:show, :edit, :update, :destroy]
def index
@books = Book.all
end
def show
end
def new
@book = Book.new
end
def create
@book = Book.new(book_params)
if @book.save
redirect_to books_path
else
render 'new'
end
end
def edit
end
def update
if @book.update(book_params)
redirect_to books_path
else
render 'edit'
end
end
def destroy
if @book.Rental_id.nil?
@book.destroy
redirect_to books_path
else
redirect_to books_path, notice: "その本は貸出中のため削除できません。"
end
end
private
def book_params
params[:book].permit(:title, :author, :manufacturer, :publication_date, :isbn, :book_code)
end
def set_book
@book = Book.find(params[:id])
end
end
Rentals
以下のようになります。createメソッドでは入力フォームに入力された情報を元に、貸し出す本を検索します。そして、モデルオブジェクトを生成し、UserとBookの紐付け、および貸出日時をセットします。さらに、貸し出す本の貸出回数のカウントをインクリメントしてRentalと紐付けをします。
destroyメソッドは本の返却を意味します。該当する本から紐付けを解除します。
class RentalsController < ApplicationController
def index
@rentals = current_user.Rentals.all
end
def new
@book = Book.new
@rental = Rental.new
end
def create
@book = Book.find(params[:book].require(:id))
if @book.Rental_id.nil?
@rental = Rental.new(rental_date: DateTime.now)
@rental.User = current_user
@rental.Book = @book
if @rental.save
@book.increment(:rental_count)
@book.Rental_id = @rental.id
@book.save
redirect_to rentals_path
else
render 'new'
end
else
redirect_to new_rental_path, notice: "その本はすでに貸出中です。"
end
end
def destroy
@rental = current_user.Rentals.find(params[:id])
@rental.Book.update(Rental_id: nil)
@rental.destroy
redirect_to rentals_path
end
end
今回はここまで!
次回はjQueryとAjaxを使ってフォームの自動入力を実装する予定です。