ごめんなさい・・・

WED(WeekEndDevelopers)のぽんたです。

開発スキルのないSIerからソフトウェアスキルを取得するため、WEDでモノづくりを計画しています。詳しい経緯はここ

現在、第5章(レイアウトを作成する)実施中です。が、ちょっと仕事がバタバタしていると他に少し私用でやらないと
いけない事あってこっちの勉強に回せてないです・・・。来週こそ少しでも勉強して記載します!!ごめんなさい・・・

レイアウトを作成する(その4)

WED(WeekEndDevelopers)のぽんたです。

開発スキルのないSIerからソフトウェアスキルを取得するため、WEDでモノづくりを計画しています。詳しい経緯はここ

現在、第5章(レイアウトを作成する)実施中です。

最近のRailsに追加された機能の中で最も特筆すべき機能の1つは、CSSJavaScript、画像などの静的コンテンツの生産性と管理を大幅に強化する「アセットパイプライン (Asset Pipeline)」というものがあります。

アセットパイプラインの概要と、素晴らしいCSS生成ツールである「Sass」の使い方について説明します。

◆アセットパイプラインの概要 Rails開発者の視点からは、アセットディレクトリ、マニフェストファイル、プリプロセッサエンジンという、3つの主要な機能が理解の対象となるそうです。

アセットディレクトRailsのアセットパイプラインでは、静的ファイルを目的別に分類する、標準的な3つのディレクトリが使われています。

- app/assets: 現在のアプリケーション固有のアセット
- lib/assets: あなたの開発チームによって作成されたライブラリ用のアセット
- vendor/assets: サードパーティのアセット 

これらのディレクトリには、それぞれのアセットクラス用のサブディレクトリがあります。例えばapp/assetsの場合を確認してみます。

  :~/develop_environment/sample_app$ ls app/assets/
  config/      images/      javascripts/ stylesheets/

◆マニュフェストファイル 静的ファイル (アセット) を上記の場所へそれぞれ配置すれば、マニフェストファイルを使って、それらをどのように1つのファイルにまとめるのかをRailsに指示することができます。なお、実際にアセットをまとめる処理を行うのはSprocketsというgemです。また、マニフェストファイルはCSSJavaScriptには適用されますが、画像ファイルには適用されません。アプリケーションのCSSマニフェストファイルを見てみます。

:~/develop_environment/sample_app$ cat app/assets/stylesheets/application.css 
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */

”*= require_tree .”はapp/assets/stylesheetsディレクトリ (サブディレクトリを含む) 中のすべてのCSSファイルが、アプリケーションCSSに含まれるようにしています。

"*= require_self"CSSの読み込みシーケンスの中で、application.css自身もその対象に含めています。

Railsには実用的なデフォルトのマニフェストファイルが付属しているので、Railsチュートリアルでは変更を加える必要がありませんが、もし必要な場合は、Railsガイドの「アセットパイプライン」で詳細な情報を参照できるそうです。

プリプロセッサエンジン
必要なアセットをディレクトリに配置してまとめた後、Railsはさまざまなプリプロセッサエンジンを介してそれらを実行し、ブラウザに配信できるようにそれらをマニフェストファイルを用いて結合し、サイトテンプレート用に準備します。Railsはどのプリプロセッサを使うのかを、ファイル名の拡張子を使って判断します。最も一般的な拡張子は、Sass用の.scss、CoffeeScript用の.coffee、埋め込みRuby (ERb) 用の.erbです。

プリプロセッサエンジンは、繋げて実行する (chain) ことができます。

foobar.js.coffee

上の拡張子の場合、CoffeeScriptプロセッサ経由で実行されます。

foobar.js.erb.coffee

上の拡張子の場合は、CoffeeScriptとERbの両方で実行されます (コードは右から左へと実行されますので、この例ではCoffeeScriptが最初に実行されます)。

