読者です 読者をやめる 読者になる 読者になる

東村山1丁目 diary

渋谷のIT企業から波佐見焼の会社へ転職!Webディレクション・デザイン・ECなど仕事の話から、食事や映画の感想まで。

Rails Girls More! 2012/10/7に行ってきました。

9月のRailsGirlsTokyoに続き、株式会社万葉さんでRails勉強会が開催されました。パリパリのパン(あのおしゃれでおいしいパンの名前は何というのだろう…)、ドーナツ、ロールケーキなど、おやつが大変充実していて至福のひとときを過ごしました。万葉さんのオフィスはアットホームな雰囲気でとても素敵でした。(フリーアドレスを採用、みんなで一つの大きな机を囲んで座る)

午前中は万葉の鳥居さんとherokuの相沢さんによる講座。
Railsの構成とgitの使い方について学びました。


リクエストに対するRailsアプリの動作概要

Railsアプリがリクエストをうけてレスポンスを返すまでの流れはざっくり以下の通り。
Routes(リクエストのURLとHTTPメソッドに応じて処理を行う先を決定。)

Controller(様々な処理を行い、つぎのViewに処理を渡す。)
↓  インスタンス変数(@はじめ)を代入してViewに渡す。
View(ユーザーの目に届く部分(ここではHTML)を作成。)

.rbと.erbの違いもこの時わかりました。
(※.erbは<%= %>でrubyを埋め込めるファイル)


gitの使い方

主なコマンドは以下の通り。
git init (バージョン管理をしますという宣言)
initした後に ls -a やると.git出てくる。
git add .(変更の登録・予約)
git status(確定の状況を見る)
git commit (変更を確定させる)
git show (内容見る)
git push (remoteリポジトリにlocalリポジトリの内容を送信)
git diff(差分を見る)
git checkout 〜 (〜まで戻る)
git commit -m " メッセージ " #-mでメッセージを同じ列で書き込める

※gitでherokuやgithubにpushする際に公開鍵でひっかかることが多いので、その辺りの情報を整理したい。


アプリの修正

午後はhコーチの指示のもと、Ruby on Rails Tutorial 7〜8章を参照しながら、前回のRailsGirlsで作ったブログに機能を追加しました。


▼前回からの変更点
・ログインページとサインアップページを作成し、各URLを変更。
・ヘッダーにLoginリンクを追加。
・LoginページではEmailとPasswordの入力欄を表示。
・新規ユーザーはSign up Now!リンクからName、Email、Passwordを登録。
・自分のアカウントでログインした時のみ"edit"と"destroy"を表示。
・ログイン中にヘッダーにLogged in as "name"と表示。

▼デプロイ先
http://sultry-beyond-3759.herokuapp.com/ideas


追加・変更したファイル・コードは以下の通りです。(実際に作成した順番とは違います)


データベースに項目追加。
db/migrate/~_create_users.rb

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end

ログインページへのリンク追加、ログイン中のユーザー名表示、ログアウトページへのリンク追加。
app/views/layouts/application.erbに以下を追加。
bootstrapのclass名をそのまま使用。

  <span class="navbar-text">
     <%= link_to "Login",signin_path %>
  </span>
  <span class="navbar-text pull-right">
      <% if signed_in? %>
      Logged in as
      <%= current_user.name %> 
      <%= link_to "Sign out",signout_path,method:"delete" %>
      <% end %>
 </span>

データベースに変更を加える。
db/migrate/~_add_password_digest_to_users.rb

class AddPasswordDigestToUsers < ActiveRecord::Migration
  def change
    add_column :users, :password_digest, :string
  end
end

パスワードは6文字以上でないとエラーを返す。パスワードをランダムにして送信する。
app/models/users.rb

class User < ActiveRecord::Base
  attr_accessible :name, :email, :password, :password_confirmation
  has_secure_password
    
  validates :password, presence: true, length: { minimum: 6 }
  validates :password_confirmation, presence: true 
  
  before_save :create_remember_token
  
  private
  
   def create_remember_token
      self.remember_token = SecureRandom.urlsafe_base64
   end
  
 end

モジュールの追加。
app/helpers/sessions_helper.rb

module SessionsHelper

  def sign_in(user)
    cookies.permanent[:remember_token] = user.remember_token
    self.current_user = user
  end
  
  def current_user=(user)
    @current_user = user
  end
  
  def current_user
    @current_user ||= User.find_by_remember_token(cookies[:remember_token])
  end
  
  def signed_in?
    !current_user.nil?
  end
  
  def sign_out
    self.current_user = nil
    cookies.delete(:remember_token)
  end  
end

何かを変更した。
config/environments/production.rb

