Category Archives: Ruby

Lokka で Google Analytics のトラッキングコードを簡単に挿入するための Helper Plugin を書いてみた

Lokka は komagata さんが開発されている、Ruby で書かれた CMS です(旧名 Pyhä)。
打倒 WordPress を目指しているそうです。

komagata’s lokka at master – GitHub

今後使用しようと思っていて、 Plugin も書けるということで、ちょっと試してみました。
簡単に Google Analytics のトラッキングコードが挿入できる Plugin です。

$LOKKA_ROOT/plugin フォルダに hello というサンプルがあるので、それを見ながら書いてみます。
komagata さんのエントリによれば、 Sinatra Extensions のサブセットだということ。

Pyhaの大体の仕組み – komagata [p0t]
Sinatra: Writing Extensions

$LOKKA_ROOT/plugin/ に google_analytics/lib/google_analytics.rb というファイルを作りました。
そして以下を記述。

module Lokka
  module Helpers
    def analytics(uid)
      haml(<<-script, {})
%script{ :type => "text/javascript" }
  :cdata
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', '#{uid}']);
    _gaq.push(['_trackPageview']);

    (function() {
      var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
      ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();
      script
    end
  end
end

モジュール名をどうしたらいいのかわからなかったので、 $LOKKA_ROOT/lib/lokka/helpers.rb を参考に Lokka::Helpers に入れてしまいました。

Rails の感覚だと後は、サーバを再起動すれば動きそうですが、このままでは動きません。
おかしいなぁと思って、プロジェクトを grep してみると、 init.rb にこんな行が。

$:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'plugin', 'hello', 'lib'))

これは同じように入れないといけないんだろうかと、こう書いてみる。

$:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'plugin', 'google_analytics', 'lib'))

そしてもう一カ所、 $LOKKA_ROOT/lib/lokka.rb を見てみると

require 'lokka/hello'

なんて行があるので、同様に

require 'lokka/google_analytics'

と書いたところ、無事に動きました。

Redmine を nginx + Unicorn で動かしてみる

今後のために、一度 Webサーバである nginx と Railsサーバ?の Unicorn を使って Redmine を動作させてみることにしました。
すでに Redmine は Apache + Passenger で動いています。

環境

  • Ubuntu Server x86_64 10.04

Rack のアンインストール

このエントリを書いている時点では Redmine は Rails 2.3.5 で作成されていて、 Rails 2.3.5 は Rack 1.0.1 を使用します。
もし Rack の1.2.1とかがインストールされている場合にはアンインストールしましょう。
でないと、こんなエラーが出て起動しません。
これにだいぶんはまりました。

