Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Monday, 17 December 2012

Ruby CI tools

最近一度プルリクエストをしたGitHubのコードに問題がある事が分かりました。多分自分が書いたコードではなくて依存しているgemが使っているAPIの仕様が変わったのではないかと思います。テストを書く事を提案してみようかどうか、どこまでプロジェクトにコミットするのかなど判断にまだ迷っています。

そんな視点を持ちつつなんとはなしにSlimのGithubレポジトリを眺めていると、Travis CI以外にも二つコードの状態を示していそうなバッジがついていました。少し調べてみると、一つは異存しているgemの状態をチェックするGemnasiumというツールでした。もう一つはCode ClimateというクラスファイルごとにCode Smellなどの観点からコードの健全性を見せてくれるツールでした。

目先、GemnasiumとTravis CIがとても使えそうですが、そもそもどこまでコミットできるかという判断が解決していないですね…。

Friday, 7 December 2012

Ruby Array#each_sliceメソッド

配列を4つごとに区切った後で更にその4つを.eachで繰り返したいということは多くあるのではないでしょうか?

RoRでの実装はeach_sliceを使ってこうしました(slimを使ったviewのテンプレートです)。

- @products.each_slice(4) do |products|
  ul
    - products.each do |product|
      li= product.name

これで

ul
  li
  li
  li
  li

ul
  li
  li
  li
  li

ul
  li
  li

と続くHTMLを作れます。

Wednesday, 5 December 2012

Array#eachでまとめてメソッド定義

例えばユーザ認証で

class User
  ROLES = %w(contributor manager admin)

  attr_accessor :role

  def is_contributor?
    self.role == "contributor"
  end

  def is_manager?
    self.role == "manager"
  end

  def is_admin
    self.role == "admin"
  end
end

user = User.new

user.role = "contributor"

user.is_admin? #--> false

user.is_contributor? #--> true


というコードを簡略にして

class User
  ROLES = %w(contributor manager admin)

  attr_accessor :role

  ROLES.each do |role|
    define_method "is_#{role}?" do
      self.role == role
    end
  end
end

とリファクタリングできます。

Monday, 26 November 2012

Ruby block, Proc, lambdaについてやっと調べてみました。

ずっと分からないと感じていたRubyのclosureについて調べてみました。

まずProcオブジェクトは手続きを記述したコードブロックを保存したオブジェクトです。これだけだとただの無名関数ですが、Procはその中にその時の周りの変数の状態なども保存できる事から、closureになるのでしょう(PHPのある日本語マニュアルページでは”無名関数はクロージャとも呼ばれ”と書いてあるけど…)。

例えば

x = 0

foo = Proc.new {return x}
foo.call

とすると

=>0

が返ってきます。しかし、


foo = Proc.new {return x}
x = 0
foo.call

とすると

NameError: undefined local variable or method `x' for main:Object

とエラーが出ます。Proc.newした時にあったKernelにくっついたxメソッドの返り値を参照しているのでしょう。ここで => 0が返って来ないのがclosureと無名関数の違いなのではないでしょうか?

Rubyでは変数の明示的削除はできないらしいですが、例えば


x = 0

foo = Proc.new {return x}
x.delete
x = 0
foo.call


などとできると

NameError: undefined local variable or method `x' for main:Object

のエラーが返ってくると思います。


closureの使い途として考えられるのは例えばDBにクエリを送る際にメソッドチェーンにして遅延評価し、DBのIOを少なくする事でしょうか。

例えばPostモデルがあった時に

@post = Post.has_image.sort_by_date.first

そのままコードを読めば、has_imageメソッドでまずPostのオブジェクトの配列を作って取得し、その後でソートして、その一番最初のオブジェクトを取得するとなります。が、本当にこんな事をしていればサービスとして破綻してしまいますね(破綻しなくても無駄が多すぎて許せないという人もいるのでしょうか…)。

ここはActiveRecordやその他のORMではProcを使用してsort_by_dateの部分までクエリを作ってしまってfirstで初めてPostのオブジェクトを返すという事にしているのでは(まだActiveRecordのコードは読んだ事が無いのですが、これは次の課題です)?

誰かこの文を読んでclosure理解の役に立つと良いですね…。それともやっぱり分かりにくい文になったかな…。

Monday, 12 November 2012

Scala/Clojure/Ruby勉強会 報告 (cont.) #ujmben2012

