#5 Pingendoでレイアウトの作成

モックレベルの動作を目指して、要素の配置を確認するためにレイアウトを作成します。今回は、知人の紹介で気になっていたPingendoを使ってみたいと思います。

以下の2画面をつくります。

  • トップページ
  • 質問閲覧ページ

早速Pingendoのサイトからダウンロードして、トップページをつくりました。

f:id:tsyknsr:20160629225017p:plain

続いて質問閲覧ページをつくります。

f:id:tsyknsr:20160629230849p:plain

用意されているコンポーネントを配置していくだけで、おおまかなレイアウトを作成することができました。作成した画面は、そのままHTMLに出力されるので次回Twitter Bootstrapの導入とレイアウトの適用を合わせて行いたいと思います。

参考

#4 回答機能の作成

第4回では、質問に回答する機能をつくります。

質問への回答機能

scaffoldを使用してテンプレートを作成します。

$ rails g scaffold answer user:references question:references content:text

生成されたマイグレーションファイルのquestion項目にnull: falseを追加して実行します。

$ rake db:migrate

routes.rbにルーティングの設定を追加します。色々な考え方があると思いますが、今回は下記のように設定しました。

resources :questions do
  resources :answers
end

現在の状態を確認します。ルーティングの設定は、開発の過程で変更する可能性もあります。

    question_answers GET    /questions/:question_id/answers(.:format)          answers#index
                     POST   /questions/:question_id/answers(.:format)          answers#create
 new_question_answer GET    /questions/:question_id/answers/new(.:format)      answers#new
edit_question_answer GET    /questions/:question_id/answers/:id/edit(.:format) answers#edit
     question_answer GET    /questions/:question_id/answers/:id(.:format)      answers#show
                     PATCH  /questions/:question_id/answers/:id(.:format)      answers#update
                     PUT    /questions/:question_id/answers/:id(.:format)      answers#update
                     DELETE /questions/:question_id/answers/:id(.:format)      answers#destroy
           questions GET    /questions(.:format)                               questions#index
                     POST   /questions(.:format)                               questions#create
        new_question GET    /questions/new(.:format)                           questions#new
       edit_question GET    /questions/:id/edit(.:format)                      questions#edit
            question GET    /questions/:id(.:format)                           questions#show
                     PATCH  /questions/:id(.:format)                           questions#update
                     PUT    /questions/:id(.:format)                           questions#update
                     DELETE /questions/:id(.:format)                           questions#destroy

参考リンクを見ながらコントローラとそれに関連するviewを編集して、回答できる状態をつくりました。この辺りの動作はUIも含めて検討中のものが多いので、ある程度まとまったら整理したいと思います。

参考: RailsのScaffoldでネストしたResourceを作る

現在の状態

新規回答画面

f:id:tsyknsr:20160629155522p:plain

質問閲覧画面

f:id:tsyknsr:20160629160825p:plain

参考

#3 仕様の作成

第3回に入る前に、改めて仕様を整理しました。実はこの時まで何をつくるか悩んでいたのですが、色々と考えた末にQ&Aサイトをつくることにしました。仕様の整理については「パーフェクト Ruby On Rails」を参考にしました。

パーフェクト Ruby on Rails

パーフェクト Ruby on Rails

主な仕様

  • ユーザはメールアドレス・Facebookアカウントで登録・ログインできる
  • 全ユーザは質問を閲覧できる
    • 質問は作成日時で降順に表示
    • 10件毎にページ送り
    • 質問タイトル・質問本文を対象にキーワード検索できる
  • ログインユーザは質問を作成できる
    • 質問タイトル(任意)
    • 質問本文(必須)
  • ユーザは自分が作成した質問を削除できる
  • ログインユーザは質問に回答できる
    • 回答本文(必須)
  • ログインユーザは退会できる
  • 退会したユーザの情報は削除される
  • 退会したユーザの質問はそのまま残る
  • 質問を作成したユーザが退会している場合、作成したユーザの情報として「退会したユーザです」と表示する
  • 質問に回答したユーザが退会している場合、回答したユーザの情報として「退会したユーザです」と表示する

仕様はつくりながら調整していく予定です。

質問を投稿する

第3回では質問を投稿する機能をつくります。モデルの定義や全体の構成については、Q&Aサイトのオープンソースプロジェクトを参考にしました。

今回はscaffoldを使ってテンプレートを作成します。

$ rails g scaffold question user:references title:string content:text

生成されたマイグレーションファイルのcontentの項目にnull: falseを追加して実行します。

$ rake db:migrate

モデルとコントローラをそれぞれ修正します。

  • Userモデルに追加
has_many :questions
  • questions_controller.rbを修正
  def new
    @question = current_user.questions.build
  end

  def create
    @question = current_user.questions.build(question_params)
    (省略)
  end

今後バリデーションなどの処理は必要ですが、ログインユーザが質問を投稿できるようにりました。

f:id:tsyknsr:20160629095624p:plain

参考

#2 deviseでログイン機能の作成

第2回では、メールアドレスを利用したユーザー登録・ログイン機能をつくります。

deviseの導入

参考サイトを見ながらdeviseを導入します。

deviseとは

