Quantcast
Channel: Ruby on Railsの記事一覧|TechRacho by BPS株式会社
Viewing all 1384 articles
Browse latest View live

Rails4でサイト構築をする – Scaffold編

$
0
0

[Rails4でサイト構築をする]
Rails環境構築編
Scaffold利用編
– Bootstrap導入編
– WYSIWYG導入編
– CSV出力機能編
– スクレイピング機能編(nokogiri)
– 非同期処理導入編(delayed_job)
– デプロイ環境構築編(capistrano3)
上記を毎週1つずつ出す予定

Ogawaです。前回Rails4でサイト構築をする – Rails環境構築編でRailsサーバが起動するところまで、行いました。今回はRailsのScaffoldを使ってコントローラとかモデルとか作ってみます。
※RailsGuidesにRailsについて詳しく書かれているので、詳しく知りたいかたはそちらを参考にするといいと思います。
ここでは、Scaffoldでできるものを確認してRailsの大枠が何となく把握できればよいかな程度で書きます。

Scaffoldによるコンポーネントの作成

RailsにはScaffoldという便利なものがあります。Scaffoldを使うことで、コントローラやモデル、ビューなどのひな型をコマンド1つで作ることができます。

bundle exec rails g scaffold article title:string content:text

[結果]
tech4
コントローラ、モデル、ビューなどが作成されています。assets以下は作らなくてよい等あればオプションがあるので調べてみてください。

congfig/routes.rbを見てみる

Techracho::Application.routes.draw do
  resources :articles
# 以下コメントいっぱい
end

rake routesを実行してみる

bundle exec rake routes

[結果]
tech5
新しくarticle関連のURLが追加されているのがわかります。
このままURLにアクセスしてもmigration走らせろエラーが出るので、URLをたたく前にmigrationを実行してください。

bundle exec rake db:migrate

/articles
tech6

/articles/new
tech7

デザインがなくてしょぼいですが、形ができました。

日本語化する

app/views/articles/_form.html.erb
内などにある、フォームのラベルが英語で表示されています。
これを日本語にしてみましょう。
config/applicatoin.rbに
以下を追加
config.i18n.default_locale = :ja

config/locales/ja.ymlを作成

ja:
  activerecord:
    attributes:
      article:
        title: 'タイトル'
        content: '内容'

まとめ

Scaffoldを使って、新しくページができるのを確認しました。
Railsに関する詳細なことは冒頭でも書いたように、RailsGuides等を参考にしてください。
次回はBootstrapを導入してデザインを付けてみたいと思います。


Rails4でサイト構築をする – Bootstrap導入編

$
0
0

[Rails4でサイト構築をする]
Rails環境構築編
Scaffold利用編
Bootstrap導入編
– WYSIWYG導入編
– CSV出力機能編
– スクレイピング機能編(nokogiri)
– 非同期処理導入編(delayed_job)
– デプロイ環境構築編(capistrano3)
上記を毎週1つずつ出す予定

Ogawaです。今回はBootstrapを使ってデザインを付けてみたいと思います。
※タイトルにRailsと入っていますが、RailsでしかBootstrapが使えないということは全くありません。
Bootstrapを使う前にまず、対応ブラウザの確認は必ず行ってください

Bootstrapの利点と欠点

Bootstrapを使う前にBootstrapにどのような利点や欠点があるのか考えてみたいと思います。
・そもそもBootstrapはHTMLやCSSなどのテンプレートをまとめたものです。
既にCSSなどはある程度組まれているため、1からHTMLを作るよりも簡単にきれいなサイトができます。
しかし、その反面、CSSがある程度決まっているので、オリジナリティのあるものを作る場合はあまりBootstrapの効果は期待できません。
・BootsrapはCSS3の機能を多く使っています。
そのため、CSS3の対応がイマイチなブラウザに対応しなければならない場合は、
Bootstrapを使う利点が薄れてしまいます。
・Bootstrapの多くは、レスポンシブデザインに対応しています。

まとめると以下のようになります。
Bootstrapの利点
・ Bootstrapのテンプレートに沿う形であれば速くできる
・ レスポンシブデザインが簡単に実現できる

Bootstrapの欠点
・ デザイン重視やUI重視のサイト(特にB to C系のサイトは見た目が重要なのでデザイナーが作ったデザインからHTMLを起こすことが多い)では使えない
・ 古いブラウザの対応が必要の場合は使えなかったりする。IE7とか

Bootstrapをダウンロードする

Railsの場合、Bootstrapをダウンロードするのは簡単です。
Gemfileに以下を追加します。

gem 'twitter-bootstrap-rails'
または
gem 'twitter-bootstrap3-rails'

上は2系で下は3系のBootstrapが入ります。

今回は3系のBootstrapを使います。

Bootstrapファイルの作成

CSSとかJSを作成する

rails generate bootstrap:install static

レイアウトを作成する

rails g bootstrap:layout application fluid #レスポンシブ
または
rails g bootstrap:layout application fixed

[結果]
tech8
デザインがつきました。

Bootstrapで用意されているCSSを使ってサイトのデザインを作る

http://getbootstrap.com/

上のサイトを参考にしてフォームなどのデザインを整えていきます。
tech9

こんな感じにフォームを修正
app/views/artiles/_form.html.erb

<%= form_for(@article, :html => {:class => "form-horizontal", :role=>"form"}) do |f| %>
  <% if @article.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved:</h2>

      <ul>
      <% @article.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="form-group">
    <%= f.label :title, class: 'col-sm-2 control-label' %>
    <div class="col-sm-10">
    <%= f.text_field :title %>
    </div>
  </div>
  <div class="form-group">
    <%= f.label :content, class: 'col-sm-2 control-label' %>
    <div class="col-sm-10">
    <%= f.text_area :content %>
    </div>
  </div>
  <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
    <%= f.submit '登録', class: 'btn btn-default' %>
   </div>
  </div>
<% end %>

その他のBootstrap

WrapBootstrap(有料)

https://wrapbootstrap.com/

Bootswatch(MITライセンス)

http://bootswatch.com/

BootstrapのCSSを上書きする場合の参考


3年間かけて培ったWebシステム開発におけるHTML/CSSコーディングまとめ

以前に書いた記事です。

まとめ

Bootstrapは簡単にそれなりにかっこいいデザインを作ることができます。
1からHTMLを作るよりも遥かにコストが抑えられるので、
管理画面等では、お客さんと相談して積極的に導入するとよいと思います。
また、BootstrapはHTMLやCSSの勉強にも良いです。
各UIパーツの作り方やクラスの付け方、HTMLの構造をどのように作っているかなど、
1度ちゃんと見てみるとかなり勉強になります。

STI(Single Table Inheritance)でハマったところ

$
0
0

最近Rails でSTI を使う機会があったのですが、幾つかハマるポイントがありました。

親クラスを継承したクラスが読み込まれない

継承した子クラスのモデルを親クラスと同じファイルにまとめていると、エラーになる場合があります。

# app/models/user.rb
class User < ActiveRecord::Base
end

class Admin < User
end

class Guest < User
end

# rails console で実行
irb(main):001:0> Admin.all
NameError: uninitialized constant Admin

この問題はRails の自動読み込みの仕組みに関連して起こるようです。
Rails の自動読み込みの話

読み込みされていないクラス/モジュールがあった場合、名前から読み込みするファイルを判断できる

上記の例の場合は、admin.rb を読み込もうとしてエラーになります。
つまり、Adminクラスにアクセスする前にUserクラスが読み込まれていれば、NameError: uninitialized constant エラーは発生しません。
Devise等を利用していて、ログイン処理をUserクラスでまとめていたりすると before_action で毎回User にアクセスしているため
エラーが起こらないということもあると思います。
また、production モードでも起動時にmodel が読み込まれるため発生しません。
以上のような理由で場合によっては1つのファイルにまとめて記述しても問題ないかもしれませんが、大抵の場合は子クラスは別ファイルに分けたほうがいいと思います。

# app/models/user.rb
class User < ActiveRecord::Base
end
# app/models/admin.rb
class Admin < User
end
# app/models/guest.rb
class Guest < User
end

Routing がおかしくなる

子クラスのcontroller を作成せず親クラスのcontroller で処理をまとめていると
create update などのaction からのリダイレクト先が 子クラスのURLになってしまってエラーになる場合があります。

# config/routes.rb
Sample::Application.routes.draw do
  root 'users#index'
  resources :users
end

# app/controllers/users_controller.rb
def create
  @user = if admin?
    Admin.new(user_params)
  elsif guest?
    Guest.new(user_params)
  else
    raise
  end

  if @user.save
    redirect_to @user
  else
    render action: :new
  end
end
# undefined method `admin_url' for #<UsersController:0x007af349879fa8>

controller を一つにまとめたい場合は becomes を使うと上手く行くと思います。

This is mostly useful in relation to single-table inheritance structures where you want a subclass to appear as the superclass.

目的にピッタリ合いそうです。

# app/controllers/users_controller.rb
def create
  # 省略
  if @user.save
    @user = @user.becomes(User) #この行を追加
    redirect_to @user
  else
    render action: :new
  end
end

これで無事 UsersController#show が表示されました。

まとめ

2つ目のRouting に関する問題は、後からSTI に変更した場合にやりがちだと思うので気をつけたいですね。

売上1億の開発会社が20人採用したあと黒字をキープするためにやったこと