勉強会に参加して、Rubyの遅延処理が2.0からEnumerable#lazyに実装されるということ(Scalaなどと比べるとそんなにlazyではないという議論になりましたが…)。あとScalaとClojure、Rubyの違いなどを聞いてきました。Clojureのアトミックなスレッドオペレーション(言葉が正しいか???)は特にインパクトがありました…。

まだまだ分からない事が多かったので、個人的にはScalaは分散処理をする必要があるときはおもしろい選択肢。Clojureは言語の仕様がかなり数学的に考えられていて面白いです。単体のマシンで走らせるプログラムにはとても面白そうという印象です。RubyはRailsを使っていると開発が速いので放せないですね。memoize処理の書き方もとてもシンプルで個性的。

Saturday, 10 November 2012

Scala/Clojure/Ruby勉強会 #ujmben2012

Scala/Clojure/Ruby勉強会に参加してきました。

http://kokucheese.com/event/index/57145/

言語ではなくハートで話す感じのこんなイベント私はとても好きです。とても刺激になりました。勉強会の後でもいろいろ調べものしないと…ですね。来年もまた参加したいです。

Google Calendarのイベントを拾ってFacebookページに投稿するアプリケーション

Google Calendarで管理しているイベントを前日に拾ってFacebookページに投稿するアプリケーションを作りました。コードはMITライセンスでGitHub上で公開しています。


ちょっとセッティングが面倒ですが使ってみてくださいね。セッティングにはある程度のRubyの開発環境とHerokuが使える事が前提です…。まだまだ開発者が使う事を前提としたアプリケーションですね…。

フィードバックもお待ちしてます。

Thursday, 8 November 2012

RailsとRubyのエラーハンドリングの違い

ウェブアプリケーションを作っていると

if !object.method
  do_this
else
  do_that
end

という方法でユーザを誘導する習慣が付いていますが、Rubyで組み込みやデスクトップアプリケーションなどを開発する際には下のようにする人が多いのではないでしょうか?

begin
  do_this
  do_that
rescue
  error_handling_method($!)
end

こうしておいて

def do_this
  raise 'Specific error message' if !some_method
end

などとそれぞれのメソッドの中でRuntime errorを発生させれば最後のrescueの所でまとめてエラーを処理できるので便利でした。例えばSTDOUTに表示させるとか、ログにまとめるとか、メールでエラーを報告するなどなど。

ちなみにRSpecではこのサイトに書いてある通り

it "should raise" do
 expect{Object.non_existent_message}.to raise_error(NameError) end

とすればテストが書けます。

Railsでも同じようにエラーの処理はできると思いますが、通常begin, rescue, endは使わないですね。ディベロッパー向けのAPI以外では、ウェブアプリケーションはエラーメッセージは極力詳細は出さない事もセキュリティー上大切なのでこのような設計になるのでしょうね。例外が発生したら多くの場合シンプルにbreakして500を返しますもんね…。ウェブサービスでもREST APIを作る人はもっと複雑なエラーハンドリングを開発しているんでしょうね。お疲れさまです。

Tuesday, 6 November 2012

RubyのTimeクラスオブジェクトをRFC3339に変換

Google Calendar API(v2)を使っていて、時間のクエリをRFC3339フォーマットにしてくださいということが書いてありましたが、RubyのTimeクラスにはrfc3339メソッドがありません。

このサイトに書いてあるにはRSSではRFC3339は標準なので、RubyではRFC3339フォーマットに時間を変化するのは#xmlschemaで提供されているそうです。

irb > Time.now.xmlschema

で変換できました。

※後で教えてもらったのですが、DateTimeクラスだとrfc3339メソッドがあるみたいです。ちなみにDateTimeクラスを用いると例えば下のコマンドで次の日の00:00時をRFC3339フォーマットのString形式で返してくれます。

Date.today.next.to_time.to_datetime.to_s

Monday, 22 October 2012

pry gem

pryというgemを今更ですが発見しました。**nixシステムのシェルみたいにrubyプロジェクトのフォルダやファイルを行ったり来たりしてクラスやメソッドを見れる助けをするライブラリのようです。https://vimeo.com/26391171にテンポ良く機能を紹介してくれるスクリーンキャストがあります。

pryでは例えば

pry(main) > require "hello_world"
pry(main) > ls HelloWorld