ユーザー登録して、送られてきたメールのリンクをクリックして本登録して、ログインして、パスワード忘れたら再設定して、何回もログインミスったらアカウントロックして…などといった認証系アプリに必要な機能を簡単に追加できる便利なgemです。

Gemfileにdeviseを追加します。

gem 'devise'
gem 'slim-rails' # slimを利用する場合
$ bundle install

deviseの設定

$ rails generate devise:install
Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:

       config.assets.initialize_on_precompile = false

     On config/application.rb forcing your application to not access the DB
     or load models when precompiling your assets.

  5. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

上から順に設定していきます。

  • デフォルトURLの設定。指定通りに追加しました。
  • root_url。コントローラを作成後、設定しました。
$ rails g controller welcome index
root 'welcome#index'
  • フラッシュの表示。指定通りに追加しました。
  • Rails4.2.6を使用しているので不要です。
  • Viewファイルの作成。指定通りに実行しました。

slimを利用する場合

gemにhtml2slimを追加して、下記のコマンドで変換を行いました。

for file in app/views/devise/**/*.erb; do erb2slim $file ${file%erb}slim && rm $file; done

参考:How To: Create Haml and Slim Views

Userモデルの作成

$ rails g devise User

今回は、マイグレーションファイルに変更を加えずに実行します。

$ rake db:migrate

Viewの編集

参考サイトから拝借したソースコードを編集してapplication.html.erbに貼付け、無事に動く状態になりました。

<% if user_signed_in? %>
    <strong><%= link_to current_user.email, root_path %></strong>
    <%= link_to 'Settings', edit_user_registration_path %>
    <%= link_to 'Log out', destroy_user_session_path, method: :delete %>
<% else %>
    <%= link_to 'Sign up', new_user_registration_path %>
    <%= link_to 'Log in', new_user_session_path %>
<% end %>

f:id:tsyknsr:20160628191453p:plain

f:id:tsyknsr:20160628191502p:plain

参考サイト

#1 Railsの環境構築

ここ数ヶ月仕事の負荷が高かったため、仕事以外の開発から意識的に離れて過ごしていたのですが、落ち着く目処がついて、徐々に何かやりたい欲が湧いてきたので久しぶりに個人サービスを開発しようと思います。1日1~2時間程度の作業量を目安に、2~3ヶ月後のリリースが目標です。作業の経過はせっかくなのでブログに残して、あとから振り返りができるようにします。モチベーションが途切れて途中で終わってしまうかもしれませんが、ゆるく続けていければと思います。

第1回はローカル環境の構築を行います。

ローカル環境の構築

Railsをバージョン指定してインストール

$ gem install rails -v 4.2.6
$ rails -v
Rails 4.2.6

RSpecの使用を想定して-TオプションをつけてTest::Unitを組み込まずに作成

$ rails new my_app -T

起動

$ rails s

http://localhost:3000/にアクセスしてデフォルトのトップページを確認しました。

f:id:tsyknsr:20160628031702p:plain

関連記事

tsyknsr.hatenablog.com

TensorFlowでHello world

Googleが提供する機械学習ライブラリTensorFlowでHello worldを出力するまでのメモ

環境構築

  • pipをインストール
$ sudo easy_install pip
  • TensorFlowをインストール
$ sudo easy_install --upgrade six
$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.8.0-py2-none-any.whl

動作確認

$ python
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42
>>>

作業中のエラー

RuntimeError: module compiled against API version 0xa but this version of numpy is 0x6
  • 原因:numpyのバージョンが古い
  • 対応:numpyのバージョンを上げる。(ついでにPythonのバージョンもあげる)

Pythonのバージョンをあげる

$ brew install pyenv
$ pyenv install 2.7.11
$ pyenv global 2.7.11
$ pyenv rehash
$ pyenv versions

現在のnumpyの場所を確認

$ python
>>> import numpy
>>> print numpy.__path__

古いバージョンのnumpyをリネーム

$ mv /path/numpy /path/numpy_old

numpyのバージョンを確認

$ python
>>> import numpy
>>> numpy.version.full_version

参考

Railsでいいねボタンを表示

Turbokinksでajaxな画面遷移をした際にいいねボタンが表示されない時の対応メモ

turbolinks対応でボタンのjsを読み込む

<body>
  <div id="fb-root"></div>

  <!-- Like button -->
  <div class="fb-like" data-send="true" data-layout="button_count" data-width="450" data-show-faces="true"></div>
$ ->
  loadFacebookSDK()
  bindFacebookEvents() unless window.fbEventsBound

bindFacebookEvents = ->
  $(document)
    .on('page:fetch', saveFacebookRoot)
    .on('page:change', restoreFacebookRoot)
    .on('page:load', ->
      FB.XFBML.parse()
    )
  @fbEventsBound = true

saveFacebookRoot = ->
  if $('#fb-root').length
    @fbRoot = $('#fb-root').detach()

restoreFacebookRoot = ->
  if @fbRoot?
    if $('#fb-root').length
      $('#fb-root').replaceWith @fbRoot
  else
    $('body').append @fbRoot

loadFacebookSDK = ->
  window.fbAsyncInit = initializeFacebookSDK
  $.getScript("//connect.facebook.net/en_US/sdk.js")

initializeFacebookSDK = ->
  FB.init
    appId     : 'YOUR_APP_ID'
    xfbml     : true
    version   : 'v2.6'

参考