Railsgirls::Application.configure do
  # Settings specified here will take precedence over those in config/application.rb

  # Code is not reloaded between requests
  config.cache_classes = true

  # Full error reports are disabled and caching is turned on
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true

  # Disable Rails's static asset server (Apache or nginx will already do this)
  config.serve_static_assets = true 

  # Compress JavaScripts and CSS
  config.assets.compress = true

  # Don't fallback to assets pipeline if a precompiled asset is missed
  config.assets.compile = true
  config.assets.initialize_on_precompile = false

  # Generate digests for assets URLs
  config.assets.digest = true

  # Defaults to Rails.root.join("public/assets")
  # config.assets.manifest = YOUR_PATH

  # Specifies the header that your server uses for sending files
  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx

  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  # config.force_ssl = true

  # See everything in the log (default is :info)
  # config.log_level = :debug

  # Prepend all log lines with the following tags
  # config.log_tags = [ :subdomain, :uuid ]

  # Use a different logger for distributed setups
  # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)

  # Use a different cache store in production
  # config.cache_store = :mem_cache_store

  # Enable serving of images, stylesheets, and JavaScripts from an asset server
  # config.action_controller.asset_host = "http://assets.example.com"

  # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
  # config.assets.precompile += %w( search.js )

  # Disable delivery errors, bad email addresses will be ignored
  # config.action_mailer.raise_delivery_errors = false

  # Enable threaded mode
  # config.threadsafe!

  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
  # the I18n.default_locale when a translation can not be found)
  config.i18n.fallbacks = true

  # Send deprecation notices to registered listeners
  config.active_support.deprecation = :notify

  # Log the query plan for queries taking more than this (works
  # with SQLite, MySQL, and PostgreSQL)
  # config.active_record.auto_explain_threshold_in_seconds = 0.5
end

サインアップページの作成。
app/views/users/new.html.erb

<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="span6 offset3">
    <%= form_for(@user) do |f| %>

      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.text_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
    <% end %>
  </div>
</div>

URLの変更。
config/routes.rb1〜11行目に以下を追加。
※resourcesがむにゃむにゃと言っていたけどなんだったか…

Railsgirls::Application.routes.draw do
  resources :users
  resources :comments

  root :to => redirect("/ideas")
  resources :ideas
  resources :sessions, only: [:new, :create, :destroy]
  
  match '/signup',  to: 'users#new'
  match '/signin',  to: 'sessions#new'
  match '/signout', to: 'sessions#destroy', via: :delete

セッション成功時のリンク先設定等。
app/controllers/session_controller.rb

class SessionsController < ApplicationController

  def new
  end

  def create
    user = User.find_by_email(params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      # Sign the user in and redirect to the user's show page.
      sign_in user
      redirect_to user
    else
      flash[:error] = 'Invalid email/password combination' # Not quite right!
      render 'new'
    end
  end

  def destroy
    sign_out
    redirect_to root_url
  end
end

なんだろう。
app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery
  include SessionsHelper
end

config周りはちょっとよくわからない。
config/environment.rb

# Load the rails application
require File.expand_path('../application', __FILE__)

# Initialize the rails application
Railsgirls::Application.initialize!

データベースに項目を追加している。
db/migrate/~_add_remember_token_to_users.rb

class AddRememberTokenToUsers < ActiveRecord::Migration
  def change
    add_column :users, :remember_token, :string
    add_index  :users, :remember_token
  end
end

サインアップページの表示部分を作成。
app/views/users/new.html.erb

<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="span6 offset3">
    <%= form_for(@user) do |f| %>

      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.text_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
    <% end %>
  </div>
</div>

サインインページの表示部分を作成。
app/view/sessions/new.html.erb

<% provide(:title, "Sign in") %>
<h1>Sign in</h1>

<div class="row">
  <div class="span6 offset3">
    <%= form_for(:session, url: sessions_path) do |f| %>

      <%= f.label :email %>
      <%= f.text_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
    <% end %>

    <p>New user? <%= link_to "Sign up now!", signup_path %></p>
  </div>
</div>

@userを定義。
app/controllers/users_controller.rb

class UsersController < ApplicationController
  
  def show
    @user = User.find(params[:id])
  end
  
  def new
    @user = User.new 
  end

  def create
    @user = User.new(params[:user])
    if @user.save
        redirect_to @user
      # Handle a successful save.
    else
      render 'new'
    end[f:id:higashimurayama1:20121008232312p:plain][f:id:higashimurayama1:20121008232328p:plain]
  end

end

名前とメールアドレスを表示。
app/views/users/show.html.erb

<%= @user.name %>, <%= @user.email %>

このモジュール使うよという宣言みたいなもの??
app/helpers/ideas_helper.rb

module IdeasHelper
end

そしてこんな感じに機能が追加されました!
f:id:higashimurayama1:20121008232312p:plain
▲TOP画面。
f:id:higashimurayama1:20121008232328p:plain
▲サインイン画面。
f:id:higashimurayama1:20121008232416p:plain
▲サインインするとリストにeditとdestroy、右上にLogin情報が表示される。


ランチはロシア料理、夕食はイタリアンのお店に連れて行っていただきました。
どちらもとてもおいしかったです…!
(そしてミモザを飲んで寝落ちしてすいませんでした)
株式会社万葉のみなさん、コーチのみなさん、参加者のみなさん、どうもありがとうございました〜。
(無料でこんなに教えていただいていいのだろうかとちょっと申しわけないような気もしつつ…。)

はー、いっちょめいっちょめ。