と打てばHelloWorldクラスのメソッドや変数を見せてくれます。また、

pry(main) > cd HelloWorld

と打てばHelloWorldクラスにcdしてくれるような挙動になり、

pry(HelloWorld) > ls

でHelloWorldクラスのメソッドや変数が見れます。また、

pry(HelloWorld) > show-method say_helloとすればメソッドのコードとファイルの場所が見れます。デバッグの時、テキストエディタの検索機能を駆使しなくても目的のコードに簡単にたどり着けそうです。


Thursday, 18 October 2012

sass 便利です

css extensionのsassをこれまた最近仕事で使う事になったのですが、便利ですし、おもしろいです。

sassでは変数が使えるので、ローカルファイルでいろいろ変数を使い回したり、グローバル変数を設定して@importで設定ファイルを読み込んだりと使い方ができます。ただRubyで使用する場合など、変数の設定はrequireでは読み込めないので、@importする必要があるようです。これはちょっと不便ですが…

OOPのようにcssを使う方法としてsassが使えます。

@extendがどちらかというと継承に使えるツールで、一番下のレイヤーcssを作っていく際など、下の様にまずプロトタイプを作ってクラスにさせて作成するというような事ができます。

%layer
  width: 100%

#header, #contents, #footer
  @extend %layer

機能追加をする Ruby でいうモジュールのような機能はミックスインで利用できます。例えばclearfixやしましまビジュアルをある要素に追加したいという場合はまずミックスインを定義してそれを要素にインクルードします。ミックスインの定義は下の様にします。

=clearfix
  *zoom: 1
  &:after
    content: "."
    display: block
    clear: both
    height: 0
    visibility: hidden

このミックスインをインクルードしたい要素にインクルードします。

#header, #contents, #footer
  +clearfix

以上が私としてはレイアウトの定義に使えるツールだったのですが、色や背景画像などのテーマを作成するにはどうしたら良いかと暫く悩んだのですが、結局関数の定義の機能を使用する事にしました。他に良いアイデアがあれば教えてほしいですね…

関数の定義は@functionを使って'whiteTheme'と'blackTheme'テーマのパーツ毎に引き出してくる形にしました。

@function themeParts( $scope, $theme: blackTheme )
  $base_bg_color = #000
  $base_font_color = #fff
  @if $theme == whiteTheme
    $base_bg_color = #fff
    $base_font_color = #000

  @if scope == base_bg_color
    @return $base_bg_color
  @if scope == base_font_color
    @return $base_font_color

以上がテーマのパーツを選んでくる関数のベースで、これを実際のテーマに入れていきます。ここで@eachを使います。

@each $theme in blackTheme, whiteTheme
  body.#{$theme}
    background: themeParts(base_bg_color, $theme)
    color: themeParts(base_font_color, $theme)

これでsassをコンパイルした時にbody.blackThemeとbody.whiteThemeのそれぞれのcssが作成されて、テーマ分けができます。随時背景画像やネストされたクラスなど同様に登録していきます。

sassは素のcssよりかなり機能が充実しているので、技に溺れて不要なツールを使いすぎてしまう可能性があるのですが、ちゃんと使えばかなりすっきりしたコードにリファクタリングできると思います。

皆さん楽しくsassを使ってみてください。

Tuesday, 16 October 2012

slim コメント方法

最近 Ruby テンプレートエンジンの slim を仕事で使い始めました。便利なのですが、困った事が一つありました。コメントをどうするか?です。

勿論本家マニュアルにはコメントの方法は書いてあるのですが、どうもうまくいきません。困って無量井さんに訊いたところ、コメントの "/" もインデント処理が有効という事でした。ということは

/ Comment
p Lorem ipsum
  p dolor sit amet

とすると / Comment 以下の行が全部コメントになってしまいます。なので、コメント以下の行を有効にしようとすると下のようにしないといけないという事でした。

  / Comment

p Lorem ipsum
  p dolor sit amet

そんな些細な事は本家のマニュアルには書いていないし…。困った方の参考になれば幸いです。

Thursday, 27 September 2012

EC2 バックアップをRuby のAWS SDKとHerokuを用いて構築

EC2が運用ベースに乗ってきたので日ごとのバックアップ環境を構築しました。こんな方法もあるのだという参考にしてください。

バックアップスクリプトはAmazonが提供しているRubyのAWS SDKを用いて作成。これはgem が提供されているので、Gemfileに