◆本番環境での効率性 Asset Pipelineの最大のメリットの1つは、本番のアプリケーションで効率的になるように最適化されたアセットも自動的に生成されることです。従来は、CSSJavaScriptを整理するために、機能を個別のファイルに分割し、(インデントを多用して) 読みやすいフォーマットに整えていました。これは、プログラマにとっては便利な方法ですが、本番環境にとっては非効率です。それというのも、最小化されていないCSSJavaScriptファイルを多数に分割すると、ページの読み込み時間が著しく遅くなるからです (読み込み時間は、ユーザー体験の質に影響を与える重要な指標の1つです)。Asset Pipelineを使うと、この「開発効率と読み込み時間のどちらを重視するか」という問題について悩む必要がなくなります。開発環境ではプログラマにとって読みやすいように整理しておき、本番環境ではAsset Pipelineを使ってファイルを最小化すればよいのです。具体的には、Asset Pipelineがすべてのスタイルシートを1つのCSSファイル (application.css) にまとめ、すべてのJavaScriptファイルを1つのJSファイル (javascripts.js) にまとめてくれます。さらに、それらのファイルすべてに対して 不要な空白やインデントを取り除く処理を行い、ファイルサイズを最小化してくれます。結果として、開発環境と本番環境という、2つの異なった状況に対してそれぞれ最高の環境を提供してくれます。

今回はここまで^^なんかあまり手を動かさずに読んでばっかりでしたwでは!!

レイアウトを作成する(その3)

WED(WeekEndDevelopers)のぽんたです。

開発スキルのないSIerからソフトウェアスキルを取得するため、WEDでモノづくりを計画しています。詳しい経緯はここ

現在、第5章(レイアウトを作成する)実施中です。

パーシャルHTMLヘッダーは論理的な単位として分けられるため、一箇所にまとめた方が便利です。
Railsではパーシャルという機能でこのような課題を解決出来ます。
最初に、パーシャルを定義するとレイアウトがどのように変わるかを見てみます。

$ cat app/views/layouts/application.html.erb 
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all',
                               'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application',
                               'data-turbolinks-track': 'reload' %>
    <%= render 'layouts/shim' %>
  </head>
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>

パーシャルが動作するためには、それに対応するファイルとコンテンツを記述しなければなりません。このshimパーシャルの場合は以下のようになります。

$ cat app/views/layouts/_shim.html.erb
<!--[if lt IE 9]>
  <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
  </script>
<![endif]-->

ヘッダーの情報を以下ののパーシャルに移動し、renderを呼び出してレイアウトに挿入することができます。

$ cat app/views/layouts/_header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%= link_to "sample app", '#', id: "logo" %>
    <nav>
      <ul class="nav navbar-nav navbar-right">
        <li><%= link_to "Home",   '#' %></li>
        <li><%= link_to "Help",   '#' %></li>
        <li><%= link_to "Log in", '#' %></li>
      </ul>
    </nav>
  </div>
</header>

パーシャルの作成方法がわかりましたので、今度はヘッダーに対応するフッタを同じ方法で追加します。 ファイル名は _footer.html.erb で、layoutsディレクトリ置きます。

$ cat app/views/layouts/_footer.html.erb
<footer class="footer">
  <small>
    The <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    by <a href="http://www.michaelhartl.com/">Michael Hartl</a>
  </small>
  <nav>
    <ul>
      <li><%= link_to "About",   '#' %></li>
      <li><%= link_to "Contact", '#' %></li>
      <li><a href="http://news.railstutorial.org/">News</a></li>
    </ul>
  </nav>
</footer>

そのまま実際にfooterを表示してみるとどうにも見苦しいので、スタイルを若干追加します。

$ cat app/assets/stylesheets/custom.scss 
:
:
/* footer */

footer {
  margin-top: 45px;
  padding-top: 5px;
  border-top: 1px solid #eaeaea;
  color: #777;
}

footer a {
  color: #555;
}