$
0
0

2年前、役員と社員あわせてエンジニア5人だった弊社は1年間で20人のエンジニアを採用しました。採用前の当時の売上は約1億。採用のために使ったキャッシュは売上の10%程度の1000万円前後。社内の実働も含めると実質売上の15%以上です。それについては以前記事にしましたので興味があるかたはこちらをどうぞ。今回のその後についでです。そもそも何やってる会社だ?と興味もってくださった方はこの記事でも軽く紹介しますがもしよければ弊社HPをご覧ください

採用の目的は事業拡大でした。時間の切り売りから商品の提供まで売り方は様々でしたが弊社売り物は技術です。だからエンジニア募集しました。そして自分たちの夢を一緒に追いかけてくれる人が20人も集まってくれました。数年間3~7人でやってきたのでまるで夢のような感覚でした。でも悪夢のような速度でお金が飛んでいきます。倒産しかけるって表現は人それぞれだと思いますが「月々収益が増えないと3ヶ月後に倒産する」的な状況には何度かありました。思いつく限りの施策をうち、終わってみれば増員1年目からぎりぎり黒字を維持し、一人あたりの集金額は減ったものの今後の商材になりうる様々な資産ができました。

やってきたこと+感想

※実施内容に因果関係がある気もするので時系列で並んでます。

1. プッシュ型の営業は捨ててみた

ピザ会スーツも捨てました。ニンニクたっぷりのピザも皆で食べちゃいます。営業できるやつがいなかったので人が増えても教えられないので拡大もできない。だからプッシュ型の営業は捨てました。ネットで情報を公開し続ければ大繁盛しないまでも声くらいはかかるでしょ。僕らの武器は開発なので開発記事をフックに人に開発力を知ってもらうことが自然に思えました。それがTechRachoです。

徐々に自然検索も増えたけどそれ以上にURL直うちで訪れる人も増えました。弊社のことを何かしら知ったうえでアクセスしてくれているということですね。これはエンジニア5人が下手なテレアポして営業に走り回ってても実現しなかったはずです。皆様の支援あってアクセスは増え定期的にお仕事の依頼を頂戴しています。ここまでのメディアになるまで15000記事を皆で書きました。増員直後は皆が暇でよかった。この時期不安が多くて本気でハゲるかと思った。

2. 技術的な制約を設けてみた

WEB開発はRuby on Railsで弊社の場合は、Ruby on Rails、を主戦場として選択しました。Ruby on Railsといえば、Rubyをベースに作られたMVCフレームワークです。最近は少数精鋭のスタートアップでよく利用されるようになってきましたね。僕らもそうですが、Ruby on Railsじゃなくても高速に開発できます。Rubyを使い始めたのもその時最も開発効率が良さそうで楽しそうだったからで、より良いものがでたら会社がこけない限りまた一気に変えるかもしれない。でもそれまでは、特に理由がない限りサーバーサイドプログラムはRubyで書いています。25人程度の会社ですからね。効率よく資産をためて共有するためには、違う仕事をしていてもある程度共通する部分を作っておくのは便利です。知識を得るのも実績を積み上げるのも仲間を募るのも。

はてブランキングrails世界は広くってありがたいことにRailsという技術的制約をもうけてもお声がけいただけます。Rubyで検索したらよくでてくるからでしょうね。はてブもソコソコ多いみたいです。おかげさまで生きていけてます。

3. 趣味を事業化してみた

expo超縦書
安定した事業(例:Ruby on RailsによるWEBシステム開発)を構築できたら余裕ができてくるわけで、新規事業を立ち上げたくなります。新規事業を立ち上げるときは資産を活用しろ、とよくアドバイス頂いたものです。その方針で新規事業を考えたこともあるのですが、リスクヘッジやお金を考えすぎると気持ちがついてこないんですよね。最初に事業に依存しちゃうかもしれないとか当時は言い訳してましたが、ぶっちゃけ制約が面倒臭かっただけだと思う。自分が燃えないような目標掲げても周りがついてきてくれないので自分のわがままを信じて興味というか憧れがあったコンテンツに近いビジネス領域を選択してみました。電子書籍です。電子書籍で漫画読みますか?電子書籍で縦書き表示された小説を読みますか?それなら弊社のソフトを利用いただいたことがあるかもしれません。

超縦書サンプル
本が好きなんですよ。出版業界と関わりたかった。ただそれだけ。出版社や大手印刷会社もいるなかで、ぼくらが貢献できるのは技術です。だから電子書籍を配信するインフラ(ビューアやDRMやCMS)を開発して販売する業務を始めました。初めての自社商材開発で、初めての大きな先行投資。1年で先行投資して回収できると思ったけど甘かった。ギリギリ黒字をキープしたがRuby on Rails側の預金を食いつぶしてしまった。

ちなみにぼくらが狙った電子書籍市場は丁度業界全般的に皆が期待していたほど市場が成長しないことを実感し始めた頃で、中小の競合も減り、大手がIRのために仕方なく継続するビジネスになってました。弊社の売上も伸びず、その時期に大事なメンバが何人か離脱し25人くらいだったのが20人弱に減り、とても苦しい時期でした。冒頭で「倒産しかけた」と表現した状況に陥ったのはここらへんです。ウオーターサーバを撤去するだけでスタッフにバレるんですよね。あれは困った。でも商材は完成し、競合と同等以上の品質を社員の数の違いもあり他社の何分の一の費用で提供できるようになり、このタイミングでようやく安定し始めたといえます。

4. 自由と責任ある仕事を任せてみた

junta and mangareborn創業メンバはわがまま言いやすいかわりに責任ある仕事をします。どんな仕事もします。僕もその一人です。とりあえず何でもやってみる創業メンバに対して、後から加わってくれたメンバは専門能力が高いですよね。役目があってそのために採用するわけですからね。だから人が増えて責任範囲が明確になるにつれて創業メンバより後から入ったメンバのほうが実力を発揮しやすくなります。僕の場合は特に専門分野がないからかもしれませんが、まだ20人なのになんでも創業メンバが決めて旗振りする時期は終わったんだなと感じます。

organization収益も改善するけどそれ以上に後輩の成長曲線が改善します。何でも挑戦して失敗して成長に繋げられる環境を作るのは難しいけど、一番むずかしいのはそうする決断をすることと、権限と責任をセットで渡すことと、徐々に徐々に渡すことです。権限がないとやっれられないし、一気に渡すと精神的に潰れます。潰してしまった方々、本当にごめんなさい。僕の実力不足です。

5. 採用にさらに力をいれてみた

採用採用は大事なパートナー探しですし、採用はしっかりやろうと思えばしっかりと時間がとられます。経験が増えた分は楽できると期待していましたが、20人じゃなくても採用すると組織が変化するので必要な人財も変わります。今、弊社はここです。結果については、半年後くらいにまとめてみようかなと思っています。採用担当の方々、ぜひいろいろアドバイスください。

よかったらこの1個まえの記事もどうぞ。
売上1億程度の開発会社がエンジニア20人採用してみた

採用バナー
Ruby on Rails開発をしてみたい方や電子書籍関係の開発をしてみたい方はぜひ弊社もご検討ください
今年はご覧いただいているTECHRACHOを磨き上げてさらに発展させていきます。ぜひご応募ください。お待ちしています!

comic1
comic2
comic3
comic4

Rails4でサイト構築をする – WYSIWYGエディタ導入編

$
0
0

[Rails4でサイト構築をする]
Rails環境構築編
Scaffold利用編
Bootstrap導入編
WYSIWYG導入編
– CSV出力機能編
– スクレイピング機能編(nokogiri)
– 非同期処理導入編(delayed_job)
– デプロイ環境構築編(capistrano3)
上記を毎週1つずつ出す予定

Ogawaです。今回はWYSIWYGエディタをRailsで作ったサイトに導入してみたいと思います。
※WYSIWYGはRailsではないと組み込めないということは全くありません。
※社内からWYSIWYGの記事の希望があったので、先に書くことにしました。

そもそもWYSIWYGエディタって何?

WordPressとかによくあるあれです。
WYSIWYG画面

WYSIWYGエディタってどういうときに使うの?

レイアウトやカラーを直感的に操作し、その結果を得たい場合。
わかりやすく言うと、文字やリンクなどの要素に対して色を変えたり、太くしたりを直感的に行いたいときなど。
記事を書くときとかによく利用される。

WYSIWYGエディタを導入する際に気をつけるべきことは?

●機能過多で使いづらくないよう、適切な機能を持ったWYSIWYGエディタを選ぶ。
公開されているWYSIWYGエディタプラグインはそれぞれ提供している機能が異なったり、見た目が異なったりします。
そのため、使用するユーザにあったWYSIWYGエディタの選択が重要になります。
機能過多のWYSIWYGエディタはユーザビリティの減少につながります。

●意図しないCSSの適用に気を付ける。
管理画面のWYSIWYGエディタで表示されている内容とフロントで表示した内容で表示が異なるなんてことがあり、だいたいの原因はCSSです。
WYSIWYGエディタで編集した部分に意図しないスタイルが適用されているなんてことがあります。
特にreset.cssを利用しているときは注意です。

●ライセンスに気を付ける
プラグイン全般に言えることですが、ライセンスについてはちゃんと確認しましょう。

WYSIWYGエディタを導入してみる