gem 'aws-sdk'

の一行を書くだけで利用できます。

毎日一度バックアップスクリプトを動作させて、7日分のバックアップを取っておく内容です。バックアップスクリプトはローカルに置くと恒常的に実行できないのでHerokuを利用させてもらいました(こんな使い方はHerokuもあまりありがたくないでしょうけど、利用するリソールは限りなくゼロに近いので許してください)。Herokuのweb workerを0にして毎日1回実行するSchedulerを登録。Herokuの無料利用枠に収まると思います。

自動バックアップツールはAmazonが提供してくれていると便利なのですが、見つかりませんでした。他にバックアップスクリプトを書いている人はいるのですが、やはり自分の環境にカスタマイズするとなると結局手間なので、使い慣れたRubyとAWS SDKの組み合わせを利用しました。

質問がある方は気軽に連絡してもらえば歓迎です。

Monday, 23 July 2012

Ruby は殆ど知らなくてもRoRは組めるのですが

RoRはRubyで書かれたフレームワークですが、フレームワークのパーツ(scaffoldやgemなど)を集めて組み立てればRuby自体は基本的なことだけ知っていればあり程度動くウェブアプリケーションは作ることができます。セキュリティーの面でも怖ければ、セッション管理などはライブラリに任せて触らないようにすれば難は逃れられるでしょう。 

良いフレームワークは矯正ギブスのようなもので、良い習慣を身につけるのに使えるという話を以前PHPerに聞きました。この意味でRoRはとても良いと思います。最近は、小さなウェブサービスの構築だとRoRを使わずにSinatraで作れるし、実はデータベースが必要なアプリケーションも単純にgemでActiveRecordやMongoIDのようなORマッパーさえ拾ってくればRoRはなくても組めるということにも気がつきます。

 

もっと自由にRubyを使えるようになりたいと思い、以前に買ったYugui著「はじめてのRuby」を引っ張り出してきたのですが、このコンテクストでは使えないようです。この本はRubyを学び始める人に有益なように譲りたいですね…。Rubyとソフトウェアのデザインパターンを一緒に習得できる書籍を見つけます。

 

 

Saturday, 17 March 2012

XCodeコマンドラインツール導入

新しくRVMでRuby 1.9.3を導入しようとしたのですが、以下のメッセージが現れてドキッとしました。

Warning: Xcode appears to be installed but xcodebuild is unusable; some ports will likely fail to build.

調べてみるとなんでもXCode 4.3はデフォルトでコマンドラインツール(例えばgcc)をインストールしてくれないので、XCodeを立ち上げて"Preference"->"Downloads"でコマンドツールを選択してダウンロードした後インストールするという作業が必要でした。この作業をすると難なくrvmでRuby1.9.3導入が完了できました。

Saturday, 4 February 2012

LionでRuby 1.9.2 インストール時にエラー

Ruby 1.9.2をOSX Lionにインストールしようと思い、

$ rvm install 1.9.2

としてエラーが出ました。MacBookProでは問題なかったのに、なぜ?

エラーメッセージは


configure: WARNING: unrecognized options: --with-libyaml
checking build system type... i386-apple-darwin11.2.0
checking host system type... i386-apple-darwin11.2.0
checking target system type... i386-apple-darwin11.2.0
checking for gcc... no
checking for cc... no
checking for cl.exe... no

調べてみるとXCodeが最新ではない様でしたので、App Storeから更新。そういえばMacBook ProはSnow Leopardのままで使い続けてました…。XCodeの最新安定版は2011年11月17日リリースの4.2.1だそうです…。エラーが出てから更新をしていなかった事に気づきました…。しかもついでに調べるとRubyも最新安定板は1.9.3…。

$rvm install 1.9.3

にするとまたエラーが。

またググると1.9.3はまだエラーが多いし、Herokuでも問題があるらしいのでやはり1.9.2をインストール。XCode4.2とgccのインストールをこなしていた事で

$rvm install 1.9.2

でインストールが無事できたようです。ついでにRailsもLionにインストール。

$sudo gem install rails

最新安定板は3.2.1です。

Saturday, 28 January 2012

OSXでRuby1.9.2へのアップグレード


1. RVM (Ruby Version Manager) のインストール

$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )

2. Rubyのインストール

$ rvm install 1.9.2
$ rvm use 1.9.2 --default
$ ruby -v