americandog1993の日記

プログラマー歴半年のメモ

合ってるはずなのにエラーが出る時

$rails s

の再起動を試してみる。
特にbundle installとbundle updateした後は必須っぽい?

Bootstrapサイトをスマホ対応させる

勝手にいい感じにレスポンシブデザインにしてくれるという触れ込みのBootstrap。
でもなぜかスマホでPCレイアウト表示される時。

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">

headタグの中にこいつを入れる。
css読み込みより上に置かないと駄目っぽい?

超シンプル家計簿

筆者zenfone3では劇的なスマホレイアウト化を確認。
スマホでご覧の皆様どうでしょう。

参考
【CSS】スマホで Media Queries が効かないときの対処法 - Qiita

.buildで空要素ができている

<%= @now.year %>年<%= @now.month %>月の支出:<%= @total %>円
  <%= form_for [@user, @user.kakeibos.build] do |f| %>
  <%= f.label :spending %>
  <%= f.number_field :spending %>
  <%= f.submit %>
  <% end %>
<ul>
<% @user.kakeibos.each do |k| %>
    <li>
      <%= k.spending %>円
    </li>
<% end %>
</ul>
<%= link_to "logout", logout_path %>

なんかこうしたら空の

  • が一個できてしまう。

    f:id:americandog1993:20170506234541p:plain

    こんな感じ。円だけのリストが一個ある。

    どうも、

    <%= form_for [@user, @user.kakeibos.build] do |f| %>

    の部分で@user.kakeibosに一個空のkakeiboができてしまうっぽい。

    <ul>
    <% @user.kakeibos.each do |k| %>
        <% if k.spending %>
        <li>
          <%= k.spending %>円
        </li>
      <% end %>
    <% end %>
    </ul>

    こうやって中身がfalseのものを除外することでとりあえず解決した。
    コードがすごく汚いのは自覚している。

  • マイ家計簿アプリを作る①

    思い立ったが吉日。

    概要

    • ユーザー登録は後回し。自分だけ使えるようにしてみる。
    • とりあえず金額入力して保存できるようにする。
    • 合計支出を表示してみる。
    • デザインも後回し。

    環境

    • Cloud9 RubyonRails
    • Ruby 2.3.0
    • Rails 5.0.0.1

    Gemfile

    source 'https://rubygems.org'
    
    gem 'rails',        '5.0.0.1'
    gem 'bcrypt',       '3.1.11'
    gem 'puma',         '3.4.0'
    gem 'sass-rails',   '5.0.6'
    gem 'uglifier',     '3.0.0'
    gem 'coffee-rails', '4.2.1'
    gem 'jquery-rails', '4.1.1'
    gem 'turbolinks',   '5.0.1'
    gem 'jbuilder',     '2.4.1'
    
    group :development, :test do
      gem 'sqlite3', '1.3.11'
      gem 'byebug',  '9.0.0', platform: :mri
    end
    
    group :development do
      gem 'web-console',           '3.1.1'
      gem 'listen',                '3.0.8'
      gem 'spring',                '1.7.2'
      gem 'spring-watcher-listen', '2.0.0'
    end
    
    group :production do
      gem 'pg', '0.18.4'
    end
    

    取り込む。

    $ bundle update
    $ bundle install

    ログイン

    Sessionコントローラを作る。

    $ rails g controller Sessions new
    # sessions_controller.rb
    
    class SessionsController < ApplicationController
      def new
      end
      
      def create
        user = User.find_by(name: params[:session][:name])
        if user && user.authenticate(params[:session][:password])
          session[:user_id] = user.id
          redirect_to user
        else
          render 'new'
        end
      end
    end
    
    #new.html.erb
    <h1>Log in</h1>
    <%= form_for(:session, url: login_path) do |f| %>
    
      <%= f.label :name %>
      <%= f.text_field :name %>
    
      <%= f.label :password %>
      <%= f.password_field :password %>
    
      <%= f.submit "Log in"%>
    <% end %>

    ログイン周りの便利メソッドを定義しておく。

    #sessions_helper.rb
    
    module SessionsHelper
    
      def log_in(user)
        session[:user_id] = user.id
      end
    
      def current_user
        @current_user ||= User.find_by(id: session[:user_id])
      end
    
      def logged_in?
        !current_user.nil?
      end
    end
    

    ユーザ

    とりあえずUserモデル作る。

    $ rails g model User name password_digest
    $ rails db:migrate
    #user.rb
    
    class User < ApplicationRecord
        has_many :kakeibos
        has_secure_password
    end
    

    自分を登録しておく。

    $ rails c
    > User.create(name: "americandog", password: "foobar")

    Userコントローラとビューも。

    $ rails g controller Users new create show
    #users_controller.rb
    
    class UsersController < ApplicationController
      def new
      end
    
      def create
      end
      
      def show
        @user ||= User.find_by(id: session[:user_id])
        if !@user.nil?
          @total = 0
          @user.kakeibos.each do |k| @total += k.spending end
          render 'show'
        else
          redirect_to login_path
        end
      end
    end
    
    # show.html.erb
    
    合計支出:<%= @total %>円
    <ul>
    <% @user.kakeibos.each do |k| %>
    <li><%= k.spending %>円</li>
    <% end %>
    <li>
      <%= form_for [@user, @user.kakeibos.build] do |f| %>
      <%= f.label :spending %>
      <%= f.number_field :spending %>
      <%= f.submit %>
      <% end %>
    </li>
    </ul>

    newとshowは今は手をつけない。

    家計簿

    $ rails g model Kakeibo spending:integer user:references
    $ rails db:migrate
    #kakeibo.rb
    
    class Kakeibo < ApplicationRecord
      belongs_to :user
      validates :spending, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
    end
    

    続いてコントローラ。

    $ rails g controller Kakeibos
    #kakeibos_controller.rb
    
    class KakeibosController < ApplicationController
      def create
        @user = User.find(params[:user_id])
        @kakeibo = @user.kakeibos.create(kakeibo_params)
        redirect_to user_path(@user.id)
      end
      
      private
        def kakeibo_params
          params[:kakeibo].permit(:spending)
        end
    end
    

    Herokuデプロイ

    Herokuにあげたい場合。

    $ git init
    $ git add -A
    $ git commit -m "First Commit"
    $ heroku create
    $ git push heroku master
    $ heroku run rake db:migrate
    $ heroku run rails c
    > User.create(name: "americandog", password: "foobar")

    今後

    続きは次回。
    あとやるべきことは・・・

    • デザインをBootStrapで整える。
    • 月単位・日単位で管理できるようにする。
    • ユーザ登録機能の実装。

    現時点の課題はこんなものだろうか。

    俺が考えた最弱の家計簿アプリ

    なんか今できるレベルの範囲でこんな家計簿Webアプリ作ろっかなーというの。
    RoRで。

    • 金額のみ入力。食費だの交通費だのの項目は設けない。
    • 給料日と予算を登録。給料日までのカウントダウンと残り予算が表示される。
    • 一ヶ月でリセットされる。

    めっちゃシンプルにしてGW中に試作できたらいいなーとか。

    Railsで超シンプルなログインシステムを作ってみる

    ※これはただの初心者の勉強記録なのでもし参考にされる場合は充分注意・自己責任の上ご利用ください。また、間違いがありましたらコメント頂けると幸いです。

    Railsチュートリアル8章までを三回くらいやってやっとおぼろげにわかってきた・・・かもしれない。

    作りたいもの

    • nameとpasswordでログインできるシステム。
    • userは自分だけ。
    • ユーザ登録等の機能はなし。

    環境

    • Cloud9 RubyonRails
    • Ruby 2.3.0p0
    • Rails 5.0.0.1

    Gemfile

    source 'https://rubygems.org'
    
    gem 'rails',        '5.0.0.1'
    gem 'bcrypt',       '3.1.11'
    gem 'puma',         '3.4.0'
    gem 'sass-rails',   '5.0.6'
    gem 'uglifier',     '3.0.0'
    gem 'coffee-rails', '4.2.1'
    gem 'jquery-rails', '4.1.1'
    gem 'turbolinks',   '5.0.1'
    gem 'jbuilder',     '2.4.1'
    
    group :development, :test do
      gem 'sqlite3', '1.3.11'
      gem 'byebug',  '9.0.0', platform: :mri
    end
    
    group :development do
      gem 'web-console',           '3.1.1'
      gem 'listen',                '3.0.8'
      gem 'spring',                '1.7.2'
      gem 'spring-watcher-listen', '2.0.0'
    end
    
    group :production do
      gem 'pg', '0.18.4'
    end

    Railsチュートリアルから引っ張ってきたのでけっこう不要なのも混ざってると思う。
    とりあえず取り込む。

    $ bundle update
    $ bundle install

    Userモデル

    Userを作って自分のnameとパスワードを入れる。

    $ rails g model User name:string password_digest:string
    $ rails db:migrate

    カラムはこれだけでOK。
    できたモデルにパスワードをそのまま保存しないためのおまじないを追加。

    models/user.rb

    class User < ApplicationRecord
        has_secure_password
    end
    

    シンプルイズベスト。
    登録機能ないのでバリデーションも不要。

    モデルができたので自分がログインするための情報を入れる。

    $ rails c
    > User.create(name: "americandog", password: "foobar", password_confirmation: "foobar")

    カラム名をpassword_digestにしてhas_secure_password入れるといつの間にかpasswordとpassword_confirmationを入れる仕様になってる。
    この辺の理解を流してしまってるので要復習。

    Sessionsコントローラ

    コントローラでログイン認証やらの操作を色々する。

    まずコントローラを作る。
    ビューはログイン画面(new)とログイン成功画面(create)を作る。

    $ rails g controller Sessions new create

    newをログイン画面にする。

    views/sessions/new.html.erb

    <h1>Log in</h1>
    <%= form_for(:session, url: login_path) do |f| %>
    
      <%= f.label :name %>
      <%= f.text_field :name %>
    
      <%= f.label :password %>
      <%= f.password_field :password %>
    
      <%= f.submit "Log in"%>
    <% end %>
    

    createはなんでもいいが、今回はLogined!と表示させる。

    view/create.html.erb

    Logined!
    

    続いてコントローラの設定。

    class SessionsController < ApplicationController
      def new
      end
      
      def create
        user = User.find_by(name: params[:session][:name])
        if user && user.authenticate(params[:session][:password])
          render 'create'
        else
          render 'new'
        end
      end
    end
    

    入力されたnameとpasswordが正しければcreateにいく。
    つまりLogined!が表示される。
    間違っていれば再びnewを表示。
    エラー文を出すとなおいいのだけどそれはまた今度ということで(Railsチュートリアルにも載ってるしね)。

    routes

    config/routes.rb

    Rails.application.routes.draw do
      root 'sessions#new'
      get    '/login',   to: 'sessions#new'
      post   '/login',   to: 'sessions#create'
    end
    

    見てみる

    $ rails s -b $IP -p $PORT

    f:id:americandog1993:20170505130018p:plain

    貧相なログイン画面が出てくるのでさっき設定したnameとpasswordを入力する。

    f:id:americandog1993:20170505130130p:plain

    成功。
    name、passwordが違うと再びログイン画面が表示される。

    GWでやりたいこと

    絶対やる

    • ドットインストール Javascript入門を完了(今半分くらい)
    • ドットインストール C#入門を完了(まったくやってない)
    • Railチュートリアル 8章まで(もうやった)
    • Webを支える技術を買う
    • オブジェクト指向でなぜつくるのかを買う
    • 亀の水を換える(やった)
    • 部屋を掃除する(まったくやってない)

    極力やる

    • リーダブルコードざっと読了
    • Webを支える技術ざっと読了

    できれば

    • 放置してたUnity5の教科書をちょっとでも進める
    • オブジェクト指向でなぜつくるのかを読み始める

    やりたいことが散らかり過ぎて何もできるようにならない危惧がある。
    でもどうせ他のこと我慢して一つのことシコシコやるとかできない性分なので全部中途半端に触ってみてそれなりに納得したらどれを伸ばしていくかを決めよう。