footer a:hover {
  color: #222;
}

footer small {
  float: left;
}

footer ul {
  float: right;
  list-style: none;
}

footer ul li {
  float: left;
  margin-left: 15px;
}

演習1
Railsがデフォルトで生成するheadタグの部分を、リスト 5.18のようにrenderに置き換えてみてください。
ヒント: 単純に削除してしまうと後でパーシャルを1から書き直す必要が出てくるので、削除する前にどこかに退避しておきましょう。

まずは以下のようにしてapplication.html.erbを退避させる。

$ cp -p application.html.erb  application.html.erb_bak

$ cat app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= render 'layouts/rails_default' %>
    <%= render 'layouts/shim' %>
  </head>
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
    </div>
  </body>
</html>

rails sすると以下のようなエラーが出ました。

ActionView::Template::Error (Missing partial layouts/_rails_default with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}. Searched in:

layouts/_rails_defaultがないからエラーが出てるんですね。。そりゃそうですよね。。自分で↑のように指定しておいてファイルがなかったら当然のエラーですよね。。

以下のようにしてエラーをとりました。

$ cat app/views/layouts/_rails_default.html.erb

<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

演習2
リスト 5.18のようなパーシャルはまだ作っていないので、現時点ではテストは redになっているはずです。実際にテストを実行して確認してみましょう。
演習3
layoutsディレクトリにheadタグ用のパーシャルを作成し、先ほど退避しておいたコードを書き込み、最後にテストが green に戻ることを確認しましょう。
動作確認だけのためなので省略します。

今回はここまで!!では^^

レイアウトを作成する(その2)

WED(WeekEndDevelopers)のぽんたです。

開発スキルのないSIerからソフトウェアスキルを取得するため、WEDでモノづくりを計画しています。詳しい経緯はここ

現在、第5章(レイアウトを作成する)実施中です。

Bootstrapを導入してみます!Gemfileを編集していきます。

$ cat Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.4.1'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.3'
gem 'bootstrap-sass', '3.3.7'
:
:

いつものようにbundle installを実行して、Bootstrapをインストールします。 無事にインストール出来てそうです。

$ bundle install
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using rake 12.3.2
Using concurrent-ruby 1.1.5
Using i18n 1.6.0
Using minitest 5.11.3
Using thread_safe 0.3.6
Using tzinfo 1.2.5
Using activesupport 5.2.3
Using builder 3.2.3
Using erubi 1.8.0
Using mini_portile2 2.4.0
Using nokogiri 1.10.3
Using rails-dom-testing 2.0.3
Using crass 1.0.4
Using loofah 2.2.3
Using rails-html-sanitizer 1.0.4
Using actionview 5.2.3
Using rack 2.0.7
Using rack-test 1.1.0
Using actionpack 5.2.3
Using nio4r 2.4.0
Using websocket-extensions 0.1.4
Using websocket-driver 0.7.1
Using actioncable 5.2.3
Using globalid 0.4.2
Using activejob 5.2.3
Using mini_mime 1.0.2
Using mail 2.7.1
Using actionmailer 5.2.3
Using activemodel 5.2.3
Using arel 9.0.0
Using activerecord 5.2.3
Using mimemagic 0.3.3
Using marcel 0.3.3
Using activestorage 5.2.3
Using ansi 1.5.0
Using execjs 2.7.0
Fetching autoprefixer-rails 9.7.3
Installing autoprefixer-rails 9.7.3
Using bindex 0.8.1
Using msgpack 1.3.0
Using bootsnap 1.4.4
Using rb-fsevent 0.10.3
Using ffi 1.11.1
Using rb-inotify 0.10.0
Using sass-listen 4.0.0
Using sass 3.7.4
Fetching bootstrap-sass 3.3.7
Installing bootstrap-sass 3.3.7
Using bundler 2.0.2
Using byebug 11.0.1
Using coderay 1.1.2
Using coffee-script-source 1.12.2
Using coffee-script 2.4.1
Using method_source 0.9.2
Using thor 0.20.3
Using railties 5.2.3
Using coffee-rails 4.2.2
Using formatador 0.2.5
Using ruby_dep 1.5.0
Using listen 3.1.5
Using lumberjack 1.0.13
Using nenv 0.3.0
Using shellany 0.0.1
Using notiffany 0.1.1
Using pry 0.12.2
Using guard 2.13.0
Using guard-compat 1.2.1
Using guard-minitest 2.4.4
Using jbuilder 2.9.1
Using ruby-progressbar 1.10.1
Using minitest-reporters 1.1.14
Using puma 3.12.1
Using sprockets 3.7.2
Using sprockets-rails 3.2.1
Using rails 5.2.3
Using rails-controller-testing 1.0.2
Using tilt 2.0.9
Using sass-rails 5.0.7
Using spring 2.1.0
Using spring-watcher-listen 2.0.1
Using sqlite3 1.4.1
Using turbolinks-source 5.2.0
Using turbolinks 5.2.0
Using uglifier 4.1.20
Using web-console 3.7.0
Bundle complete! 21 Gemfile dependencies, 83 gems now installed.
Gems in the group production were not installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

