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

CoffeeScriptオンリーでWebアプリを作ってみた

ruby rails CoffeeScript

この記事は大都会岡山 Advent Calendar 2012向けに書いたものです。

昨日の@ore_publicさんの記事は読みましたか!?さすが僕らのリーダーやで。

さて私、RailsからRubyを始めたワリにはCSSとかJavaScriptとか苦手で、あまり関わらないように生きてきました。しかし、CoffeeScriptの登場で大量のfunctionや"{}"や";"を使わずともJavaScriptを書くことができる時代になりました。ステキ。せっかく時代がこちらへ歩み寄ってきてるのだから、なにか作ってみることにしました。

お題はLuckOfWiseさんが会社の飲み会用に作ってたAndroidアプリを真似てみることに。車輪の再発明はムダじゃない!モチベーションが大切です。

できた。
http://tomikuji.herokuapp.comで使うことができます。ソースはgithubに置いてます。
オータムジャンボ宝くじの番号を入力すると当たりの可能性が表示されます。会社で共同購入したくじをみんなで開封するときに使うと楽しいです。

Rails

普通にRails new tomikujiして空のcontrollerを作っただけです。今回は動作確認やCoffeeScriptコンパイルするのがRailsの役目です。
コントローラとビューはこんな感じ

├── controllers
│   ├── application_controller.rb
│   └── main_controller.rb
└── views
    ├── layouts
    │   └── application.html.erb
    └── main
          └── index.html.erb

CoffeeScript

前方一致で当たりの可能性を表示するロジックはちょっと工夫してみました。

# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

$(document).ready ->
  if Modernizr.touch
    $(".key").bind 'touchend', (event) ->
      btnClick($(@).text())
  else
    $(".key").click ->
      btnClick($(@).text())

  setTimeout("scrollTo(0,1)",100)

# 当たり番号
hits =
  "1等" : "187077"
  "2等" : "179409"
  "3等" : "119658"
  "4等" : "....30"
  "5等" : ".....9"

# 表示処理
btnClick = (number) ->
  if number == "clear"
    $("#number").text("")
    $("#message").text("")
  else
    score = $("#number").text() + number
    if score.length <= 6
      $("#number").text(score)
      showResult(score)

# 結果表示
showResult = (score) ->
  message = ""
  for key, value of hits
    diff = value.slice(0, score.length)
    if score.match(new RegExp("^#{diff}"))
      message = message + key
  if message == ""
    $("#message").text("残念!")
  else
    $("#message").text("#{message}の可能性があります")

初めはスマートフォン用もclickイベントを使ってたんですが、処理速度がメチャクチャ遅かったんですよね。なので、touchイベントに変えました。clickイベントを使うかtouchイベントを使うかの判断はModernizrを使ってみました。

css

普通のブラウザ用とスマホ用の2つを用意して画面の幅によって切り替えてみました。レスポンシブデザインとかやってみたかったの。

<head>
  <title>富くじ</title>
  <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.9.0/build/base/base-min.css">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" />
  <%= stylesheet_link_tag    "application", :media => "screen and (min-width: 641px)" %>
  <%= stylesheet_link_tag    "application_small", :media => "screen and (max-width: 640px)" %>
  <%= javascript_include_tag "application" %>
  <%= javascript_include_tag "http://modernizr.com/downloads/modernizr.js" %>
  <%= csrf_meta_tags %>
</head>

通常は複数のscssファイルが1つに統合されてしまうのですがマニフェストファイルを編集して2つに分けています。

stylesheets/
├── application.css
├── application_small.css
├── main.css.scss
└── small.css.scss

app/assets/stylesheets/application.cssにmain.css.scssを読み込むように設定

/*
 * 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, vendor/assets/stylesheets,
 * or vendor/assets/stylesheets of plugins, if any, 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 top of the
 * compiled file, but it's generally better to create a new file per style scope.
 *
 *= require_self
 *= require main.css.scss
 */

app/assets/stylesheets/application_small.cssにsmall.css.scssを読み込むように設定

/*
 * 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, vendor/assets/stylesheets,
 * or vendor/assets/stylesheets of plugins, if any, 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 top of the
 * compiled file, but it's generally better to create a new file per style scope.
 *
 *= require_self
 *= require small.css.scss
 */

あとはconfig/environments/production.rbに明示的にプリコンパイルするcssファイルを記述します。

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

こんな感じでCoffeeScriptを使ってWebアプリを作ることができました。ちょっとしたアプリならクライアントだけで実現できるのがいいですね。
さて、明日はハカセのアイコンでお馴染みのにゃーさんです。お楽しみに!