今回はなるべくシンプルで使いやすいものをと思い、NicEditを選択しました。
NicEditはMITライセンスです。

ダウンロード

http://nicedit.comのサイトから作成者に感謝をしつつダウンロードします。

tech11
ダウンロードして
– nicEdit.js
– nicEditorIcons.gif
があるか確認してください。

Railsプロジェクトに組み込んで動かす

・nicEdit.jsをapp/javascripts直下に置く
・nicEditorIcons.gifをapp/images/直下に置く

nicEdit.jsの読み込み。レイアウトなどのHTMLファイル内に追加

<%= javascript_include_tag 'nicEdit' %>

IDがarticle-abstractのtextarea要素をWYSIWYGエディタにする。
HTMLサンプル

<div class=”controls”>
<%= f.text_area :abstract, rows: 10, cols: 40, :style => ‘width: auto’, :id => ‘article-abstract’ %>
</div>

JavaScript

<script type=”text/javascript”>
bkLib.onDomLoaded(function() {
new nicEditor({iconsPath : ‘<%= asset_path ‘nicEditorIcons.gif’ %>’}).panelInstance(‘article-abstract’);
});
</script>

結果
WYSIWYG画面

まとめ

WYSIWYGエディタはプラグインのおかげで比較的簡単に導入することができますが、メリットばかりではないので、WYSIWYGエディタを導入すべきかどうか、また、どのようなWYSIWYGエディタがよいかを検討してから導入しましょう。

【勉強会報告】Crafting Rails 4 Applications読み会:第2回資料

$
0
0

こんにちは、hachi8833です。

今回、「Crafting Rails 4 Applications」という一人で読むとくじけそうなRuby on Rails上級者向け技術本を読み通してみようじゃないのという社内企画に参加いたしました。噂に違わず、初心者などまるで相手にしていない濃厚な内容で、一つの章に大小様々な秘法がめいいっぱい詰め込まれています。正直自分のレベルではちょっと無謀でしたが、上級者の世界をいろいろ垣間見ることができました。あれはもしかすると走馬灯だっのかもしれません。

自分が担当した第2章「Building Models with Active Model」のスライドを掲載します。

第2章のメモ

RailsのActive Recordといえば、属性(=データベースのテーブル)を定義すると自動的にその属性を名前に取り込んだメソッドが使えるようになる機能で有名です。2章ではActiveModel::AttributeMethodsを使用して同じことをやってみています。具体的にはattribute_method_prefix()やattribute_method_suffix()などを使用します。

この機能の背後で活躍しているのが、黒魔法とすら呼ばれるmethod_missing()メソッドです。このメソッドを知ったのは『メタプログラミングRuby』という本ですが、どうもこのメソッドについて「家庭から出る排水口にかぶせて大事なものを寸前でキャッチするためのストッキング」みたいなものをついつい連想してしまいました。

自作のモデルをActive Record APIに準拠させるにはinclude ActiveModel::Modelするだけでできてしまうのですが、それをあえて複数のステップに分解し、ActiveModel::Lint::Testsで確認しながら、そこで行われている動作をみっちり解説してくれています。

何かの参考になれば幸いです。

【勉強会報告】Crafting Rails 4 Applications読み会:第8回資料

$
0
0

こんにちは、hachi8833です。turnipまじでいいかもと思いつつある今日このごろです。

引き続き、「Crafting Rails 4 Applications」の読み会で使用した、第8章「Building Models with Active Model」のスライドを掲載いたします。

第8回のメモ

第8回は総集編らしく、第7回までのようなプラグインではなくRailsアプリケーションを作って見せています。素材としてi18n機能で通常のYAMLではなくKey-Valueデータベースを使用するという企画ですが、多くの要素をこれでもかと盛り込んでくれているので、i18nの話題は途中から何だかそっちのけになっていて、第7章でも詳しく解説されているRackミドルウェアの話題が一番目に付きます。

Railsアプリのルートディレクトリにあるconfig.ruって何だろうとは思っていたのですが、本章で詳しく解説されています。あまつさえ、config.ruだけでRailsアプリケーションを作るという飛び道具を繰り出したかと思うと、Railsの中でSinatraを実行するという奇想天外な技も披露されています。

面白かったのが、Capybaraを使用して認証を行なう場合にセッションやcookiesを書き換えるという技が使えない理由でした。詳しくはスライドをご覧いただきたいのですが、ただでさえテスティングでの認証周りはいろいろと面倒なことになりがちなのに困ったことです。実は、今回の読み会に参加いただいたベテランのiさんが、Wardenミドルウェアにモンキーパッチを当ててCapybaraでの認証をバイパスするという技をこっそり教えてくれました。まだまだ自分の中で消化不良ですが、そのうち記事にできればと思います。

何かの参考になれば幸いです。

Rails4でサイト構築をする-スクレイピング機能編(Nokogiri)

$
0
0

[Rails4でサイト構築をする]
Rails環境構築編
Scaffold利用編
Bootstrap導入編
WYSIWYG導入編
– CSV出力機能編
スクレイピング機能編(nokogiri)
– 非同期処理導入編(delayed_job)
– デプロイ環境構築編(capistrano3)
上記を毎週1つずつ出す予定

今回は別のサイトのHTMLをパースして情報を取得する機能を作ってみたいと思います。

HTMLのパースにはNokogiriというプラグインを使います。

Nokogiriのインストール

Gemfileに以下を追加する

gem 'nokogiri'

そして、bundle install

Nokogiriを使って別サイトのHTMLから情報を取得する

対象サイトのHTMLを把握する