ちなみに、rails generateコマンドを実行することでコントローラーごとに分けられたCSSファイルが自動的に生成されますが、これらのファイルを正しい順序で読み込ませるのは至難の技なので、本チュートリアルでは (簡潔のために) すべてのCSSを1つにまとめる方針を採っています。とのことです。

$ touch app/assets/stylesheets/custom.scss

カスタムCSS用のファイルを作成したら、Bootstrap (とそれに関連するSprockets) を読み込みます。

$ cat app/assets/stylesheets/custom.scss 
@import "bootstrap-sprockets";
@import "bootstrap";

rails sで起動すると以下のように無事に確認出来ました。 テキストの配置は今ひとつで、ロゴにはスタイルもありませんが、色使いとsignupボタンはなかなかよい感じになってきました。

f:id:ponta1119:20191230102149p:plain

Webサイト全体にわたってレイアウトと個別のページにスタイルを与えるためのCSSを追加します。

$ cat app/assets/stylesheets/custom.scss 
@import "bootstrap-sprockets";
@import "bootstrap";

/* universal */

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
}

.center h1 {
  margin-bottom: 10px;
}

f:id:ponta1119:20191230104937p:plain

次に 洗練されたタイポグラフィーを利用するためのCSSを追加する。

$ cat app/assets/stylesheets/custom.scss 
@import "bootstrap-sprockets";
@import "bootstrap";

/* universal */

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
}

.center h1 {
  margin-bottom: 10px;
}

/* typography */

h1, h2, h3, h4, h5, h6 {
  line-height: 1;
}

h1 {
  font-size: 3em;
  letter-spacing: -2px;
  margin-bottom: 30px;
  text-align: center;
}

h2 {
  font-size: 1.2em;
  letter-spacing: -1px;
  margin-bottom: 30px;
  text-align: center;
  font-weight: normal;
  color: #777;
}

p {
  font-size: 1.1em;
  line-height: 1.7em;
}

f:id:ponta1119:20191230105838p:plain

最後に、いくつかのルールをサイトロゴに追加します。このサイトロゴは「sample app」だけが表示されているシンプルなものです。

$ cat app/assets/stylesheets/custom.scss 
@import "bootstrap-sprockets";
@import "bootstrap";

/* universal */

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
}

.center h1 {
  margin-bottom: 10px;
}

/* typography */

h1, h2, h3, h4, h5, h6 {
  line-height: 1;
}

h1 {
  font-size: 3em;
  letter-spacing: -2px;
  margin-bottom: 30px;
  text-align: center;
}

h2 {
  font-size: 1.2em;
  letter-spacing: -1px;
  margin-bottom: 30px;
  text-align: center;
  font-weight: normal;
  color: #777;
}

