Ruby on Rails の 紹 介 2015/10 高 島 亮 祐
自 己 紹 介 高 島 亮 祐 (たかしま りょうすけ) id:rst76 (twitter, hatena, github) 日 本 ユニシス 株 式 会 社 2001 年 度 入 社 2010 年 くらいから Ruby / Rails に 携 わる( 同 僚 のお 手 伝 い) プライベートでは Haskell / Lazy K ゴルファー ( 端 的 に 言 うと 関 数 型 厨 )
コードゴルフって? 仕 様 を 満 たすプログラムを できるだけ 少 ない 打 数 (バイト 数 )で 実 装 する 例 : 自 然 対 数 の 底 eを100 桁 出 力 する 27182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274 main=print$sum$36:scanl div(10^100)[1..99] (42bytes in Haskell) 浮 動 小 数 では 精 度 が 足 りないので 多 倍 長 整 数 を 使 う 指 数 関 数 のテイラー 展 開 を 利 用 する 高 階 関 数 のパターンにはめる(scanl) a 1 2 3 a/1! a/2! a/3! a=10 100 sum
Lazy K って? コンビネータ 論 理 (= 型 なしラムダ 計 算 )を 具 現 化 した 言 語 プリミティブは 以 下 の3つだけ S = λxyz.xz(yz) K = λxy.x I = λx.x たとえば 整 数 は 以 下 のように 定 義 できる 0 = SK 1 = SKK = I (*) = S(KS)K = B 0 * 1 0 に 見 えるが 0 * 1 = S(KS)K(SK)(SKK) = (KS)(SK)(K(SK))(SKK) = S(K(SK))(SKK) 0 * 1 = 0 が 成 り 立 つ! 0 f x = SKfx = Kx(fx) = x (0 * 1) f x = S(K(SK))(SKK)fx = (K(SK)f)(SKKf)x = SKfx=x ちなみに 1 f x = SKKfx = Kf(Kf)x = f x (チャーチ 数 )
Lazy K の Quine (*) `S````SSSS``SS`SK``SS`SK``S`KSK```S``S`KS``S`K`S`KS``S`K`S`KK``S`K`S`KS ``S`K`S``S`KS``S`K`S`KS``S`K`S`K`S`KS``S`K`S``S`KS``S`KK``S`KS``S`KK``S ``S``SSS`SK`KK``S`KK``S``S`KSK`K```S`KSK``S`K`S``S``SKK`K```S``SS``SS`` SS``SS``SSS``SS`SK``S`KSKK``S`K`S`KK``S`K`S``S`KS``S`KK``S`KSK``S`KK``S `K`S``S`KS``S`KK``S`K`S``S`KSK``S`KSKK``S`KK``S`K`S``S`KS``S`KK``S`KSKK ``S``S``S``S``SSS`SK`KK`K``S`K`S``S``SKK`K```SS``SS``SS``S``SSS``S``SS`` SS`SK``SS`SK``S`KSKK`K``S`K`S``S``SKK`K```SS``SS```SS```SSSS``SS`SK``S` KSKK``SKK``SKKSKSKSSKKSKSKSSKKSKSKSSSKKSSKKSKSSKSSSSKKSSSSSSSSKKKSSSSK KKSSSSKKSSSSKKKSKKSKSKSSKKSSKKSSKSKKSSKKSKKSKSKSSSKKSSKKSKSSKSSSSKKSKS SKSSSSKKSSSSKKSSKKSSSSSSKKSSKKSSSSKKSSSSKKSSSSKKKSKKSKSKSSKKSSKKSSKSKK SSKKSKKSKSKKSKSSKSSSSSSKKSSKKSSKKSSKKSSKKSKSKSSSKKSSKKSKSKKSSKKSSSKKSS KKSSKSKKSSKKSKSKKSSKKSKSKSSSKKSSKKSKSSSKKSSKKSSKSKKSSKKSKSKKSSKKSSSKKS SKKSSKSKKSSKKSKSKKSSKKSKSSSKKSSKKSKSKKSSKKSSSKKSSKKSSKSKKSSKKSKSKKSSKS KKSSKKSKSKSSSKKSSKKSKSSKSSSSKKSSSSSSKKSSSSKKSSSSKKSSSSKKSSSSKKSSKKKSKK SKSKSSKKSSKKSSKSKKSSKKSKSSSKKSSKKKSKKSKSSSKKSSKKSSKKSKSKKSSKKSKSKKSKSS KSSSSSSKKSSKKSSKKSKSKKSSKKSSSKKSSKKSKSKKSSKKSSSKKSSKKSSKSKKSSKKSSSKKSS KSKKSSKSKKSSKKSSSKKSSKSKKSSKKSSSKKSSKKSSKSKKSSKKSSSKKSSKSKKSSKKSKSKKSS KSKKSSKKSSSKKSSKSKKSSKKSSSKKSSKKSSKKKSKSSSKKSSKKSKSSKSSSSKKSKSSKSSSSKK SSSSSSSSKKKKSSK (*) 自 分 自 身 を 出 力 するプログラム
じゃあ Ruby でコードゴルフを ごめんなさい 読 めません _="_=%p;$><<_%%_";$><<_%_ (Quine in Ruby) Ruby についてはあまりディープな 使 い 方 をしていないので 今 日 は 主 に Rails の 話 をします
Ruby on Rails って? Ruby による Web アプリケーションフレームワーク 2003 年 David Heinemeier Hansson が 開 発 現 在 のバージョンは4.2(もうすぐ5.0)
Rails のよいところ オブジェクト 指 向 にのっとったキレイな 設 計 RESTful なルーティング 抽 象 度 の 高 い O/R マッパー 低 い 開 発 負 荷 豊 富 なライブラリ 準 備 された 開 発 環 境
Ruby on Rails のアーキテクチャ Webブラウザ HTTPリクエストの 受 け 付 け 適 切 なModelへの 振 り 分 け 結 果 のViewへの 受 け 渡 し HTTPレスポンスの 返 却 Controller Model 業 務 ロジック DBアクセス 1 2 3 8 5 4 データベース 7 6 HTMLやJSONのレンダリング View Rails Railsの 場 合 原 則 として データベースの1テーブルに Modelの1クラス Controllerの1クラスが 対 応 する
RESTful なルーティング HTTPメソッド パス コントローラ#アクション 目 的 POST /books books#create 書 籍 を1つ 作 成 する GET /books books#index すべての 書 籍 の 一 覧 を 表 示 GET /books/:id books#show 特 定 の 書 籍 を 表 示 する PATCH/PUT /books/:id books#update 特 定 の 書 籍 を 更 新 する DELETE /books/:id books#destroy 特 定 の 書 籍 を 削 除 する GET /books/new books#new GET /books/:id/edit books#edit 書 籍 を1つ 作 成 するための HTMLフォームを 返 す 書 籍 を 編 集 するための HTMLフォームを 返 す
抽 象 度 の 高 い O/R マッパー(1) books name: string author_id: integer authors name: stirng class Book belongs_to :author end class Author has_many :books end books = Author.find_by(name: ' 安 部 公 房 ').books SELECT authors.* FROM authors WHERE authors.name = 安 部 公 房 LIMIT 1 SELECT books.* FROM books WHERE books.author_id = 1
抽 象 度 の 高 い O/R マッパー(2) books name: string writings author_id: integer book_id: integer authors name: string class Book has_many :writings has_many :authors, through: writings end class Writing belongs_to :author belongs_to :book end class Author has_many :writings has_many :books, through: writings end books = Author.find_by(name: ' 安 部 公 房 ').books SELECT authors.* FROM authors WHERE authors.name = 安 部 公 房 LIMIT 1 SELECT books.* FROM books INNER JOIN writings ON books.id = writings.book_id WHERE writings.author_id = 1
豊 富 なライブラリ 例 ) 全 文 検 索 エンジンを 利 用 したい ライブラリを 導 入 して 以 下 のように 書 けば インデクシングされる class Dataset searchable do text :name, stored: true text :description, stored: true time :created_at time :updated_at end その 他 にも Key Value Store との 連 携 など 様 々なライブラリ が 存 在
準 備 された 開 発 環 境 本 番 環 境 APサーバ: Apache + Passenger DBサーバ: PosgreSQL / MySQL (/ SQL Server (/ Oracle)) 開 発 環 境 APサーバ: WEBrick DBサーバ: SQLite 環 境 の 差 異 を 意 識 せずに 開 発 できる
Ruby のメタプログラミング(1) ミラノ 万 博 アプリ: 多 言 語 対 応 ( 日 英 伊 の3ヶ 国 語 )が 必 要 name_ja, name_en, name_itの3つの 属 性 からユーザに 応 じ て 適 切 な 属 性 を 選 択 したい つまり のようなことを 各 属 性 についてやりたい def name(user) send name_#{user.language} end これを 各 属 性 について 書 くのは 面 倒 なので
Ruby のメタプログラミング(2) モジュールに 定 義 して 取 り 込 めば 使 えるようにした multilingual_support.rb module MultilingualSupport def self.included(base) base.class_eval do def self.attr_multilingual(*attrs) attrs.each do attr define_method attr do user send("#{attr}_#{user.language}") end : content.rb class Content include MultilingualSupport attr_multilingual :name, :description 呼 出 元 @content.name(@user) @content.description(@user)
Ruby のメタプログラミング(3) 動 的 なメソッド 定 義 といったメタプログラミングが 自 由 自 在 (send, define_method, method_missingなど) 使 いすぎには 注 意 が 必 要 ( 黒 魔 術 ) Rails 等 ライブラリの 内 部 はメタプログラミングの 塊
参 考 書 籍 Railsの 書 籍 は 色 々あります