試しに、弊社のサイト(http://www.bpsinc.jp)のグローバルナビの情報を取得してみたいと思います。
画像の赤枠部分。
tech12

画像の赤枠部分のHTML

<div id=”menu” style=”padding-bottom: 0px;”>
<div class=”container clearfix”>
<ul id=”primary” class=”nav”>
<li id=”menu-item-7768″ class=”menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-7768″><a href=”http://www.bpsinc.jp/”>Home</a></li>
<li id=”menu-item-7532″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-7532″><a href=”http://www.bpsinc.jp/company”>会社概要</a></li>
<li id=”menu-item-7733″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-7733″><a href=”http://www.bpsinc.jp/rails”>Ruby on Rails</a></li>
<li id=”menu-item-7736″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-7736″><a href=”http://www.bpsinc.jp/epub”>EPUB電子書籍</a></li>
<li id=”menu-item-11426″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-11426″><a href=”http://www.bpsinc.jp/manga_translation”>漫画翻訳</a></li>
<li id=”menu-item-7730″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-7730″><a href=”http://www.bpsinc.jp/manga-reborn”>MANGAREBORN</a></li>
<li id=”menu-item-10493″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-10493″><a href=”http://www.bpsinc.jp/seo-lpo-efo-listing-analytics”>SEO対策</a></li>
<li id=”menu-item-9336″ class=”menu-item menu-item-type-custom menu-item-object-custom menu-item-9336″><a target=”_blank” href=”http://techracho.bpsinc.jp/”>開発ブログ</a></li>
<li id=”menu-item-7735″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-7735″><a href=”http://www.bpsinc.jp/recruit”>採用</a></li>
<li id=”menu-item-7734″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-7734″><a href=”http://www.bpsinc.jp/contact”>お問い合わせ</a></li>
</ul>
</div> <!– end .container –>
</div> <!– end #menu –>

目的とするグローバルナビの要素(会社概要とか、漫画翻訳など)のCSSを特定するにはどうすればよいかを考えてみます。
liタグにidがついており、idはすべて”menu-item-任意の数字”となっています。そしてそのあとにaタグといった構造になっています。
なので、’li[id*="menu-item-"] a’としてあげればよさそうです。

HTMLをパースする機能を持つモジュールの作成

モジュールを作らなければできないなんてことはないですが、モジュールとしてまとめて使いまわせるようにしておくと何かと便利です。

モジュールの作成

lib/scrape.rb

require ‘nokogiri’
require ‘open-uri’
module Scrape
BPS_SITE_URL = ‘http://www.bpsinc.jp’
BPS_TARGET_CSS = ‘li[id*="menu-item-"] a’

def self.bps_global_navi
doc = Nokogiri::HTML(open(BPS_SITE_URL)) # スクレイピング先のURLを指定
navi_list = Array.new
doc.css(BPS_TARGET_CSS).each do |link| #
navi_list << link.content
end
return navi_list
end
end

Railsコンソールで実行した結果

rails console
> Scrape.bps_global_navi
=> ["Home", "会社概要", "Ruby on Rails", "EPUB電子書籍", "漫画翻訳", "MANGAREBORN", "SEO対策", "開発ブログ", "採用", "お問い合わせ"]

自動読み込みの設定

lib/以下のファイルは自動で読み込まれません。Controller等で使う場合は自動で読み込むようにしておくと楽です。

config/application.rbに以下を追加

config.autoload_paths += %W(#{config.root}/lib)

コラム

社内で簡単にCSSパスをコピーする方法が挙がったので記載しておきます。

CSSパスをコピーする

CSSパスを自分で読み取って書くのが面倒な人はブラウザの機能を使って目的の要素のCSSパスを簡単にコピーすることができます。
■ Firefox(28.0)
右クリック=>要素を調査=>目的とする要素で右クリック=>一意なセレクタをコピー
tech13
・画像のところでコピーした結果
#menu-item-7532 > a:nth-child(1)

■ Chrome(34.0.1847.116 m)
右クリック=>要素を検証=>目的とする要素で右クリック=> Copy CSS path
tech14
・画像のところでコピーした結果
#menu-item-7532 > a

■ IE11
F12で開発者ツールが出るのですが、CSSパスをコピーするようなのは見つからなかったです。

まとめ

Nokogiriを使うことでかなり簡単にサイトの情報を取得することができるので、
サイトから情報を取得するような機能を作成する場合はNokogiriがおすすめです。


[翻訳]Ruby on Railsアップグレードガイド (4.1対応版)

$
0
0

こんにちは、hachi8833です。やっとRails 4.1が出ましたので、この間翻訳したアップグレードガイドを更新しました。前回からの更新は10行程度で、Google Translator Toolkitのおかげでいつものようにあっさりと翻訳を更新できました。

Ruby on Railsアップグレードガイド(4.1対応版)

今回の原文はedgeguidesをベースにしました。

前回の記事は更新前のアップグレードガイドを参照ください。

[翻訳]Ruby on Rails 4.1リリースノート & Active Recordコールバック

$
0
0

こんにちは、hachi8833です。この間リリースされたRuby on Railsのリリースノートを翻訳しました。訳したのは少し前だったのですが、移動時にちまちま作業中Google Translator Toolkitでの保存に失敗して復元した分遅れました。ついでに、Rails Guideの「Active Recordコールバック」の訳も公開します。

関連: [翻訳]Ruby on Railsアップグレードガイド (4.1対応版)とAssociation Basics

Ruby on Rails 4.1 リリースノート

今回は急いで訳したのでちょっと荒っぽいかもしれません。

Active Recordコールバック

こちらはDocrailsの原文を使用しています。

Ruby 1.9.2 でdelayed_job を使ったらNoMethodError にぶつかった

$
0
0

どうも、shibuso です。春イベントですね。私の資源力は53 万です。(実際には80 万ぐらいあります:P)

既に動いているシステムのバージョンってなかなか上げられないのが困りモノです。今回も古いRuby を使っていたがために問題にぶつかったので、今となってはあまり需要は無さそうですがまとめてみました。

まず問題が起こった環境はRuby 1.9.2p320 とRails 3.1.3 で動いていたところにdelayed_job_active_record 4.0.1 (現時点で最新)を入れた状態でした。最初Ruby 1.9.3p448 を使用していたところ問題なく動いていたので、恐らくRuby 1.9.3 以降では起こらないのではないかと思います。

問題はdelayed_job を呼び出すためにdelay メソッドを呼び出して実行した時に、DB のdelayed_jobs テーブルにあるhandler カラムに入るパラメータの一部に間違いがあるために正しく実行されないというものです。以下、適当なModule を非同期で呼びだそうとした時の正しい例と間違った例を記載します。

呼び出す箇所

HogeHoge.delay.hoge

正しい値の例 (Ruby 1.9.3p448 + delayed_job_active_record 4.0.1)

object: !ruby/module HogeHoge

間違っている値の例 (Ruby 1.9.2p320 + delayed_job_active_record 4.0.1)

object: !ruby/object:Module {}

ここの情報が間違っているためにModule を上手く呼び出せず、結果としてNoMethodError が発生していました。

どうもこの現象は当時それなりに問題になっていた模様で、検索するとGitHub のIssue でやり取りが見れました。2 年前ですが(苦笑)
NoMethodError with delayed_job · Issue #323 · collectiveidea/delayed_job · GitHub

このIssue の中にある投稿で解決できた報告があり、且つ環境が似ていたので同じくdelayed_job 2.1.4 を入れてみたところ動くようになりました!

Gemfile

gem delayed_job, '2.1.4'

原因は何か複数あるような感じで、このIssue を見ているとHeroku 関連の問題もあるみたいでした。ちなみに今回私が経験したのはHeroku ではなく普通のサーバーと手元のVM 環境で、nginx + unicorn です。

Rails4でサイト構築をする – CSV出力機能編

$
0
0

[Rails4でサイト構築をする]
Rails環境構築編
Scaffold利用編
Bootstrap導入編
WYSIWYG導入編
CSV出力機能編
スクレイピング機能編(nokogiri)
– 非同期処理導入編(delayed_job)
– デプロイ環境構築編(capistrano3)
上記を毎週1つずつ出す予定

今回はDBに保存されているデータをCSV形式で出力する機能を作ってみたいと思います。

対象モデルのデータを全て出力する

今回は、Scaffold利用編で作ったArticleモデルのレコード全てをCSVで出力するプログラムを書いてみます。
想定要件
・記事のデータ全てを一覧出力する
・articlesテーブルのカラムすべてを出力する

app/models/article.rb

#-*- coding: utf-8 -*-
require 'csv'
class Article < ActiveRecord::Base
  # to_csvメソッドを追加する
  def self.to_csv
    CSV.generate do |csv|
      csv << column_names
      all.each do |book|
        # SJISで出す必要がなければmapはいらない
        csv << book.attributes.values_at(*column_names).map{|v| v.to_s.encode('Shift_JIS', undef: :replace, replace: '')}
      end
    end
  end
end

app/controllers/articles_controller.rb

class ArticlesController < ApplicationController
  # /articles.csvでCSV出力できるようにする。
  def index
    @articles = Article.all
    respond_to do |format|
      format.html
      format.csv { send_data Article.to_csv }
    end
  end
end 

【結果】
tech15

複数のモデルから特定の条件で取得したデータをCSVとして出力する

単一のテーブルのレコード全てを一覧出力するよりも、特定条件で取得したデータを必要な項目だけ抽出してCSV出力するケースのほうが多いと思います。
いくつか方法はあると思うのですが、私がよく書くやり方を紹介します。
※もっといい方法がありそうなので、こういうやり方のほうがよさそう等あれば、コメントください。

想定要件
・1か月1以内に作成された記事(Articleモデル)を「著者名」、「タイトル」、「作成日」の項目で一覧表示する。
想定ER
tech16

config/routes.rb

resources :article do
  get :csv_download
end

app/controllers/article.rb

class ArticlesController < ApplicatoinController
  # 追加
  def csv_download
    articles = Article.where(created_at: Date.today..Date.today.next_month)
    csv = ArticleCsvBuilder::ArticleCsvOutput.new
    send_data(csv.output(articles), filename: 'article.csv', disposition: 'attachment')
  end
end

lib/base_csv_builder.rb

# CSV作成の基となるモジュール
module BaseCsvBuilder

 # 出力ベース
  class BaseCsvOutput
    def initialize(filename=nil)
        @base_date = Date.today
        @filename = filename
        @records = []
        @type = 'text/csv'
    end
  end

  # レコードベース
  class BaseRecord
    def self.header(klass = nil)
      self::FIELDS.map { |field| field[1] || klass.human_attribute_name(field.first) }.join(',')
    end
    
   def to_csv
      ('"' << self.class::FIELDS.map { |field| eval("self.#{field.first}").to_s.gsub(/"/, '""') }.join('","') << '"')
   end

   def self.define_field_attr_accessor
     self::FIELDS.each do |field|
       (class << self;
         self;
        end).class_eval { attr_accessor field.first }
        attr_accessor field.first
      end
    end
  end
end

lib/article_csv_builder.rb

#-*- coding: utf-8 -*-
module ArticleCsvBuilder
  class ArticleRecord < BaseCsvBuilder::BaseRecord
    FIELDS = [
      [:author_name, "著者名"],
      [:title, "タイトル"],
      [:created_at, "作成日"]
    ]
    define_field_attr_accessor

   def initialize
     @author_name = ""
     @title = ""
     @created_at = ""
   end
  end

  class ArticleCsvOutput < BaseCsvBuilder::BaseCsvOutput
    def output(articles)
      @records << ArticleRecord.header
      articles.each do |article|
        record = ArticleRecord.new
        record.author_name = article.author.name
        record.title = article.title
        record.created_at = article.created_at.strftime("%Y/%m/%d %H:%M")
        @records << record.to_csv
      end
      @records.join("\n")
    end
  end
end

【結果】
tech17

自動でlib以下を読み込むようにする

Nokogiri編参照

まとめ

2つ方法を紹介しましたが、経験上、1つのモデルのデータを出力するような機能を作ったことはほとんどないです。
2つ目の方法はよく利用していて、用途に応じてカスタマイズして使っています。
もっといい方法がありそうな気がするので、よい方法があれば教えていただけると嬉しいです。

[翻訳+α] Rails/RSpec/Capybara/Seleniumでdatabase_cleaner gemを使う

$
0
0

こんにちは、hachi8833です。

Rails 4.1.1環境でなぜかPoltergeistでスクリーンショットを保存できない問題が解決したら記事にしようと思っていたのですが、間に合わなかったので今回はConfiguring database_cleaner with Rails, RSpec, Capybara and Seleniumという記事を翻訳してみました。
なお、この記事の内容は、弊社で行った「Crafting Rails 4 Applications読み会:第8回資料」と密接に関連します(スライド47 – 53ページあたり)。

解説

RSpecの1つ1つのテスト(beforeとafterも含めて1つの単位とします)は本来互いに独立すべきものなので、本来であればどのような順序で実行されても同じ結果にならなければなりません。だからこそRSpecは2.8からテスト実行順序をランダム化(config.order = "random")できるようになったのです。

しかしテストの量が増えてきたり古いRails環境だったりすると、データベースに残ったデータに知らず知らずに依存してしまうテストが増えてきます。その結果、「単体だと正常に実行できるのに全体テストでエラーになるテスト」や逆に「全体テストでは正常なのに単体だとエラーになるテスト」ができてしまいます。

前者は、たとえば同一のファクトリーを異なるテストでcreateしている場合が考えられます。それぞれのテストではファクトリーをcreateするのは正当なことですが、全体テストでは最初にcreateしたファクトリーが残留して、かつそのモデルで重複が禁止されていれば、2度目のcreateでエラーが生じてしまいます。

後者は、先に行われたテストで生成されたファクトリーに後のテストが依存している場合が考えられます。全体テストではとおりますが、単体だとファクトリーが足りずエラーになります。

database_cleanerを導入するのは、このような状態を避けるためでもあります。もっとも大量のテストがある巨大プロジェクトにdatabase_cleanerを追加すると、依存関係によるエラーが続々見つかって修正が大変かもしれませんが。

個人的には、テストはDRYを目指すより、前処理や後処理が多少重複しても独立性を目指すほうがよいように思います。

[翻訳]Rails/RSpec/Capybara/Seleniumでdatabase_cleaner gemを使う

元記事: Configuring database_cleaner with Rails, RSpec, Capybara and Selenium

Railsのコードを書いている人、Rubyでデータベースを扱うコードを書く人、テストを自動化している人なら、database_cleanerというgemを何となく知っていたり使ったりしたことがあることでしょう。これは実際よくできたgemで、さまざまなORM APIを抽象化してデータベースをきれいな白紙の状態に戻してくれます。

私は定期的にRSpec/Capybara/Selenumを使うRailsプロジェクトを新たに立ち上げていますが、そのたびにテストデータベースの一貫性が損なわれてしまうという憂き目に遭っています。せっかくテストデータベースにレコードをいくつか設定しても、Seleniumで駆動されるブラウザベースのテストは、そんなレコードなどどこにもないかのように振る舞います。最後にやっと問題点を解決し、そのたびに前にも同じ問題に遭遇して同じように解決していたことを思い出すのです。三歩歩くと忘れてしまうおのれの鳥頭が情けなくなります。

ぶつかる問題点は毎度同じです。テストはデータベーストランザクションによってラップされているので、実際のテストプロセスの外で実行されるあらゆるコード(つまり、Seleniumで駆動されるブラウザのリクエストに応答するサーバープロセスなど)からは、そのままでは私が作ったデータベースフィクスチャを参照できないのです。

ちょうどこの間ペアプログラミングを行ったときにも同じ問題を解決したので、そのときの作業を忘れないうちにメモします。皆様の髪の毛が抜けてしまわないために役立てば幸いです。

最初の手順、ここがとにかく肝心です。spec/spec_helper.rbを変更します。

config.use_transactional_fixtures = true

上の設定を以下のように変更してください。

config.use_transactional_fixtures = false

rspec-railsは暗黙のうちにデータベーストランザクションをラップしているのですが、これをオフにしておきます。そうしないと以下の設定が無意味になってしまいます。

次にdatabase_cleanerを設定します。私の場合、spec/support/database_cleaner.rbというファイルをそれ用に作成します。内容はだいたい以下のような感じです。

RSpec.configure do |config|

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

end

解説

順に説明します。

config.before(:suite) do
  DatabaseCleaner.clean_with(:truncation)
end

上の設定は、テストスイート全体が実行される前にテストデータベースを完全に消去します。これにより、中断したテストや下手なテストコードによって生じたゴミを一掃し、テストが思わぬ振る舞いをするのを防ぎます。

config.before(:each) do
  DatabaseCleaner.strategy = :transaction
end

上の設定は、データベース消去のストラテジを”transaction”に設定します。トランザクションは非常に速いので、トランザクションを実行するすべてのテスト(実際のところ、RSpecプロセスで実行されるすべてのテスト)において、この設定を行っておくのがよいでしょう。

config.before(:each, :js => true) do
  DatabaseCleaner.strategy = :truncation
end

上の設定は、「:js => true」フラグが設定された例の前でのみ実行されます。デフォルトでは、Capybaraがテストサーバープロセスを起動してSeleniumバックエンド経由で実際のブラウザを駆動するのはこのようなテストだけです。このようなテストではトランザクションが動作しないので、このコードで設定を上書きしてストラテジを”truncation”に変更しています。

config.before(:each) do
  DatabaseCleaner.start
end

config.after(:each) do
  DatabaseCleaner.clean
end

上の設定は、1つ1つのテストの実行前と実行後にdatabase_cleanerをフックしています。どのようなデータベース消去ストラテジを選択していても、database_cleanerが常に実行されるようにしています。

以上です。
上のコードはRSpec用であり、Cucumberの設定までは考慮していないことにご注意ください。

私が受けたストレスを皆様が避けることができれば幸いです。

追記

Gistで行っているようにすべてのスレッドを同一のActiveRecord接続で共有しないのはどうしてなのかという質問を何人かの方から受けました。いくつか理由を説明します。

  • database_cleaner を使用するのは、ORM(オブジェクト/関係マッピング)が中立であることを期待しているからです。database_cleaner はActiveRecord、DataMapper、MongoMapperなどをサポートしていますが、Gistで説明されているソリューションはActiveRecordでしか動作しません。
  • Gistのモンキーパッチによる方法は、ActiveRecordが内部での接続共有を変更しない間しか有効ではありません。正直、この方法がすべてのRuby VMとデータベースの組み合わせで動作するのかどうか私には確信がありません(追記: 現行のPostgreアダプタで競合が生じるという報告が2名からあがっています)。すべてのコンテキストで動作する設定オプションがActiveRecordにあれば私もこの方法をもっと使うかもしれません。
  • 上で強調したように、これを必要とするテストだけがtruncationにフォールバックするように注意を払いました。:js => trueを使用するテストの量は、私の場合多くはありません(そもそもブラウザを駆動するとどうしても速度が低下してしまいますから使い過ぎないようにしています)ので、私のソリューションで生じるオーバーヘッドについては気にしすぎないようにしています。受け入れテストでブラウザ駆動を全面的に行なうことがあればその点をもう少し気にしたでしょう。
  • データベースをtruncateするとテスト時間が大きく増加するのであれば、そのテストで特定のテーブルのサブセットだけをtruncateするように改良することで速度を向上できるでしょう。database_cleaner を採用しているのはそれがやりやすくなるからでもあります。これについては後日記事にするかもしれません。

追記: @donaldballから良い指摘がありました。テストとテストサーバー間のトランザクションを共有すると、production環境での実行と挙動が異なる部分が生じてしまいます。特に、production環境ではafter_commitフックは決して起動されません。

関連する投稿:

  1. Rack-Test and Capybara are uneasy bedfellows
  2. Announcing NullDB 0.0.1
  3. Complex Hash Expectations in RSpec

[Rails]ビューで配列を改行するなら脆弱なjoinではなくsafe_joinにしよう

$
0
0

こんにちは、hachi8833です。小ネタなのでQiitaに書こうかと思いましたが、こちらにしました。

Railsのビューテンプレートで配列の内容を改行brで区切って縦に一覧表示したいとき(普通ならulを使うところですがあえてbrにします)、こんなコードを最初書いてみました。なおビューではhamlを使用しています。

#コントローラ
@my_array = ['太郎', '次郎', '花子']
#ビュー
=@my_array.join('<br/>').html_safe

が、書いてみてすぐ、このコードが脆弱なため使えないことに気付きました。ここで@my_arrayはユーザーが入力した内容をDBから取り出したものなので、ユーザー入力に悪意のあるタグが含まれていたらXSS脆弱性が発現してアウトです。ビューでユーザー入力にhtml_safeをかけるのは禁じ手です。

何かスマートな方法はないかと探してみたところ、Rails 3.1からsafe_joinというそれ用のヘルパーメソッドが追加されていました。

# File actionpack/lib/action_view/helpers/output_safety_helper.rb, line 31
      def safe_join(array, sep=$,)
        sep = ERB::Util.html_escape(sep)

        array.map { |i| ERB::Util.html_escape(i) }.join(sep).html_safe
      end

今回惜しくもRailsのバージョンが3.0だったので、上のコードをヘルパーに追加しました。また、そのままでは区切り文字までサニタイズされてしまうので、sep = ERB::Util.html_escape(sep)は削除しました。
お互いセキュリティには気を付けましょう。

[RSpec][Turnip] 一般的に使えるTurnipステップ集

$
0
0

こんにちは、hachi8833です。最近ますます好きになってきたTurnipを使いやすくするため、たいていの受け入れテストで使い回せるTurnipステップをテンプレとしてまとめてみました。ある程度ですがCapybaraのカンニングペーパーにもなります。

## -*- encoding: utf-8 -*- 
## 一般的に利用できるTurnipステップ

## テスト用ステップ

	#表示テキスト存在確認
step %(:textと表示されている) do |text|
  expect(page).to have_content(text)
end

	#表示テキスト不在確認
step %(:textと表示されていない) do |text|
  expect(page).not_to have_content(text)
end

## 操作用ステップ

	#ページ移動
step %(:pageページにアクセスする) do |page|
  visit "http://localhost/#{page}"
end

	#リンクをクリック (textはリンク文字列かid)
	#同じ名前のリンクが複数ある場合には文字列は指定できない
step %(:textリンクをクリックする) do |text|
  click_link text
end

	#同じ名前のリンクが複数ある場合に順序も指定
step %(:n番目の:textリンクをクリックする) do |n, text|
  n = n.to_i - 1
  all(:link_or_button, text)[n].click
end

	#ボタンをクリック (textはボタン文字列かid)
	#同じ名前のボタンが複数ある場合には文字列は指定できない
step %(:textボタンをクリックする) do |text|
  click_button text
end

	# フィールドに文字列を入力する |fieldはモデル[属性]の形式
step %(:fieldに:valueを設定する) do |field, value|
  fill_in field, with: value
end

	# ドロップダウンボックスを選択 (textはボタン文字列かid)
	#同じ名前の項目が複数ある場合には文字列は指定できない
step %(:choiceを選択する) do |choice|
  choose choice
end

	# チェックボックスを選択  (choiceは文字列かid)
	# 同じ名前の項目が複数ある場合には文字列は指定できない
step %(:choiceをチェックする) do |choice|
  check choice
end

	# チェックボックスを選択解除  (choiceは文字列かid)
	# 同じ名前の項目が複数ある場合には文字列は指定できない
step %(:choiceのチェックを外す) do |choice|
  uncheck choice
end

## デバッグ用

	# pryを呼ぶ (pry, pry-rails, pry-doc がインストールされていること)
step %(pryを呼び出す) do
  binding.pry
  puts ''
end

	# その時点の静的なwebページを表示する
step %(表示する) do
  save_and_open_page
end

	# ペンディング用
step %(:reasonという理由でペンディング) do |reason|
  pending reason
end

こういうのをこしらえておけば、Turnipのfeatureファイルも以下のような感じでざくざく書けます。

    前提 "[参加者一覧]"リンクをクリックする
    ならば "参加者一覧"と表示されている
    かつ "[参加者編集]"リンクをクリックする
    かつ "[追加]"リンクをクリックする
    ならば "1件追加"と表示されている
    かつ "sankasha[name]"に"参加者001"を設定する
    かつ "sankasha[yomi]"に"さんかしゃよみ"を設定する
    かつ "sankasha[zip_code]"に"239-0803"を設定する
    かつ "sankasha[address]"に"住所1"を設定する
    かつ "sankasha[sub_address]"に"住所2"を設定する
    かつ "sankasha[tel]"に"03-671-2500"を設定する
    かつ "sankasha[fax]"に"03-671-2501"を設定する
    かつ "sankasha[eigyou]"に"営業太郎"を設定する
    かつ "sankasha[email]"に"eigyou@eigyou.com"を設定する
    かつ "追加"ボタンをクリックする
    ならば "参加者001を作成しました"と表示されている

認証やfactoryの準備などはもちろん別途行う必要がありますが、画面ナビゲーションレベルについては大抵間に合うのではないかと思います。皆様も適宜これをカスタマイズしてお使いいただければと思います。Githubにも置きましたので、今後はこちらを更新します。

ここまで落とし込めれば、お客さんにfeatureファイルを書いてもらうことも夢ではないかもしれません(現実にはなかなかないでしょうけれど)。


[RSpec]モックとスタブの使い方

$
0
0

こんにちは、hachi8833です。

なかなかRSpecをうまく書けずに悩んでましたが、morimorihogeさんに教えてもらって、RSpecのモックとスタブの使い分け方が少し見えてきたのでメモします。

スタブの目的

そもそもスタブを使用する目的は、本当にテストしたいところだけをテストできるように、本筋に関係ない部分(バリデーションなど)をとにかく動くようにする、動かしたい場所まで辿り着くことです。例えて言うなら、ペンキを塗ったりエアブラシを使うときに、塗料が付いて欲しくない部分に貼るマスキングテープをイメージするとよいでしょう。テストしたい箇所以外はスタブで塞いでしまうわけです(以下の4行目)。

#vtypes_controller_spec
describe "POST create" do
  it "create_from_text が呼ばれ,client_vtypes_path を再表示すること" do
    Vtype.stub(:type_string).and_return(10)      # ここがスタブ
    post :create, text:"data_text", vtype:"10"   # テストしたいアクション
    response.should redirect_to(client_vtypes_path(filtered_vtype:"10")) # アクションの結果をテスト
  end
end

上の4行目では、下のモデルにあるtype_stringメソッドを偽って、type_stringが10という値を返したということにしてくれています。
以下はVtypeモデルです。

# Vtypeモデル
# name:: 種別 - 日本語 (string),null 不可
# sort_order:: 並び順カラム (integer),null 不可
class Vtype < ActiveRecord::Base
  def self.type_string(num)
    return self.find_by_sort_order(num).name
  end
end

なお以下はコントローラのcreateアクションの抜粋です。

#vtypes コントローラ
def create
  @vtype  = params[:filtered_vtype]
  if @vtype.save
    flash[:notice] = "#{@v.name}を作成しました"
    redirect_to client_vtypes_path(filtered_vtype: @vtype) and return
  else
    @vtype = params[:filtered_vtype]
    render action:'new'
  end
end

スタブのメリットは、オブジェクトやメソッドのふりをするだけなので、データを用意するフィクスチャーやファクトリーよりも高速である点です。また、本筋に関係ない部分が未実装であっても、スタブを使用できます。完全にシステムをだますことができるわけです。

このことからわかるように、「スタブで塞いだ箇所はテストされたことになりません」。スタブで塞いだ部分は、結合テストなど他のどこかの箇所で最終的にテストされていなければなりません。極端に言えば、テストがスタブだけですべて固められてしまっていればそもそもテストの意味がありません。

従って、スタブを多用し過ぎると、その部分を他でテストし忘れていた場合、「テストは通るのに本番でエラーになる」ということになりかねません。

Railsの場合、スタブを使う場所は基本的には単体テスト、主にコントローラになると思います。コントローラのテストは「不要である」と言われることが多く、初心者はコントローラのテストを作るべきかどうか迷いがちですが、結合テストや受け入れテスト(features、requests、acceptanceなど)が別途行われるのであれば、コントローラではアクションが動作することだけ確認すればよいと思います。実際、scaffoldで生成されるコントローラspecはアクションが動くことを確認しているだけです。

モックの目的

モックはスタブと似た面がありますが、モックはそれ自体がテストになり得る点がスタブとは決定的に異なります。これは、テストする対象のオブジェクトが実装されてないとモックは使えないからです。テスト対象オブジェクトがなくても動くスタブとはその点が違います。
実は、モックはその内部でスタブをこっそり使っています。モックを実行すると、最初にスタブを内部で作成してから動かし、次に実際のオブジェクトに同じデータを与えて動かし、両者の結果が同じかどうかを比較します。結果が合えばパス、違えば失敗となるわけです。

describe "POST create" do
  before :each do
    mock_budget.should_receive(:budget_main).and_return(mock_budget_main)
    mock_budget.should_receive(:budget_owner).and_return(mock_budget_owner)
    mock_budget.should_receive(:budget_unit).and_return(mock_budget_unit)
  end

  it "redirects to new_contract_path when creation of contract succeeds" do
    mock_budget.should_receive(:save).and_return(true)
    post :create, budget:{these: :params}
    response.should redirect_to(new_contract_path(budget_id:mock_budget.id))
  end
end

従って、モックはスタブと同様のマスキングテープ的な使い方もできますし、それ自体をテストコードにすることもできます。上のコードの3, 4, 5行目はbeforeの中でスタブ的に使っていますし、9行目ではテストとして書かれています。

おまけ

なお、モックとスタブはてっきりRSpec固有の機能かと思ったら、元々テスティング一般で使用される概念だったんですね。今回参考にした「Ruby on Railsでのモックとスタブの作成」にさらっと『もしかすると私達は、これらの概念の表現としては不適切な言葉を選んでしまったのかもしれません。しかし今や、これらの言葉を使わざるをえません。』と書かれていることからわかるように、モックとスタブという言葉は割りと混乱を呼んでいます。モックとスタブについてこれまでいろんな説明がなされていますが、どれもどうもしっくりこなかったので、自分にとってのまとめとしてこの記事を書きました。

実はこんなにある rails generate

$
0
0

熱いワールドカップが終わって平和な夜に戻ったshibuso です。Rails ユーザの皆さんは色々rails genarate コマンドを利用しているかと思いますが、この前調べていたら「こんなにあったのか!」となったので、今回Rails のgenerator を大まかに紹介してみます。Rails のバージョンは4.0.1 です。

実行結果をまとめてみました

結構数があるので先に目次を作っておきます。順番は重要そうなものだったり気の向くままだったりしていますので、大して意味はありません。

rails generate scaffold

これはもう使ったことがない人はいないレベルでメジャーじゃないでしょうか。モデル名を指定することによりRails のMVC モデルに則った各種ファイルを生成してくれます。article と入力して実行した結果は以下のとおりです(これより下、全て名前をarticle で実行しています)

$ rails g scaffold article
      invoke  active_record
      create    db/migrate/20140716040221_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml
      invoke  resource_route
       route    resources :articles
      invoke  scaffold_controller
      create    app/controllers/articles_controller.rb
      invoke    erb
      create      app/views/articles
      create      app/views/articles/index.html.erb
      create      app/views/articles/edit.html.erb
      create      app/views/articles/show.html.erb
      create      app/views/articles/new.html.erb
      create      app/views/articles/_form.html.erb
      invoke    test_unit
      create      test/controllers/articles_controller_test.rb
      invoke    helper
      create      app/helpers/articles_helper.rb
      invoke      test_unit
      create        test/helpers/articles_helper_test.rb
      invoke    jbuilder
      create      app/views/articles/index.json.jbuilder
      create      app/views/articles/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/articles.js.coffee
      invoke    scss
      create      app/assets/stylesheets/articles.css.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.css.scss

(※同プロジェクトで作っては消してを繰り返してたので、実行環境によって新規作成だったり既にあるのを使ったり、多少結果の見え方に違いが出ます)

rails generate scaffold_controller

scaffold と比べるとあまり使われていないのではないかと勝手に思っているのがこのscaffold_controller です。scaffold の実行で出力されるコントローラとビューと、それらに関わる部分を切り出した感じで生成します。モデルやアセットは作られません。モデルだけ先に作った場合、地味に便利です。

$ rails g scaffold_controller article
      create  app/controllers/articles_controller.rb
      invoke  erb
      create    app/views/articles
      create    app/views/articles/index.html.erb
      create    app/views/articles/edit.html.erb
      create    app/views/articles/show.html.erb
      create    app/views/articles/new.html.erb
      create    app/views/articles/_form.html.erb
      invoke  test_unit
      create    test/controllers/articles_controller_test.rb
      invoke  helper
      create    app/helpers/articles_helper.rb
      invoke    test_unit
      create      test/helpers/articles_helper_test.rb
      invoke  jbuilder
      create    app/views/articles/index.json.jbuilder
      create    app/views/articles/show.json.jbuilder

rails generate controller

コントローラを生成します。scaffold_controller との違いはRESTful な設計を特に考えない土台を作っているというところです。ビューに関してはディレクトリは作成されますが、中に誰もいませんよ中は空です。こちらはアセットを作っています。また入力した単語は複数形にならずそのまま使われます。

$ rails g controller article
      create  app/controllers/article_controller.rb
      invoke  erb
      create    app/views/article
      invoke  test_unit
      create    test/controllers/article_controller_test.rb
      invoke  helper
      create    app/helpers/article_helper.rb
      invoke    test_unit
      create      test/helpers/article_helper_test.rb
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/article.js.coffee
      invoke    scss
      create      app/assets/stylesheets/article.css.scss

rails generate resource

恥ずかしながらこの記事をまとめるまで、このコマンドは使ったことがありませんでした。scaffold と同じようにMVC モデルに沿って生成しますが、こちらはRESTful を意識していないようです。そのためコントローラの中身もビューも空です。

$ rails g resource article
      invoke  active_record
      create    db/migrate/20140716080820_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml
      invoke  controller
      create    app/controllers/articles_controller.rb
      invoke    erb
      create      app/views/articles
      invoke    test_unit
      create      test/controllers/articles_controller_test.rb
      invoke    helper
      create      app/helpers/articles_helper.rb
      invoke      test_unit
      create        test/helpers/articles_helper_test.rb
      invoke    assets
      invoke      coffee
      create        app/assets/javascripts/articles.js.coffee
      invoke      scss
      create        app/assets/stylesheets/articles.css.scss
      invoke  resource_route
       route    resources :articles

rails generate model

モデルの生成と、テーブルをcreate するマイグレーションを生成します。

$ rails g model article
      invoke  active_record
      create    db/migrate/20140716040948_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml

rails generate migration

scaffold に負けず劣らず有名ドコロです、使用頻度で考えるとscaffold よりも多いのではないでしょうか。カラムの型変更からテーブルの追加・削除まで、DB に関する各種変更の操作を記述可能なマイグレーションを生成します。

$ rails g migration AddNameToArticles
      invoke  active_record
      create    db/migrate/20140716052116_add_name_to_articles.rb

rails generate assets

アセットを生成します。最初のscaffold のところからそうですが、CoffeeScript とSass を導入しているためcoffee ファイルとscss ファイルが生成された例となっていますが、入っていない場合はそれぞれ普通のjs ファイルとcss ファイルになります。ここでは入力した単語は複数形にならずにそのまま用いられます。

$ rails g assets article
      invoke  coffee
      create    app/assets/javascripts/article.js.coffee
      invoke  scss
      create    app/assets/stylesheets/article.css.scss

rails generate helper

ヘルパーを生成します。合わせてテストも生成します。こちらも複数形にはなりません。

$ rails g helper article
      create  app/helpers/article_helper.rb
      invoke  test_unit
      create    test/helpers/article_helper_test.rb

rails generate generator

generator を generate します…って、これだけではいまいち理解できないですね。generate する時にgenerator を指定することができるみたいで、そのgenerator をまずgenerate するんだそうです。generator がゲシュタルト崩壊を起こしそう…。詳しくはRailsGuides 等を読んでいただけたらと思います。

$ rails g generator article
      create  lib/generators/article
      create  lib/generators/article/article_generator.rb
      create  lib/generators/article/USAGE
      create  lib/generators/article/templates

rails generate integration_test

インテグレーションテスト(総合テスト)のファイルを生成します。このファイルは他のgenerate コマンドでは作られません。

$ rails g integration_test article
      invoke  test_unit
      create    test/integration/article_test.rb

rails generate jbuilder

Jbuilder はJava の統合開発環境…ではなく、JSON をこねくりまわすシンプルなDSL です。scaffold でも生成されています。ビューはなくてもJbuilder のgenerate コマンドはあるんだな、と思ったり。

$ rails g jbuilder article
      create  app/views/articles
      create  app/views/articles/index.json.jbuilder
      create  app/views/articles/show.json.jbuilder

rails generate mailer

メーラーを生成します。こちらもintegration_test と同じで、このgenerate コマンドでしか作られません。

$ rails g mailer article
      create  app/mailers/article.rb
      invoke  erb
      create    app/views/article
      invoke  test_unit
      create    test/mailers/article_test.rb

rails generate task

Rake タスクを生成します。

$ rails g task article
      create  lib/tasks/article.rake

おわりに

今回はRails のgenerator のみ紹介しましたが、他にも色々generator は用意されているので、一度確認してみると良いかもしれません。下記コマンドで一覧が表示されます。

$ rails g -h

またここで紹介したのは生成されるファイルだけでしたが、ヘルプを見ると各種オプションも記載されているので、使用される際にはそちらも目を通してみると良いかと思います。scaffold の場合は下のようになります。

$ rails g scaffold -h

Rails勉強会まとめ —非同期処理/RSpecなど

$
0
0

こんにちは、hachi8833です。

今回は棚卸しとして、弊社CTOのbabaさんによるRails勉強会スライドから引用して記事にします。
勉強会自体はRails 3.x時代のものなので既出が多くなっていますが、棚卸しも兼ねて今のうちに記事にいたしました。

非同期処理

言うまでもなく、リクエストからレスポンスまでの時間が長くなるほどユーザー・エクスペリエンスの質が低下します。これを改善するためにさまざまな工夫が必要になるわけですが、その中の一つとして、時間のかかる処理をバックグラウンドで実施しておくというのがあります。

cron

最も素朴な方法はやはりunix標準のcronを使って定時に出力データを準備することでしょう。この場合、起動用スクリプト(rakeなど)やジョブ管理は自分で作成する必要があります。

delayed_job

delayed_job gemを使用すると、ジョブをActive Recordで管理できます。
その便利さについては各方面で語られているので省略しますが、以下の点が少々残念であるという指摘があります。

  • ジョブ完了時にキューから該当ジョブを単純に削除するため、完了したのか、Enqueueに失敗したのかわかりにくい
  • データをMarshallで渡すため、バージョンが変わったときにトラブルの元になることがある
  • Railsが動作していることが前提のため、その分重い

resque

3番手はresqueです。resqueはredis (C言語で書かれたKey-Valueストア) を使用してジョブキューを管理します。Redisとresqueがインストールされていれば、Railsなしでも実行可能です(ActiveRecordがないと使いにくいとは思います)。

resqueはJSONでデータを受け渡しするので互換性が高いのが特長です。

※Redisには少々癖があり、旧バージョンでは書き込みIO負荷が高い・メモリ不足の時に落ちる・expireしても次回読み込みまで消えないなどの問題があったようです(2012年時点の情報なのでその後状況が変わっている可能性あり)。

使い方は以下をどうぞ。

resqueはgemで拡張するのが習わしになっています。

resqueの注意点など

  • resqueはマスタープロセスからforkさせてからキューを実行するので、デプロイ時にはマスタープロセスの再起動が必要。
  • Workerクラスはモデルの内部クラスとして実装すると見通しがよくて便利です。
  • resqueの監視にはmonitが無難でおすすめです(godよりは安定しているみたい)。
  • Mysql::Error: MySQL server has gone awayエラーが発生する場合は、最初にActiveRecord::Base.verify_active_connections!を行ってみよう。database.ymlにreconnection:trueと書く手もあるようですが、長いトランザクションの途中でreconnectされると怖いかも。

RubyのWebアプリケーションフレームワークについて

sinatraといえばRubyによる軽量フレームワークとして今や定着しました (一時はRails3の登場で絶滅が危惧されたそうです)。プロジェクトの規模に応じて、RailsとSinatraを使い分け、場合によってはRackを直接駆動するというのがよい感じです。

ちなみに紹介記事を元に生Rackアプリを書いてみたら、えらく簡単でした。

class MyApp
  def call(env)
    [
      200,
      { 'Content-Type' => 'text/html' },
      ['<html><head></head><body><h1>hello</h1></body></html>']
    ]
  end
end

テスト駆動開発(TDD)について

TestFirstとTDDは同じものではありません。TestFirstは単にテストが先行しているだけの状態であり、TDDはテストが開発を牽引しているかどうかという点が違います。

テストのカバレッジですが、一般的に言って100%にこぎつけるのはやはり難しいと言えます。カバレッジにはC0/C1/C2などの段階がありますが、たとえばbegin/rescueブロックをどうチェックするか、fork先のプロセスまでチェックするかなど、追い求めるときりがありません。Coverageは90%を目指すのが現実的だと思います。

xUnitRSpecという図式について、Railsでは当時からRSpecが支配的だったこともあり、弊社ではRSpecの使用が推奨されてきました。

RSpecでのノウハウ

以下パラパラとメモします。

  • テスティングでよく使用されるのはAAAというパターンです。
  1. Arrange: 環境のセットアップ
  2. Act: テスト対象を実行
  3. Assert: 結果を検証
  • itでのテスティングの説明は極力シンプルにしましょう。ほとんどの場合1行以内に収まるはずです。
  • beforeをうまく使ってテスティングの下準備部分をまとめ、効率化するのがポイントです。デフォルトではbefore :eachなのでその場合:eachは省略できます。
  • itを生成するメタプログラミングもありですが、あまり複雑にするのはよくないようです。入力・出力のペアをまとめて検証するぐらいにしておきましょう。
  • JavaScriptのテストは一律行うと遅いので、必要な部分のみを実施するようにしましょう。最初にJSをオフにして全テストを実行し、最後にJSが必要な部分だけを実行すると効率的です。具体的には、decribeブロックごとにRackとWebKitを切り替えます。つまり、必要な場合にのみWebKitを使用してJavaScriptをテストし、通常は極力Rackを使用します。RackはWebKitより10倍速いので。
  • 毎回RSpecをフルで回していると時間がかかってしょうがないので、RSpec実行時に --fail-fast を指定すると、失敗が1つ発生した時点でテストが終了するので、うまく使えば時間を節約できます。
  • bundle exec rspec spec / --fail-fast
    

    RSpecのマッチャー

    RSpecも少し前に3.0が登場しましたが、以前のノウハウもまだまだ健在です。
    RSpecのマッチャーで真っ先に覚えるべきはbe_hogehoge系のpredicate(述語)マッチャーでしょう。このマッチャーが機能するには、hogehoge?というメソッドが必要ですので、逆に言えばこのマッチャーが使えるようにコードを書くようにしましょう。ついでながら、このメソッド名もマッチャーがおかしくならないような名前にしておきたいものです。「is_flag?」みたいなメソッド名だとマッチャーが「be_is_flag?」みたいなみっともない名前になるので、そういう名前は使うものではないということがわかります。

    他にビルトインのsatisfyマッチャーはブロックを引数に取り、ブロックがtrueかどうかをチェックします。

    raise_errorマッチャーは例外が発生するかどうかを確認できるビルトインマッチャーです。例外のテストは意外と忘れがちです。

    それから、カスタムマッチャーは遠慮せずにどんどん作りましょう。複雑なオブジェクトをeqで比較できるようにするとか。

    UIテストについて

    TestFirstが常に善とは限りません。UIを試行錯誤しながら開発するときにはTestFirstはほとんど意味がないのでとっとと諦めましょう。UIにびっしりテストを書いたところで、仕様が変わったときのダメージが大きいので、必要な分だけにしておきましょう。

    UIのテストでは、むしろ「/usersだったらuserがたくさん表示されていることを確認する」など、瑣末でない本質的な部分を押さえるようにしてください。後、クライアントの指示で必ず含めなければならない定番の文言があるならそれをテストに含めるのも有効です。

    テスト内容がCSSセレクタでデザインに依存するのはよい傾向ではありません。注意しましょう。

    テストデータ

    単体テストでは、テスト対象以外の関連オブジェクトのデータを作るかどうかが思案のしどころです。大きく分けて、モックでさくさく進めるか、ちゃんとオブジェクトを作成(Object#create)するかです。

    • モックは動作も高速で比較的作りやすいのですが、関連オブジェクトの仕様が変わっても検出できないという問題があります。
    • Object#createは面倒な代わりに、関連オブジェクトの仕様が変わった場合に検出することができます。

    どちらを選ぶにしても、テストをどのように分離し、網羅するかはしっかり考えておく必要があります。単体テストはその対象だけに集中すべきと考えるなら、結合テストで関連オブジェクトとの関係をカバーする必要がある、というふうに。

    ところで、テストで時間を扱うにはtimecop gemが便利です。

    テスト環境・ドキュメント

    CI(継続的インテグレーション)サービスにはtravis CIを始め多くのサービスが出現していますので、積極的に使いましょう。

    rspec --format documentation -o 出力ファイル名でRSpecのログを残せます。rspec --format html -o 出力ファイル名とすればHTML形式で出力できます。

    自動生成ドキュメントは何かと使いづらいので、必要なドキュメントがあれば自分で書きましょう。

    • 主要エンティティER図
    • 主要エンティティ状態遷移図
    • などなど

    active decorator

    ヘルパーファイルの命名はビューに依存していて、数が増えてくるとapp/helperの下のどれに追加したらよいか迷ってしまいます。メソッドを追加したいのはモデルであることが多いのですが、モデルが肥大化するのは避けたいものです。

    そんなときにはactive decoratordraperなどのdecoratorパターンです。full_nameなどのメソッドを簡単に見通しよく追加できます。

    decoratorパターンについては『肥大化したActiveRecordモデルをリファクタリングする7つの方法』も参考にしてください。

    [翻訳] Rails Guideの翻訳を進めました

    $
    0
    0

    こんにちは、hachi8833です。これまでチマチマ翻訳してきたRails Guideへのリンクをご紹介します。ガイド全体から見ればまだ半分ぐらいですが、サイズの大きいファイルから先に翻訳を進めてきたので、残っているのは比較的小さなファイルです。

    注意: これらのファイルは今のところ翻訳が完了しただけであり、レビューなどはまだ行われていません。各人の責任でご利用ください。

    補足: Githubに置いたことでmarkdownは簡易整形されていますが、画像は表示されません。Railsガイド ガイドラインに記載されている方法で Railsガイドをビルドすれば画像+CSSのあるガイドが得られます。
    ファイル間のリンクはビルドが前提なので、そのままでは無効です。
    訳していて怪しいと思った箇所には●を付けてとっとと先に進んでいます。
    原文に忠実な訳とは限りません。原文より情報を増やしたり言い方を変えてあるところが多々あります。
    たまに原文のdiffの残りが巨大な文字で表示されていることがありますが気にしないでください。
    今後置き場所を移動する可能性がありますのでご了承ください。

    Rails Guide (最近翻訳した分)

    Rails Guide (これまで翻訳した累積分)

    入門編

    モデル関連

    コントローラ関連

    応用編

    更新情報

    小物ファイル

    Rails アプリケーション開発で役に立ったJavaScript デバッグの小技

    $
    0
    0

    Chrome devtools でイベント監視

    いろいろなJavaScriptプラグインを使っていると
    イベントの伝播を止めてしまうような動作をするものを使ってしまうことがあります。
    function を割り当てたいイベントが止められていると厄介です。
    代用できるイベントが生き残っていればそちらを使ってしまいたいです。
    そんな時、どんなイベントが発生しているのかは Chrome devtools のmonitorEvents で確認することができます。
    https://developer.chrome.com/devtools/docs/commandline-api#monitoreventsobject-events

    第一引数で監視対象、第二引数でイベントを指定します。

    monitorEvents(window, "resize");
    

    イベントの指定はイベント名だけでなく、”mouse” でマウス系のイベントを”key” でキーボード入力系のイベントを指定できます。
    配列にして渡せば複数のイベントを確認できます。
    省略した場合は全てのイベントが対象になりますが、プラグイン側で独自に定義したイベントは拾えないようです。

    イベント監視の解除は

    unmonitorEvents(window)
    

    引数は同じです。

    Better Errors でエラー確認

    link_to :remote 等を使ってAjax 処理を行っていると
    例外が発生してもエラーの内容をブラウザで確認できないので
    development.log を開いて確認していたのですが、
    Better Errors を使っているなら
    /__better_errors
    にアクセスするだけで簡単にエラーが確認できます。
    Better Errors を使うようになって暫くたつのですが、最近までこの機能を知りませんでした。
    /__better_errors では直前のエラーを確認することが出来るようです。
    https://github.com/charliesome/better_errors/wiki#view-last-error

    Better Errors なしだと devtools でエラーが起こったことだけしかわからないですが。

    この後はdevelopment.log を確認したりコードを見なおしたり。

    Better Errors を入れておけばこのようにエラーの詳細が確認できます。
    ajax_better_errors

    binding_of_caller も合わせてインストールしておけば、@users が空だということがすぐに確認できます。

    これを知ってからAjax処理中に起きたエラーの確認がとても楽になりました。
    この機能、README ではなくWiki の方に記載されているのですが、これはREADME にも記載しておいて欲しいですね。

    Viewing all 1384 articles
    Browse latest View live