p {
  font-size: 1.1em;
  line-height: 1.7em;
}

/* header */

#logo {
  float: left;
  margin-right: 10px;
  font-size: 1.7em;
  color: #fff;
  text-transform: uppercase;
  letter-spacing: -1px;
  padding-top: 9px;
  font-weight: bold;
}

#logo:hover {
  color: #fff;
  text-decoration: none;
}

f:id:ponta1119:20191230110239p:plain

演習1
↑で使ったネコ画像をコメントアウトしてみてください。また、ブラウザのHTMLインスペクタ機能を使って、コメントアウトするとHTMLのソースからも消えていることを確認してみてください。

以下のようにコメントアウトする。

$ cat app/views/static_pages/home.html.erb 
<div class="center jumbotron">
  <h1>Welcome to the Sample App</h1>

  <h2>
    This is the home page for the
    <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
  </h2>

  <%= link_to "Sign up now!", '#', class: "btn btn-lg btn-primary" %>
</div>

<%#= link_to image_tag("rails.png", alt: "Rails logo"),
            'http://rubyonrails.org/' %>

無事に画像が消える事を確認。

f:id:ponta1119:20191231174346p:plain

演習2
リスト 5.11のコードをcustom.scssに追加し、すべての画像を非表示にしてみてください。うまくいけば、Railsのロゴ画像がHomeページから消えるはずです。先ほどと同様にインスペクタ機能を使って、今度はHTMLのソースコードは残ったままで、画像だけが表示されなくなっていることを確認してみてください。

リスト 5.11: すべての画像を非表示にするCSS

img {
  display: none;
}

以下のようにコメントアウトすることで同様に画像が消えていることを確認

$ cat app/assets/stylesheets/custom.scss 
@import "bootstrap-sprockets";
@import "bootstrap";

/* universal */

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
}

.center h1 {
  margin-bottom: 10px;
}

/* typography */

h1, h2, h3, h4, h5, h6 {
  line-height: 1;
}

h1 {
  font-size: 3em;
  letter-spacing: -2px;
  margin-bottom: 30px;
  text-align: center;
}

h2 {
  font-size: 1.2em;
  letter-spacing: -1px;
  margin-bottom: 30px;
  text-align: center;
  font-weight: normal;
  color: #777;
}

p {
  font-size: 1.1em;
  line-height: 1.7em;
}

/* header */

#logo {
  float: left;
  margin-right: 10px;
  font-size: 1.7em;
  color: #fff;
  text-transform: uppercase;
  letter-spacing: -1px;
  padding-top: 9px;
  font-weight: bold;
}

#logo:hover {
  color: #fff;
  text-decoration: none;
}

img {
  display: none;
}

今回はここまで!では^^

レイアウトを作成する(その1)

WED(WeekEndDevelopers)のぽんたです。

開発スキルのないSIerからソフトウェアスキルを取得するため、WEDでモノづくりを計画しています。詳しい経緯はここ

今回から第5章(レイアウトを作成する)に入っていきます。

ふー、やっと第5章です。。。
この章では、アプリケーションにBootstrapフレームワークを組み込み、そして、カスタムスタイルを追加します。
た、これまで作成したページ (HomeやAboutなど) へのリンクをレイアウトに追加するそうです。
なんだか目に見えるものを作っていける感じでちょっと楽しくなってきました。

まずは準備としてgitでソース管理をしているのでブランチを切ります。

$ git checkout -b filling-in-layout
Switched to a new branch 'filling-in-layout'

サンプルアプリケーションにリンクとスタイルを追加するために、サイトのレイアウトファイルapplication.html.erbにhtml構造を追加し、レイアウトファイルを更新します。この更新には、領域 (divタグ) の追加、CSSクラスの追加、サイトナビゲーションの起点となる領域の追加も含まれます。