I, [2010-10-05T14:04:25.155622 #26791]  INFO -- : unlinking existing socket=/tmp/unicorn.sock
I, [2010-10-05T14:04:25.155914 #26791]  INFO -- : listening on addr=/tmp/unicorn.sock fd=3
I, [2010-10-05T14:04:25.156344 #26791]  INFO -- : Refreshing Gem list
Missing the Rails 2.3.5 gem. Please `gem install -v=2.3.5 rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.

Unicorn 0.96 doesn’t play nice with Rails 2.3.5

インストール

$ sudo apt-get install nginx
$ sudo gem install unicorn

Unicorn の設定

設定のほとんどは nginx + Unicorn を試してみた – milk1000cc からのコピペです。

ここで設定するソケットを後で使用します。

$ vi $RAILS_ROOT/config/unicorn.rb
# ワーカーの数
worker_processes 2

# ソケット
listen '/tmp/unicorn.sock'

# ログ
stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])

# ダウンタイムなくす
preload_app true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  old_pid = "#{ server.config[:pid] }.oldbin"
  unless old_pid == server.pid
    begin
      # SIGTTOU だと worker_processes が多いときおかしい気がする
      Process.kill :QUIT, File.read(old_pid).to_i
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

設定ができたら Unicorn を起動します。

$ unicorn_rails -c config/unicorn.rb -E production -D

nginx の設定

http にきたものはすべて https に転送するようにしているので、設定は以下のようになります。

upstream unicorn の部分で設定するものは、先ほどの unicorn.rb で設定したソケットです。
最下行から2行目の proxy_pass で設定する部分は、最上位の upstream hoge の hoge になります。

$ vi /etc/nginx/sites-available/redmine
upstream unicorn {
         server unix:/tmp/unicorn.sock;
}

server {
        listen          80;
        server_name     example.com; 
        rewrite ^/(.*) https://example.com/$1 permanent;
}

server {
        listen  443;    
        server_name     example.com;

        root            /var/www/redmine/public;
        error_log       /var/www/redmine/log/error.log;

        ssl  on;
        ssl_certificate  /etc/nginx/ssl/apache.pem;
        ssl_certificate_key  /etc/nginx/ssl/apache.pem;
        
        ssl_session_timeout  5m;
        ssl_protocols  SSLv2 SSLv3 TLSv1;
        ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
        ssl_prefer_server_ciphers   on;

        location / {
                if (-f $request_filename) { break; }
                proxy_set_header X-Real-IP  $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_pass http://unicorn;
        }
}

サーバのスタート

$ sudo ln -s /etc/nginx/sites-available/redmine /etc/nginx/sites-enabled/redmine
$ sudo /etc/init.d/nginx start

参考文献

devise で Basic 認証をする

devise は高機能な Rack ベースの認証システムだそうです。
plataformatec’s devise at master – GitHub

よくあるログイン画面を表示して認証する方式もありますし(これはなんというのだろう?)、いろいろな認証方式を使用することができるようです。

今回、お試しサイトを作る必要があって Basic 認証を使用することにしました。
その方法をググってもいまいちわからなかったので、ここに記載しておくことにします。
しかしながらこれで使い方があっているのかどうか、いまいち自身がないので間違っている場合には、ご指摘をお願いします。

devise では通常以下のようなコードで認証を必須にできます。

class ArticlesController < ApplicationController
  before_filter :authenticate_user!
end

以下のページによると HTTP を使用した認証にはこんな風に書いてあります。
How to: use http authentication – devise – GitHub

def http_authenticate
  authenticate_or_request_with_http_digest do |user_name, password|
    user_name == "foo" && password == "bar"
  end
  warden.custom_failure! if performed?
end

今回はパスワードは固定ではないので、えいやとこれだけにしてみました。

class ArticlesController < ApplicationController
  before_filter :authenticate_user!

  def http_authenticate
  end
end

思った通りに Basic 認証で認証することができるようになりました。

Capistrano with Bundler and RVM

最近、新しい Rails サーバを立ち上げる必要が出てきて、一から Capistrano によって deploy をする必要に迫られました。

Capistrano についてはいろいろなところで良質な記事があるので、それ自体を使うのは難しくはないと思うのですが、 RVM や Bundler を使用した環境で使用する場合に結構はまってしまったので、記録しておこうと思います。

サーバ側で RVM を使用する場合

RVM: Ruby Version Manager – RVM with Crapistrano を参照し、Ruby 1.9.2 を使うのであれば、以下の3行を deploy.rb に書き加えます。

$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
require "rvm/capistrano"
set :rvm_ruby_string, '1.9.2'
set :rvm_type, :user

deploy 時に Bundler で Gem を更新する場合

deploy 時に bundle install で Gem をインストールしてほしいと思います。

大前提として、 Bundler を最新版にしておくことが重要です。
自分の場合、古いバージョンが入っていて上手く動きませんでした。

config/deploy.rb に

require "bundler/capistrano"

と書いておけば、 deploy 時に標準では shared/bundle フォルダに bundle install をしてくれます。

RSpecでMacro?を書く。

RSpecを使ってSpecを書いていると何度も同じことを書くことが多いです。

たとえばパラメータに応じてページタイトルを変えたい場合とか、validationがきちんと行われているかとか。。。
毎回、 it “should have hoge” do … end と書いているのは大変です。
RSpecではいくつかの方法を使用して、もっと簡単に書くことができます。

クラスメソッドを使う

一つのspecファイルで何度も使うものであればクラスメソッドにします。

[$RAILS_ROOT/spec/views/articles/index.html.erb_spec.rb]

describe "/articles" do
  def self.it_should_have_tag(selector, content)
    it "should have '#{content}' at '#{selector}'" do
      response.should(have_tag(selector, content))
    end
  end
end

と書いておけば、以下のような書き方が可能になります。

[$RAILS_ROOT/spec/views/articles/index.html.erb_spec.rb]

describe "/articles" do
  def self.it_should_have_tag(selector, content)
    it "should have '#{content}' at '#{selector}'" do
      response.should(have_tag(selector, content))
    end
  end

  it_should_have_tag('tr>td', 'MyString')
end

it_should_have_tag(‘tr>td’, ‘MyString’) の部分だけで適切なspecに展開されます。
1行で簡潔に書けますので、理解する時間も短くてすみます。

自分はページタイトル、meta description、meta keywords、RSSのスペックに以下のコードを使用しています。

[$RAILS_ROOT/spec/views/articles/index.html.erb_spec.rb]

describe "/articles" do
  def self.it_should_have_tag(selector, content)
    it "should have '#{content}' at '#{selector}'" do
      response.should(have_tag(selector, content))
    end
  end

  def self.it_should_have_page_title(title)
    it_should_have_tag('head>title', title)
  end

  def self.it_should_have_meta_description(meta_description)
    it_should_have_tag('head>meta[name=description][content=?]', meta_description)
  end

  def self.it_should_have_meta_keywords(meta_keywords)
    it_should_have_tag('head>meta[name=keywords][content=?]', meta_keywords)
  end

  def self.it_should_have_rss_link(link)
    it_should_have_tag('head>link[rel=alternate][type=application/rss+xml][href=?]', link)
  end
end

モジュールに追い出す

さらによく使う項目、上記のhtmlに関するspecなどはたくさんのところに書かれるであろうことが推測されます。
そういう場合には、モジュールに追い出してしまうということが可能だということを同僚のquekさんに教えていただきました。1

$RAILS_ROOT/spec/support フォルダにモジュールのファイルを書きます。
上記の例であれば

[$RAILS_ROOT/spec/support/tag_macros.rb]

module TagMacros
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def it_should_have_tag(selector, content)
      it "should have '#{content}' at '#{selector}'" do
        response.should(have_tag(selector, content))
      end
    end

    def it_should_have_page_title(title)
      it_should_have_tag('head>title', title)
    end

    def it_should_have_meta_description(meta_description)
      it_should_have_tag('head>meta[name=description][content=?]', meta_description)
    end

    def it_should_have_meta_keywords(meta_keywords)
      it_should_have_tag('head>meta[name=keywords][content=?]', meta_keywords)
    end

    def it_should_have_rss_link(link)
      it_should_have_tag('head>link[rel=alternate][type=application/rss+xml][href=?]', link)
    end
  end
end

使用する際には include TagMacros を書いておきます。

[$RAILS_ROOT/spec/views/articles/index.html.erb_spec.rb]

describe "/articles" do
  include TagMacros

  it_should_have_tag('tr>td', 'MyString')
end

自分のような include 〜 を書くのもものぐさだという人は、 $RAILS_ROOT/spec/spec_helper.rb に config.include メソッドを使用すれば、自動的に読み込まれるようになります。

[$RAILS_ROOT/spec/spec_helper.rb]

Spec::Runner.configure do |config|
  # ...
  config.include(TagMacros, :type => [:views])
  # ...
end

上記のように :type を指定すれば view だけで読み込まれるというような指定も可能です。

参考

Railscasts – RSpec Matchers & Macros
Writing Macros in RSpec • Blog Archive • Ben Mabey

P.S.
参考にしたサイトではMacroと書いてありますが、どうもこれをMacroと読んでいいものなのかどうかかなり謎なので、タイトルはMacro?と?付きにしてみましたwww

  1. quekさんによると、下の「参考」のところに書いた Railscasts に同様のことが書いてあり、そのアドレスを過去の自分は社内のチケットに書いていたらしいのですが、モジュールに出すことは全く知りませんでしたwww []

ssl_requirement pluginでssl_required(:all)と書きたい!

Ruby on RailsでSSLで通信する必要があるページには、DHH謹製らしい?ssl_requirement pluginを使用すると、以下のようにに簡単にhttpsにリダイレクトしてくれるようにできます。

class Hoge < ApplicationController
  ssl_required(:index)  # インデックスページだけSSLで通信する。

  def index
    # some crazy codes ...
  end

  def show
    # some rotten codes ...
  end
end

残念ながら、このssl_requiredはアクションに:allとか書いてコントローラ全部を対象にするというようなことができません。
allというアクションを定義する場合もあるからこうなっているのかもしれません。

コントローラ全体にSSL通信をさせるようにするための方法については、コントローラ全体をssl強制に – 車輪の再発明というサイトに、trueを返すssl_required?メソッドを定義する方法が書かれています。

現在書いているRailsアプリでも同様のことが行われているものの、いかんせんたびたび見る気がしてきて、クラスメソッドにしようかと思いました。
でも、すでにssl_requiredというメソッドがあるところに、さらなる同じようなメソッドを作るのは避けたいし、やっぱりssl_required(:all)と書きたいと思いました。

そこでalias_method_chainを使用して、ApplicationControllerをこんな風にしてみました。

class ApplicationController < ActionController::Base
  include SslRequirement

  # some codes...

  class << self
    def ssl_required_with_all(*actions)
      if actions.include?(:all)
        class_eval do
          def ssl_required?
            true
          end
        end
      else
        class_eval do
          ssl_required_without_all(*actions)
        end
      end
    end
    alias_method_chain(:ssl_required, :all)
  end
end

まともにclass_evalとかがわかっていないので、かなり怪しいです!!!

Apple Push Notification Serviceを利用した、iPhone クライアントと、Rubyによるサーバの作成。

[とりあえず表示しましたが、これからコードをアップロードしたり改変していきます。]

先週から、システム部で何か動くものを作って発表するという企画?が始まりました。
プログラムプレゼンテーションを始めてみたら意外に良かった

第一弾は自分だったので、1週間しかなかったので、ちょこっとやればできそうで今までやってみたかったiPhone OS 3.0の目玉機能の一つ、Push Notification Serviceの実装をやってみることにしてみました。

iPhoneクライアントはほぼObjective-Cしかありませんのでそれを使い、サーバはRubyで実装しました。

以下が発表したスライドを少し改変したものになります。

コードは今回はbitbucket.orgにアップロードすることにしました!
コードはこちらになります。
http://bitbucket.org/milkcocoa/apns-test/

ただしサーバのファイルに関しては

  • デバイスIDとかの部分はxでマスクしています。
  • キーに関してはスライドで指定した方法で記述してください。

[ポイントを書く。]

mislav-will_paginate pluginを使用したページをRSpecでテストする。

Webアプリケーションでは、たくさんの項目を一覧表示する場合、1ページに全部見せるのではなくpaginate処理をして数ページに分ける場合があります。
たとえばGoogleの検索結果は通常、1ページに10件しか表示されません。

そういうページをRuby on Railsで作成する場合には、mislav-will_paginate pluginというプラグインを使用するということは割とよく知られていることです。

先日もそういうページを作成する必要があり、作成していましたが、RSpecでテストを作成しようとしたところやり方がわからず詰まりました。
そのため、その方法をここに記しておこうと思います。

ドキュメントを読もう!

実はGitHubのpluginのWikiページに最低限必要なことは書いてありました。
気がついていればもっと早く解決していたところでした。
「I’m getting “undefined method `total_pages’” error when rendering in the view!」という部分ですね。

ポイントはpaginateやtotal_pagesというメソッドをstub!で定義してあげることです。

実際のコード

  • Controller: ArticlesController
  • Model: Article
    • title: string
    • body: text

Controllerのテスト(の一部)

[$RAILS_ROOT/spec/controllers/articles_controller_spec.rb]

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe ArticlesController do
  describe "handling GET /articles" do
    before(:each) do
      article = mock_model(Article)
      article.stub!(:find).and_return([article])

      @articles = [article]
      @articles.stub!(:total_pages).and_return(1)
      @articles.stub!(:paginate).and_return(@articles)
    end

    def do_get
      get(:index)
    end

    it "should be successful" do
      do_get
      response.should be_success
    end

    it "should render index template" do
      do_get
      response.should render_template('index')
    end

    it "should find all articles" do
      Article.should_receive(:paginate).with(:page => nil, :per_page => 100).and_return(@articles)
      do_get
    end

    it "should assign the found articles for the view" do
      do_get
      assigns[:articles].should == @articles
    end
  end
end

ちなみに29行目の:page => nilになっているのは、たぶんassingsとかでparameterを指定していないからこうなるのだと思います。
まだshould_receiveをきちんと理解していないで、まともな説明が書けません。

Viewのテスト(の一部)

[$RAILS_ROOT/spec/views/articles/index.html.erb_spec.rb]

require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')

describe "/articles/index.html.erb" do
  include ArticlesHelper

  before(:each) do
    article_98 = mock_model(Article)
    article_98.stub!(:id).and_return(1)
    article_98.stub!(:title).and_return('MyString')
    article_98.stub!(:body).and_return('MyText')

    article_99 = mock_model(Article)
    article_99.stub!(:id).and_return(2)
    article_99.stub!(:title).and_return('MyString')
    article_99.stub!(:body).and_return('MyText')

    @articles = [article_98, article_99]
    @articles.stub!(:total_pages).and_return(1)
    @articles.stub!(:paginate).and_return(@articles)

    assigns[:articles] = @articles
  end

  it "should render list of articles" do
    render "/articles/index.html.erb"
    response.should have_tag("tr>td", "MyString", 2)
    response.should have_tag("tr>td", "MyText", 2)
  end
end

RubyでArrayの部分集合を作成する。

Arrayの部分集合を作成する必要があったので、作ってみました。

class Array
  def subset
    rec = Proc.new do |univ|
      # subset!でポインタが循環しないようにcloneを使う。
      (ret = []) << univ.clone
      univ.each do |e|
        ret += rec.call(univ - [e])
      end
      ret
    end

    rec.call(self).uniq
  end

  def subset!
    self.replace(self.subset)
  end
end

他には同じサイズの配列を作成して、その要素を使用するかどうかtrueかfalseのフラグを立てていくという手法もあるようです。

irbで実行するとこうなります。

>> a = %w(1 2 3 4)
=> ["1", "2", "3", "4"]
>> a.subset
=> [["1", "2", "3", "4"], ["2", "3", "4"], ["3", "4"], ["4"], [], ["3"], ["2", "4"], ["2"], ["2", "3"], ["1", "3", "4"], ["1", "4"], ["1"], ["1", "3"], ["1", "2", "4"], ["1", "2"], ["1", "2", "3"]]

2009/7/20 追記

twitterですばらしい方法を教えていただきました!

ただしRuby 1.8.7で追加されたcombinationというメソッドを使用しているので1.8.7以降限定です。
cf. Ruby 1.8.7で使えるようになったRuby 1.9のメソッドたち – (rubikitch loves (Emacs Ruby CUI))

class Array
  def subset
    (0..self.length).inject([]) do |ret, n|
      ret.push(*self.combination(n))
    end
  end
end

irbでの実行結果。

>> a = %w(1 2 3 4)
=> ["1", "2", "3", "4"]
>> a.subset
=> [[], ["1"], ["2"], ["3"], ["4"], ["1", "2"], ["1", "3"], ["1", "4"], ["2", "3"], ["2", "4"], ["3", "4"], ["1", "2", "3"], ["1", "2", "4"], ["1", "3", "4"], ["2", "3", "4"], ["1", "2", "3", "4"]]

すごくすっきりしました!

レセプトオンライン送信で請求ができたかを確認するRubyスクリプト

すごいニッチなところをすみませんwww。

レセプトオンライン送信について知っている人だけをまずは対象にしています。

複数の店舗のレセプトを一括してオンライン請求するときにきちんと請求済みになっているかどうか1 を(念のため)確認するのは2(社保、国保) × 店舗数分やらないといけないので大変です。
特にEeePCを使っていると遅いので、だいぶん大変度が増します。
ということで、Rubyでオートマティックに確認するスクリプトを書いてみました。
神奈川県の事例しか知らないので神奈川県限定です。
スクリプト中の神奈川県に関する部分を修正すれば、ほかの県でももしかしたら利用できるかもしれません。
またHTMLを解析して、やっていますのでサイトの構成やHTML等が変わってしまった場合には利用ができません。

共有はしますが、ノーサポートです。
私はこのスクリプトを使用して生じた一切の責任を負いません。

ライセンスをどうしようかと思いましたが、どのみちスクリプトですから改変しても公開せざるを得ないと思うので、GPLv3にしておきます。2

動作環境は

  • Windows3
  • Ruby 1.8.7
  • RubyGems 1.3.2
    RubyGemsによってインストールした

    • WWW::Mechanize 0.9.2
    • Term::ANSIColor 1.0.3
    • Win32Console 1.2.0
    • およびそれらの依存ライブラリ(Nokogiri等)

です。
これらのインストールに関する質問はお答えできませんので、あらかじめご了承を。

さらにopenssl(UNIX系だと普通にあると思われる4 )を用いて配布されているp12形式の証明書ファイルからcerファイルとkeyファイル(この二つをいまいちわかっていない)を作成します。

パスワードの入力を求められますが、これは証明書発行時に発行されたパスワードになります。

openssl pkcs12 -in hoge.p12 -clcerts -out hoge.cer -nokeys
openssl pkcs12 -in hoge.p12 -clcerts -out hoge.key -nocerts -nodes

さらに店舗情報としてYAMLファイルを作成します。
名前は適当につけていただいて、ファイルの中身は

- name: hoge
  id: 0120444444
  password: hogepass
  cert: hoge.cer
  key: hoge.key
- name: piyo
  id: 0120888888
  password: piyopass
  cert: piyo.cer
  key: piyo.key

とかしてください。

nameは任意の区別できる名前にします。
id, passwordはその薬局がログインするときのIDとパスワードです。
certとkeyは上記で作成したcertファイルとkeyファイルのパスを指定します。
後のオプションはきっとわかると思います。
このときWindowsでパス区切りに使われるバックスラッシュ(\)はうまく動いてくれなかったように思えるので、スラッシュでパスを区切りました。

あとは

ruby receipt_check.rb hoge.yaml

とでも打ち込めば、請求済みであれば緑色の字で[OK]、請求済みになっていない場合には[Failed]と表示されます。

ruby receipt_check.rb -t hoge.yaml

のように -t オプションをつけると、確認試験で実行します。

さらに自分は上記コマンドを呼び出すバッチファイルを作成し、それをcmd.exeで呼び出すリンクファイルを作ってリンクファイルをクリックするだけで確認できるようにしてあります。

TODOはそこにも書いてありますが、エラー処理を全くしていません。
そのため運用時間外などに実行すると、運用時間外ですとか知らせることなく、思い切りスクリプトのエラーが出ます。
もしやる気があれば、未請求になっていた場合にはスクリプトで請求できるようにしたり、もうスクリプトだけで請求するということも考えています(こちらは実現が難しそう)。

あと、できるだけ修正はしたいと思いますが、最終的なデバッグはレセプトオンライン送信の端末でしかできないので、修正まで非常に時間がかかる場合、修正しない場合があります。

ということで、以上を理解した方のみダウンロードはこちらから。

  1. 送信してから、請求するボタンを押さないといけません []
  2. 正直ここらは返るかもしれません []
  3. 今から考えると確認するだけならWindowsである必要はありませんね。 []
  4. MacでやったのでWindowsだとわからない []