$ cat app/views/layouts/application.html.erb 
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all',
                               'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application',
                               'data-turbolinks-track': 'reload' %>
    <!--[if lt IE 9]>
      <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
      </script>
    <![endif]-->
  </head>

  <body>
    <header class="navbar navbar-fixed-top navbar-inverse">
      <div class="container">
        <%= link_to "sample app", '#', id: "logo" %>
        <nav>
          <ul class="nav navbar-nav navbar-right">
            <li><%= link_to "Home",   '#' %></li>
            <li><%= link_to "Help",   '#' %></li>
            <li><%= link_to "Log in", '#' %></li>
          </ul>
        </nav>
      </div>
    </header>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>

今後のスタイル要素を利用するために、home.html.erbビューに特別な要素をいくつか追加します。

$ cat app/views/static_pages/home.html.erb 
<div class="center jumbotron">
  <h1>Welcome to the Sample App</h1>

  <h2>
    This is the home page for the
    <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
  </h2>

  <%= link_to "Sign up now!", '#', class: "btn btn-lg btn-primary" %>
</div>

<%= link_to image_tag("rails.png", alt: "Rails logo"),
            'http://rubyonrails.org/' %>

Ruby on Rails公式ページの https://railstutorial.jp/rails.png から画像をダウンロードして、app/assets/images/ディレクトリにおきます。

$ curl -o app/assets/images/rails.png -OL railstutorial.jp/rails.png
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 13036  100 13036    0     0   5250      0  0:00:02  0:00:02 --:--:--  8604
$ rails s
=> Booting Puma
=> Rails 5.2.3 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.4.1-p111), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000

http://localhost:3000/static_pages/homeにアクセスすることで確認できました。

f:id:ponta1119:20191229141234p:plain

演習1
Webページと言ったらネコ画像、というぐらいにはWebにはネコ画像が溢れていますよね。リスト 5.4のコマンドを使って、図 5.3のネコ画像をダウンロードしてきましょう。

以下(リスト5.4)の通り実施しました。

$ curl -OL cdn.learnenough.com/kitten.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
100  138k  100  138k    0     0  47102      0  0:00:03  0:00:03 --:--:-- 86923

このままだと、app/assets/images/ディレクトリに配置されないんですよね。念のために確認します。

~/develop_environment/sample_app$ ls
Gemfile       README.md     app/          config/       db/           lib/          package.json  storage/      tmp/
Gemfile.lock  Rakefile      bin/          config.ru     kitten.jpg    log/          public/       test/         vendor/

演習2
mvコマンドを使って、ダウンロードしたkitten.jpgファイルを適切なアセットディレクトリに移動してください (参考: 5.2.1)。
app/assets/images/に配置するって事なのでしょうか?やってみます。

$ mv kitten.jpg ./app/assets/images/
$ ls app/assets/images/
kitten.jpg  rails.png

演習3
image_tagを使って、kitten.jpg画像を表示してみてください (図 5.4)。

演習2ではファイルを移動させるところまでやりました。
ただこのままだとファイル名の関係で表示させる事が出来ないため、rails.pngを退避させて kitten.jpgをrails.pngにリネームしてやります。

$ cd app/assets/images/
$ mkdir bak
$ mv rails.png ./bak/
$ mv kitten.jpg rails.png 
$ rails s
=> Booting Puma
=> Rails 5.2.3 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.4.1-p111), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop

f:id:ponta1119:20191229141318p:plain

無事確認することが出来ました!!

今回はここまで!では^^

Rails風味のRuby(その11)

WED(WeekEndDevelopers)のぽんたです。

開発スキルのないSIerからソフトウェアスキルを取得するため、WEDでモノづくりを計画しています。詳しい経緯はここ
※現在はruby on railsチュートリアル(ここから)を進めていってます。

この章ではRubyの基礎知識を学んでいきます。(前回までの続き)
Ruby を学ぶためのツールとして、主にRailsコンソールを使っていくことにします。

最後に完全なクラスを作成して、この章を終わりにします。そこで、第6章で使う User クラスを最初から作成することにします。

これまではコンソール上でクラスを定義しましたが、このような面倒な作業はもう行いたくありません。 これからは、アプリケーションのルートディレクトリにexample_user.rbファイルを作成します。

syo4118@nishiyama-kake-no-MacBook-Pro:~/develop_environment/sample_app$ cat example_user.rb

class User
  attr_accessor :name, :email

  def initialize(attributes = {})
    @name  = attributes[:name]
    @email = attributes[:email]
  end

  def formatted_email
    "#{@name} <#{@email}>"
  end
end

"attr_accessor :name, :email"の意味についての説明です。

ユーザー名とメールアドレス (属性: attribute) に対応するアクセサー (accessor) をそれぞれ作成します。 アクセサーを作成すると、そのデータを取り出すメソッド (getter) と、データに代入するメソッド (setter) を それぞれ定義してくれます。

具体的には、この行を実行したことにより、インスタンス変数@nameとインスタンス変数@emailに アクセスするためのメソッドが用意されます。

インスタンス変数は常に@記号で始まり、まだ定義されていなければ値がnilになります。

attributes変数は空のハッシュをデフォルトの値として持つため、名前やメールアドレスのない ユーザーを作ることができます。

Railsコンソールを起動し、example_userのコードをrequireして、自作したクラスを試しに使ってみます。

>> require './example_user'     # example_userのコードを読み込む方法
=> true
>> example = User.new
=> #<User:0x007fe7bc8fe430 @name=nil, @email=nil>
>> example.name                 # attributes[:name]は存在しないのでnil
=> nil
>> example.name = "Example User"           # 名前を代入する
=> "Example User"
>> example.email = "user@example.com"      # メールアドレスを代入する
=> "user@example.com"
>> example.formatted_email
=> "Example User <user@example.com>"

他のユーザを作成してみます。

?> user = User.new(name: "Michael Hartl", email: "mhartl@example.com")
=> #<User:0x007fe7bc875220 @name="Michael Hartl", @email="mhartl@example.com">
>> user.formatted_email
=> "Michael Hartl <mhartl@example.com>"

演習1
Userクラスで定義されているname属性を修正して、first_name属性とlast_name属性に分割してみましょう。また、それらの属性を使って "Michael Hartl" といった文字列を返すfull_nameメソッドを定義してみてください。最後に、formatted_emailメソッドのnameの部分を、full_nameに置き換えてみましょう (元々の結果と同じになっていれば成功です)

以下の通り修正した

cat example_user.rb 
class User
  attr_accessor :first_name,:last_name, :email

  def initialize(attributes = {})
    @first_name = attributes[:first_name]
    @last_name = attributes[:last_name]
    @email = attributes[:email]
  end

  def full_name
    @full_name = "#{@first_name} #{@last_name}"
  end

  def formatted_email
    "#{@full_name} <#{@email}>"
  end
end

consoleで実行してみます。

?> require './example_user'
=> true
>> user = User.new(first_name: "Michael", last_name: "Hartl", email: "mhartl@example.com")
=> #<User:0x007fe7bccc0b40 @first_name="Michael", @last_name="Hartl", @email="mhartl@example.com">
>> user.full_name
=> "Michael Hartl"
>> user.formatted_email
=> "Michael Hartl <mhartl@example.com>"

演習2
"Hartl, Michael" といったフォーマット (苗字と名前がカンマ+半角スペースで区切られている文字列) で返すalphabetical_nameメソッドを定義してみましょう。

演習1で作成したUserクラスを使ってみます。alphabetical_nameを追加です。

$ cat example_user.rb 
class User
  attr_accessor :first_name,:last_name, :email

  def initialize(attributes = {})
    @first_name = attributes[:first_name]
    @last_name = attributes[:last_name]
    @email = attributes[:email]
  end

  def full_name
    @full_name = "#{@first_name} #{@last_name}"
  end

   def alphabetical_name
     @alphabetical_name = "#{@last_name}, #{@first_name}"
   end

  def formatted_email
    "#{@full_name} <#{@email}>"
  end
end

そしてconsoleで実行してみます。

?> require './example_user'
=> true
>> user = User.new(first_name: "Michael", last_name: "Hartl", email: "mhartl@example.com")
=> #<User:0x007fe7ba796180 @first_name="Michael", @last_name="Hartl", @email="mhartl@example.com">
>> user.alphabetical_name
=> "Hartl, Michael"

演習3
full_name.splitとalphabetical_name.split(', ').reverseの結果を比較し、同じ結果になるかどうか確認してみましょう。

以下の通り実施して同じ結果になっていることを確認しました。

>> user.full_name.split
=> ["Michael", "Hartl"]
>> user.alphabetical_name.split(', ').reverse
=> ["Michael", "Hartl"]

演習までしっかりやってブログ書くとなかなか長かったですね。。。とりあえず4章はこれで終わりです!!
今度は5章やります!!では^^

Rails風味のRuby(その10)

WED(WeekEndDevelopers)のぽんたです。

開発スキルのないSIerからソフトウェアスキルを取得するため、WEDでモノづくりを計画しています。詳しい経緯はここ
※現在はruby on railsチュートリアル(ここから)を進めていってます。

この章ではRubyの基礎知識を学んでいきます。(前回までの続き)
Ruby を学ぶためのツールとして、主にRailsコンソールを使っていくことにします。

これまでクラスや継承を勉強してきました。前の章でも似たような事やりました。

class StaticPagesController < ApplicationController

  def home
  end

  def help
  end

  def about
  end
end

StaticPagesControllerはApplicationControllerを継承して定義されるhomeやhelp、aboutアクションを見ます。

?> controller = StaticPagesController.new
=> #<StaticPagesController:0x007fe7bd0ec9d0 @_action_has_layout=true, @_routes=nil, @_request=nil, @_response=nil>
>> controller.class
=> StaticPagesController
>> controller.class.superclass
=> ApplicationController
>> controller.class.superclass.superclass
=> ActionController::Base
>> controller.class.superclass.superclass.superclass
=> ActionController::Metal
>> controller.class.superclass.superclass.superclass.superclass
=> AbstractController::Base
>> controller.class.superclass.superclass.superclass.superclass.superclass
=> Object

Railsコンソールでは、その中からコントローラのアクション (実はメソッド) を呼ぶこともできます。

>> controller.home
=> nil

ここでは、homeアクションの中身は空なのでnilが返されます。

ここで重要な点があります。Railsのアクションには戻り値がありません。少なくとも、返される値は重要ではありません。第3章で示したとおり、home アクションはWebページを表示するためのものであり、値を返すためのものではありませんでした。しかも、第3章では一度もStaticPagesController.newを実行しませんでした。どうしてこれでうまくいっているのでしょうか。

実は、Railsは確かにRubyで書かれていますが、既にRubyとは別物なのです。Railsのクラスは、普通のRubyオブジェクトと同様に振る舞うものもありますが、多くのクラスにはRailsの魔法の粉が振りかけられています。Railsは独特であり、Rubyとは切り離して学習する必要があります。

演習1
第2章で作ったToyアプリケーションのディレクトリでRailsコンソールを開き、User.newと実行することでuserオブジェクトが生成できることを確認してみましょう。

?> User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>

演習2

生成したuserオブジェクトのクラスの継承階層を調べてみてください。  
>> User.superclass
=> ApplicationRecord(abstract)
>> User.superclass.superclass
=> ActiveRecord::Base
>> User.superclass.superclass.superclass
=> Object
>> User.superclass.superclass.superclass.superclass
=> BasicObject

今回はここまで次回また続きをやっていきます^^