複数人で利用するリモートブランチを扱う場合、masterブランチのみで開発を行うことは実質不可能となり、topicブランチやfeatureブランチ等、何かしらブランチを作成して品質を確保した上でメインブランチにPull Requestを行って反映するようなやり方をすることが多くなります。その際にメインブランチではコミットが頻繁に行われたりすると派生ブランチは古いバージョンのソースからブランチが切られていたりして、最新コミットに追従出来ていない状態においちることがあります。
Gitには平行開発を安全に、派生ブランチを健全に運用していくためのいくつかのコマンドがあり、その代表の1つとしてrebaseがあります。rebaseは単純に説明すると「既にコミット済みのものを再編集する」ものですが、最新コミットへのブランチの追従やコメントの付け替え、複数のコミットをまとめたり出来ます。
細かい使い方、ブランチの順番等を思い出す時はヘルプを参照するとブランチの図入りで例が載っているのでおすすめです:
1
|
|
派生したブランチ(topic)にて開発していた場合に、メインブランチ(master)の開発が進み最新コミットが入り込んだ場合に追従し、最新コミットからのブランチから枝分かれするよう追従させる場合は以下を利用します
1
|
|
また、rebaseではありませんが、既にtopicブランチ自体も複数人で共有している場合等、ブランチにあるコミットを変更したくない(できない)場合にはmergeすることでも追従可能なので、ケースバイケースで使い分けます
1
|
|
rebaseを行うと枝元の古いコミットから順に最新コミットへの追従が行われていきますが、途中のコミットにてコンフリクトが発生する場合があります。コンフリクトが発生したコミットはリベース中の状態(無名ブランチ)となってコンフリクトの解消を手動で行うようにrebaseが中断します。そのときの対応コマンドは以下になります:
1 2 3 |
|
ブランチの派生元を別ブランチに差し替えたい場合は–ontoオプションを利用します
1
|
|
過去のコミット編集を個別に行う場合は-iオプションを使います
1
|
|
コミットログと操作内容が書かれた文章がエディタで開かれる(最初はすべてpickが指定)ので、操作したいコミットを編集します。以下の操作がおこなえます
1 2 3 4 5 6 7 |
|
操作内容が決まったら編集を保存し、エディタを閉じるとrebaseが操作リストにしたがって行われます。
git resetを用いてもコミット内容は取り消せますが、痕跡も残らない強力なものなので、内容を取り消したという履歴を残すバージョン管理システムとして自然な取り消しを行いたい場合はrevertを用います
1 2 3 4 |
|
pull-requestの一部の修正のみ取り込みたい場合や他のブランチから一部必要な機能が含まれているコミットのみを取り込みたい場合にcherry-pickを用います
1 2 |
|
コミットリストの二分検索により確認を行っていき効率的にバグ混入箇所を特定します。
1 2 3 |
|
上記のコマンドを実行すると二分検索が始まり、中間のコミットがチェックアウトされる。後はビルド(テスト)を行って、
1 2 |
|
を繰り替えして最後に失敗したコミットがバグ混入箇所と特定できる。
1
|
|
他にもsubmoduleコマンド等色々有るが利用ケースが今のところないので割愛します。新しい有用なコマンド等が見つかった場合に続きを書きます。
]]>I18n(internationalization) Gem はRails2.2から提供されており、多言語をサポートしたアプリケーションを提供するためのフレームワークである。 「国際化(I18n:internationalization)」を行うとは、全ての文字を抽象化し、日付や通貨などロケール(地域や言語)によるものをアプリケーションの外に出すことである。 「地域化(L10n:localization)」を行うとは、それらアプリケーションの外に出したものに対して、翻訳やフォーマットを提供することである。
I18n化するために必要なこと
L10n化するために必要なこと
最も重要なAPIが以下の2つ
1 2 3 4 |
|
Railsのデフォルトではconfig/localesフォルダにある.rbと.ymlファイルを自動でロードする。
1 2 |
|
このサンプルの場合は、:enロケールだった場合は「hello」というキーを「hello world」という文字列にマップする。
デフォルトのappllcation.rbファイルに辞書の追加の仕方やデフォルトロケールの設定の仕方がコメントアウトで載っている。
1 2 3 |
|
load_pathは辞書ファイルを自動ロードするための設定でRuby配列のパスになっている。 default_localeがデフォルトのロケール設定になる。無指定のときは英語がデフォルトロケールになる。
複数のロケールを使う場合リクエスト中にロケール設定の仕方が必要になる。 ここで注意したいのは、sessionやcookieでロケールを保存して選択してはいけないことである。 ロケールはURLの一部に含めるべきで、URLを友人に送ったときは同じページで同じコンテンツで表示させるべきである。 RESTfulのアプローチでいけばこのルールから外れるべきではない。
簡単なロケールの設定の仕方は、ApplicationControllerのbefore_filterに以下のように書き、 URLのクエリとしてlocaleを渡す(例:http://localhost:3000?locale=de)方法である。
1 2 3 4 |
|
www.example.com なら英語、www.example.esならスペインのロケールというようにドメイン名でロケールを分ける。 トップレベルでロケールを設定すると以下のような利点がある。
ApplicationController以下のように記述すると実現できる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
サブドメインに設定する場合は
1 2 3 4 5 6 7 8 |
|
available_localesには定義済みのロケールリストが保存されている。
以下はロケールを切り替えるリンクの方法の例、APP_CONFIG[:deutsch_website_url]には「http://www.application.de」のような値が保存されている。
1
|
|
URLにロケールを含めるのは最も一般的な方法である。 先の例のparamsからロケールを設定する場合、全てのリクエストに link_to( books_url(:locale => I18n.locale))) のようなロケールを含めるのは大変であるので、 ApplicationController#default_url_optionsメソッドをオーバーライドする。
1 2 3 4 5 |
|
これはurl_forメソッドのデフォルト設定をオーバーライドしているので、url_forメソッドを使ったもの(root_path/routesファイルのリソースパス)全てに自動でクエリがつくようになる。
www.example.com/en/booksのようなURLでロケールを設定する場合は、routesファイルで以下のようにpath_prefix付ける。
1 2 3 4 |
|
ブラウザなどに含まれているHTTPヘッダーを使う
1 2 3 4 5 6 7 8 9 |
|
クライアントのIPアドレスから地域の情報をマッピングしてロケールを決める。 GeoIP Lite Countryデータベースを使うと、IPアドレスから国/地域/市などを返してくれる。
ユーザがアプリケーション内でロケールを設定できるようにして、データベースに保存する。
以上で、Ruby on RailsアプリケーションのI18nサポートの初期化が終わった。 次にL10n化を行う。 つまり、全てのロケール固有のパーツを抽象化することと、その翻訳を用意することである。
Railsの「t」ヘルパーをキーと一緒に使って以下のように書ける。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
キーに該当する辞書ファイルが見つからない場合は のようなタグがHTMLに入る。 辞書ファイルを追加する場合は、サーバの再起動が必要である。 辞書ファイルにはYAMLまたはRubyファイルが使われるが、Rails開発者の中ではYAMLが推奨されている。 しかし、YAMLはスペースや特殊文字に弱く、アプリケーションがロードに失敗することもある。 Rubyファイルは最初のリクエストでアプリケーションがクラッシュするので、間違いがわかりやすい。
以下のようにしてViewから辞書ファイルに変数を渡せる。
1 2 3 4 5 |
|
時間フォーマットをl10n化するときはRailsメソッドの「l」ヘルパーを使って、Timeオブジェクトを渡す。 ヘルパーには :format オプションも渡せる。無指定の場合は:defaultフォーマットが使用される。
1 2 3 4 5 6 7 |
|
辞書ファイルは以下で提供されているので、Gemで使うなり、config/localesにファイルを手動で置くなりして利用すると良い。 rails-i18n repository at Github(https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale)
Rails2.3からロケールによるテンプレート自動選択してくれるになった。 app/views/books/index.html.erbテンプレートを用意し、同階層にindex.es.html.erbファイルを置くと、 esロケールではesのerbファイルを参照し、デフォルトはindex.html.erbファイルが参照される。
1つのロケールに対して、1つの辞書ファイルだと、増えたときに管理するのが難しくなる。 よって、以下のように階層化するなどして管理するとよい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
これはモデルとビュー内のモデル属性とデフォルトで分けた例である。 このようにネストした場合は、辞書ファイルがデフォルト設定ではロードされなくなるので、以下のように 書かなければならない。
1 2 |
|
既存のクラスの挙動を変更したり、拡張するときの影響範囲を名前空間で限定する機能です。 これまでも既存のクラスやメソッドに対する、動的な挙動の変更や追加は可能でしたが、以下のような問題もありました。
モンキーパッチをモジュールとして分割してincludeするなどして、 明示的にするなどの対処法はとられてきましたが、 refinmentsは書き換えをより厳密で局所的なものにとどめるものになっています。
例としてStringクラスに局所的にメソッドを追加するコードを示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
HogeExtensionモジュールでは、Stringクラスに対するto_calmelcaseメソッドの追加をrefineキーワードで行なっています。 この実装は、HogeExtensionモジュールをusingキーワードでとりこんだRefineTestクラスでは適用されるので、利用できます。 しかし、それ以外の部分でStringクラスのインスタンスに対しては、利用できないことがわかります。
refinementsは厳密なレキシカルスコープ(内部で定義した変数は外から見えないが、その逆は可能というスコープ)で動きます。 つまり、usingしたスコープと違うスコープに対しては、適用されません。 また、外側よりは内部の、前のよりは後の方が優先度が高く適用されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
モジュールのメソッドにはrefinementsを適用できません。
1 2 3 4 5 |
|
これはちょっとややこしいので、例を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
26行目のintroduceに注目。 intstanceのintroduceが呼ぶのは元のAクラスのsay_hogeメソッドですので、’fuga’ではなく’hoge’の方が画面に出力されます。 これは、refinementsがレキシカルスコープで動くことの証拠です。 Aのintroduceメソッドは、それとは違うスコープで適用されたrefinementsの影響を受けません。 このような挙動をSelectorNamespcace と呼ぶそうです。
]]>シンボルの配列がリテラルで書けるようになった。
1
|
|
ちなみに文字列の配列のリテラルは以下のようにする。(これは以前からあった)
1
|
|
prependは呼び出し元のクラス/モジュールの前にモジュールを置きます。 その呼ばれたモジュールの中で同じ名前を持つメソッドがあれば、それをラップします。 局所的なモンキーパッチを当てるような感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
キーワード引数はメソッドのそれぞれの引数にその意味を示すキーワードを付与し、キーワードを通じて引数を渡せる機能です。
1 2 3 4 5 6 7 8 9 |
|
実行時キーワード省略でデフォルト値が利用され、キーワード指定すると指定したものだけ値が書き換えられる。 引数全てを渡さなくてもよいというのも嬉しい。 定義されていないキーワードを指定すると当然ながらエラーとなる。
]]>基本はRuby on Rails Guides: Asset Pipelineの訳ですが簡略化や自分の解釈で意訳した部分が多々あります。気になる点あったらコメントください。
Asset(アセット)とは、訳すと「資産」のこと。Assets Pipelineは画像やJavaScript、CSSを高速でリクエストを捌けるようにしたRails 3.1より標準搭載された仕組みです。
Assets Pipelineはデフォルトで有効です。無効にしたければconfig/application.rbにて
1
|
|
を設定してください。また、アプリケーション作成時であれば
1
|
|
と–skip-sporocketsオプションを付ける事でも無効にできます。ただし、何らかの理由が無ければ、デフォルトの状態で有効にしておくと高速化の面でも有利ですのでそのままにしておくべきでしょう。
app/assetsディレクトリの中にAssetを配置します。今まではpublicに全て配置していて、利用は可能ですが、全て静的ファイルとしてのみ扱われます。
production環境のデフォルトでは事前にプリコンパイルを行い、public/assetsに配置して動作時にapp/assetsから直接出力せずパフォーマンスに配慮したデプロイを行います。
Assetの配置場所は
の三箇所があります。appはアプリケーション固有のもの、libは複数のアプリケーションでも利用できるもの、vendorはサードベンダーのJSプラグインやCSSフレームワークといったように使い分けると良いでしょう。
マニフェストやヘルパーよりファイルを参照すると、デフォルトではimages、javascripts、stylesheetsのサブディレクトリ内からファイルを探します。例えば、
1 2 3 |
|
をJSマニフェストから参照するとすると
1 2 3 |
|
ヘルパからだと
1 2 3 |
|
にて参照できます。
indexファイルはフォルダ名指定でlib/assets/library_name/index.jsを
1
|
|
と参照可能です。ちなみにRails.application.config.assets.pathsを見るとAsset検索Pathが分かります。また、以下のようにconfig/application.rbにパスを追加できます
1
|
|
重要なことは、検索したいファイルはプリコンパイル対象となっていることです。そうしないとproduction環境では利用できなくなってしまいます。
Fingerprintingとはファイル内容も加味されたファイルネーミングの仕組みです。ファイルの中身が変更されるとファイル名も更新されます。
これにより、CDNであったり、複数の別のサーバー上に配置したとしても、ファイル名によってコンテンツ内容が一意である事が分かり、キャッシュ最適化を行う事が可能になります。
Assets Pipelineではファイル名にMD5ハッシュが挿入されます。global.cssが元ファイルとすると、global-908e25f4bf641868d8683022a5b62f54.cssのようなファイル名となります。
Assets Pipeline導入前のRailsは時間ベースの文字列クエリを付加していましたが、以下のデメリットがありました:
これらのデメリットをファイル内容に基づくファイル名の付加によって解消されました。
Fingerprintingはproduction環境で有効、その他の環境は無効にデフォルトはなっています。替えたい場合はconfig.assets.digest設定を変更して下さい。
Assets Pipelineでは通常のリンクヘルパを利用すればOKです
1 2 3 |
|
accetsパスへの検索、production環境であればMD5をファイル名に付加更新もここで行われます
1
|
|
Assets PipelineはERBにて評価可能です。application.css.erbのようにerbの拡張子を付加すれば次のように利用できます。
1
|
|
Base64形式として埋め込みヘルパもあります
1
|
|
application.js.cooffee.erbのようにCoffeeScriptにも利用できます
1
|
|
どのアセットを利用するかを決定するのにマニフェストファイルを利用します。CSS/JavaScriptにコメントにてディレクティブを記述します。また、Rails.application.config.assets.compressがtrueであれば連結します。連結することに単一ファイルになるのでリクエスト時間を減らせます。例えばapp/assets/javascripts/application.jsに以下のように記述します
1 2 3 4 |
|
//=で行を始めてディレクティブを記載します。jquery.jsとjquery_ujs.jsはjquery-rails gemが提供しています。
require_treeは再帰検索を行います。対象パスのサブディレクトリも検索してすべてのファイルを出力します。サブディレクトリを検索しないで特定のディレクトリを指定したい場合はrequire_directoryを利用して下さい。
requireは上から順に処理されますが、require_treeは何処に記載しても順序は関係無いです。連結した場合でも、特定のJavascriptが一番最初に来るように保証したいのであれば、requireも一番最初に記述してください
CSSの例は以下のようになります
1 2 3 4 |
|
requre_selfはこれが呼び出された順序で自分のCSSを読み込むようになります。require_treeを使うとJSと同様に現在のディレクトリのすべてのスタイルシートを読み込みます。
複数のSassファイルを利用する時はSassの@importルールを使用スべきです。ディレクティブで記載してしまうと全Sassファイルはそれぞれのスコープ下に存在することになって変数やmixinが定義されたドキュメント内でしか利用できなくなります。
Assetの拡張子で前処理が決まります。projects.js.coffeeとすればCoffeeScriptが、projects.css.scssとすればSCSSが処理されます。
複数の拡張子を付加すれば前処理の多重化も可能です。projects.css.scss.erbとすれば、拡張子は右側からERB、SCSSと処理され、最終的にCSSとして応答します。
この拡張子の処理順序は重要で、projects.js.erb.coffeeと記載してしまうと、ERB記述のままCoffeeScriptインタプリタが処理されてしまいエラーとなってしまいます。projects.js.coffee.erbの順で記載してください。
JavaScriptは:closure :uglifier :yuiの3種類が選べます。closure-compiler・uglifier・yui-compressorの各gemが必要です。Gemfileにはデフォルトでuglifierがあります。ホワイトスペースを削除し、if-else文を三項演算子に変更するなどの最適化をします。
1
|
|
JS圧縮を有効にするには以下の設定が必要です
1
|
|
development環境では連結されずに別々のファイルとなります
1 2 3 |
|
の記載では
1 2 3 |
|
となります。但し、
1
|
|
と、デバッグモードをオフにすれば連結状態になります。
サーバに初回リクエストにてアセットはコンパイル・キャッシュされ、304を返すようになります。マニフェスト記載のどれかが変更があると新しくコンパイルしてファイルを応答します。
デバッグモードは以下でも有効に出来ます。
1 2 |
|
パフォーマンス的にはデバッグモードは不利なので切り替えが提供されています
production環境ではFingerprintを利用します。プリコンパイル時にファイル内容に応じてMD5値が生成されてファイル名が更新されてディスクに格納されます。挿入された名前はマニフェスト、ヘルパーで補完されます。
1 2 |
|
にて
1 2 |
|
となります。
config.assets.digest設定にてFingerprintのON/OFFを切り替えられます。production環境で有効、その他は無効になっています。通常はこのデフォルト設定は変更すべきではありません。キャッシュ制御がクライアント側で困難になるからです。
development環境のデフォルトでは動的にAssetファイルがコンパイルされますが、production環境のデフォルトでは高速化を図るため、事前にコンパイルして静的ファイルとして配置するようになっています。これをプリコンパイルといいます。Railsではrakeタスクとして配布されています。
コンパイルされたAssetはconfig.assets.prefixに設定されたディレクトリに格納されます。デフォルトはpublic/assetsディレクトリです。
デプロイサーバー上でのプリコンパイルも可能ですが、ファイル書き込み権限が無い等、rakeタスクを直接実行出来ない時はローカルでrakeタスクを実行してください。実行するrakeタスクは、以下のようになります。
1
|
|
プリコンパイルの実行速度を早めるためにconfig.assets.initialize_on_precompile設定をfalseに設定してRailsアプリケーションのロードをプリコンパイル時には部分的に行うようにすることが可能となります。Herokuではこの設定は必須となっています。
config.assets.initialize_on_precompile設定をfalseにした際は、ローカルでプリコンパイルが正しく実行出来るか確認してからでプロイして下さい。アプリケーションのオブジェクトやメソッドを参照していたりするとエラーが発生する場合があるので注意する必要があります。
Capistano(v2.8.0以降)にはプリコンパイル実行を制御するレシピが用意されています。以下の行をCapfileに追加してください。
1
|
|
これによって、config.assets.prefixはshared/assetsディレクトリに設定されます。既にこのフォルダを利用していた場合は独自にrakeタスクを作成して下さい。
また、重要な点として、古いプリコンパイルされたAssetsファイルがページキャッシュ有効な間は正しく参照可能となるようにこのsharedフォルダはデプロイサーバー間で共有されている必要があります。
Assetsファイルをローカルでプリコンパイルする時は、デプロイ環境ではAsset関連のgemが必要なくなるので、以下のコマンドでassetsグループのgemを除外すると良いでしょう。
1
|
|
プリコンパイルを行うファイルとして、application.js、application.cssとJS/CSSファイルではない全てのファイルが含まれます。もし、他にも独自のJS/CSSファイルを読み込みたい場合は以下のように追加設定する必要があります。
1
|
|
この設定により、rakeタスクによるmanifest.ymlにはassetsファイルとそのFingerprintsの対応付けが行われ、ヘルパを呼び出すたびにSprocketsによるFingerprintへのマッピングリクエストを回避する事が出来ます。マニフェストファイルの例は以下のような感じです。
1 2 3 4 5 6 |
|
マニフェストファイルの配置場所はconfig.assets.prefixのルートディレクトリに配置されます。変更したい場合は以下にて設定出来ます。
1
|
|
Production環境でプリコンパイルされたファイルが見つからなければ、存在しないファイル名と共にSprockets::Helpers::RailsHelper::AssetPaths::AssetNotPrecompiledError の例外がRaiseされます。
プリコンパイルされたAssetファイルはファイルシステム上に静的ファイルとして配置され、Webサーバーより直接提供出来ます。Fingerprintingのメリットを十分に生かすため、以下のようにサーバー設定を行う事が推奨されます。
Apache:
1 2 3 4 5 6 7 |
|
nginx:
1 2 3 4 5 6 7 |
|
プリコンパイル時、gzip圧縮(.gz)ファイルも同時に作成されます。WebサーバーではしばしばGzip圧縮転送の設定を行って転送量の軽減を図りますが、動的な圧縮だと、CPUの使用も懸念して圧縮率に妥協をすることがあります。この問題を解決するために事前に最小サイズとなるようにgzip圧縮ファイルを高圧縮率で作成した物を直接ディスクより提供する事でサーバー負荷を低減させるように設定する事もできます。
Nginxではgzip_staticを有効にする事により可能になります。設定は以下の通り。
1 2 3 4 5 6 |
|
このディレクティブは大凡のコンパイル済みWebサーバーで利用出来ますが、出来ない場合はモジュールを追加してコンパイルする必要がある場合があります
1
|
|
Phusion Passengerと一緒にnginxをコンパイルする場合はこのオプションを指定する必要があります。
Apacheでも可能ですがやや困難です。トライしたいならググってください。
動的コンパイルをやりたい環境がある場合はSprocketsに全てのリクエストを投げる事も出来ます。以下のように設定します
1
|
|
Assetの初回アクセス時にコンパイルされdevelopment環境よりも上位環境ではキャッシュされてMD5ハッシュ化されたファイル名が使用されます。
SprocketsはCache-Controlヘッダにmax-age=31536000を設定してきます。これはサーバー、クライアント間でリクエストされたデータは1年間キャッシュしても良いという取り決めになります。この事によりブラウザ等でのローカルキャッシュや中間キャッシュを行うことができるようになり、サーバーへのリクエスト削減が期待出来ます。
しかしながら、動的コンパイルは多くのメモリやサーバ負荷となり得るのでお勧め出来ません。
もし、JavaScriptランタイムが導入されていないproduction環境のサーバーデプロイしたい場合は以下をGemfileに追加してください
1 2 3 |
|
現在CSS圧縮エンジンとしてYUIがあります。YUIはCSSの最小化を行います。
1
|
|
config.assets.compressはtrueにしておく必要があります。
JS圧縮は:closure、:uglifierand、:yuiの3種類から選択出来ます。それぞれ、closure-compiler、uglifier、yui-compressorのgemが必要になります。
デフォルトでGemfileにはuglifierが指定されています。これはNodeJSで書かれたUglifierJSのRubyラッパーです。スペース削減やif文を3項演算子に変換する等JSの論理変換を行ってサイズ最小化が行われます。以下のように指定してください
1
|
|
JS圧縮指定時もconfig.assets.compressは有効である必要があります。
uglifierにはJSランタイムであるExecJSが必要になります。MacOSXやWindowsにはインストールされています。サポートされているOSに関してはExecJSのドキュメントをチェックして下さい。
自分で圧縮ロジックを定義する事もできます。compressメソッドで変換結果をリターンして下さい。
1 2 3 4 5 |
|
利用するにはオブジェクトを指定します
1
|
|
Asset公開パスのデフォルトは /assets です。3.1にアップデートする際に既にこのURIが利用されていた等の際には以下にてパスを変更する事も出来ます
1
|
|
X-SendfileヘッダはWebサーバー自身がアプリケーションからのレスポンスをカスタマイズしてファイルをディスク上から直接読み込んで代わりにデータの受け渡しをします。デフォルトはオフですが、サポートされているなら有効にすることによりファイル提供の転送速度向上が期待できます。
Apache、nginxでサポートされており、以下をconfig/environments/production.rbに設定します
1 2 |
|
既に存在しているアプリケーションのアップグレード時等に、production環境以外のX-Sendfileに対応していない環境化にこの設定をコピペしないように注意してください。
Sprocketsはdeveloment、production環境でRailsのデフォルトキャッシュストアを利用します。
デフォルトstore以外を指定出来る事が今後の課題です。
AssetsはGemsの形式でも外部ソースを取り込めます。
jquery-rails gem等が良い例です。一般的なJSライブラリを取り込めます。このgemにはRails::Engineが継承されたクラスを含んでいて、中に含まれているapp/assetsやlib/assets、vendor/assets等のディレクトをSprocketsの検索パスとして追加されます。
以上。あと、3.1以前からのアップデートの方法等載っていました。興味のある人は原文を参照してみてください。
]]>まず、ファイルをロードする require/load/autoload と ロードしない include/extend に分けられる。 違いについては、次で個別に説明した後に表にしてまとめる。
1
|
|
1
|
|
1
|
|
1
|
|
1
|
|
extendは使用したことがなかったので、具体例を以下に示す。
1 2 3 4 5 6 7 8 9 |
|
require | load | autoload | |
---|---|---|---|
メソッドの定義元 | Kernelモジュール | Kernelモジュール | Kernelモジュール or Moduleクラス |
複数回ロード | されない | される | されない(requireに従うので以下省略) |
ロード時の拡張子省略 | 可 | 不可 | |
ロード可能ライブラリ | Rubyスクリプト+拡張ライブラリ | Rubyスクリプト |
requireはライブラリのロードをしたいとき、loadは設定ファイルなど再読み込み可能にしたいとき、というように使い分けられる。 また、拡張子が.rbや.soなどではない.txt(中身はruby)ファイルをロードしたいときにも load を使用する。
include | extend | |
---|---|---|
メソッドの定義元 | Moduleクラス | Objectクラス |
振る舞い | includeしたクラスのインスタンスメソッドとして使用 | extendしたクラスのクラスメソッドとして使用 |
振る舞いの違いがわかりにくいので、以下に例を示す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Rails3 でのアプリケーション作り始めにて、
1
|
|
などと打つと、色々なファイルが生成され、その中にはroutes.rbも含まれている。routes.rbの覗いてみると、
1
|
|
という記載がある。 これはリソースCRUD操作を行うためのURLとアクションを自動で設定してくれる。 RailsでCRUDを行うために用意されている7つのアクション(index, new, create, show, edit, update, destroy)とURLとの紐付けをresourcesを使うことによって一度にすることができる。 なお、routes.rbにresources, resourceなどと書いていくわけだが、ルーティングの優先順位は上から順となっている。
現在設定されているルーティングを確認するには、rake routesコマンド用いる。
1 2 3 4 5 6 7 8 |
|
基本で記載したresourcesを用いた場合は、
1
|
|
のように、URLにidが付加されている。 しかし、ユーザのプロフィール設定画面などidが不要な場合もあるので、そのような場合はresourcesではなく、resourceを用いる。
1
|
|
7つのCRUDアクションの内、indexは生成されなくなる。
1 2 3 4 5 6 7 |
|
デフォルトのアクション7つのうち、不要なURLを生成したくない場合、:only 又は :except オプションを使用する。
:onlyオプションを用いると、指定したアクションのみ生成される。
1
|
|
:exceptオプションを用いると、指定したアクションは生成されない。
1
|
|
ルーティングの追加方法はリソースのidがURLに付くかどうかで、2つの方法がある。リソースidが付く方(/articles/1/preview みたいなの)をメンバールーティング、付かない方(/articles/preview みたいなの)をコレクションルーティングと呼ぶ。
メンバールーティングの追加
1 2 3 4 5 6 7 8 9 |
|
コレクションルーティングの追加
1 2 3 4 5 6 7 8 9 |
|
ログアウトのリンクなど、どのユーザでも変らないURLをピンポイントで指定するには次のようにmatchを用いる。
1
|
|
1 2 3 |
|
Named helperとはprofile_pathなどと書いているもののこと。 これを設定するには、:as オプションを使って、ルーティングのための名前を指定する。
1
|
|
これでlogout_pathやlogout_urlが使えるようになる。
リソースが1対他の関係にある場合、URLをネストさせることができる。 例えば、1つの記事(article)にいくつかのコメント(comment)がある場合には次のように書くことができる。
1 2 3 |
|
便利だが、ネストしすぎると混乱を招きそうなので、1回くらいにしておくとよい。 2回、3回とネストしなければならない場合、設計を見直す機会かもしれない。
1 2 3 |
|
デフォルトで用意されているpublic/index.htmlを消去してから、次のように記載する。
1
|
|
Non-Resourceful Routesとは、任意のURLをアクションにルーティングするためのサポート。
1
|
|
というように書く。これで、GET articles/edit/1 すると、パラメータは次のようになる。
1
|
|
URLに特定の文字列を含む場合は、
1
|
|
として、GET /articles/show/1/with_user/2すると
1
|
|
となる。
参考サイト:ruby/rails/RailsGuidesをゆっくり和訳してみたよ/Rails Routing from the Outside In - 株式会社ウサギィwiki
]]>まずはrvmを最新にし、ruby 2.0をインストールします。
1 2 3 |
|
で、実験です。1から30までの整数で3が含まれるもの(3, 13, 23, 30)の最初の3つを求めるには
1 2 |
|
このコードでは、
map で各整数を文字列化
selectで文字列に3が出現するものを正規表現で選択する。=> [“3”, “13”, “23”, “30”]
takeで先頭の三つを取り出す。=> [“3”, “13”, “23”]
で、指定した範囲の最後まで読み込んでから次の処理を行う。
これに対し、lazyを用いたコードは以下。
1 2 |
|
先頭の3つを読み込んだところで終了しています。 これは、結果をArrayではなくEnumerable型として返すようにmapメソッドやselectメソッドを再定義し、実際に要素の値が必要になったとき、つまり、mapの処理はselectが呼ばれたときに開始、 selectの処理はtakeに呼ばれたときに開始…というように必要なときになったら呼び出すようになっています。
]]>Web Storageは、HTML5の周辺APIのひとつで、ブラウザにデータを保存するための仕組みです。データの保存・上書き・削除・全クリアなどの操作は、Javascriptで行います。 Web StorageはCookieとよく似ていますが、Cookieに比べてはるかに大きな容量のデータをブラウザに保存できます。 Web Storageには、sessionStorageとlocalStorageの2種類のストレージが用意されています。どちらもキーと値をペアにしたデータリストをブラウザに保存するkey-value型のデータ保存形式である点は同じですが、データの有効期限などが異なります。 対応している主要なブラウザはIE8以降、Firefox3.5以降、Safari4.0以降です。詳しくはCan I use… Support tables for HTML5, CSS3, etcをご覧ください。
機能 | Cookie | sessionStorage | localStorage |
---|---|---|---|
保存容量 | 4KB | 1オリジン当たり5MB(推奨) | 1オリジン当たり5MB(推奨) |
データの有効期限 | 指定期限まで有効 | ウィンドウやタブを閉じるまで有効 | 永続的に有効 |
サーバーへのデータ送信 | 毎回自動送信 | 必要時のみ送信 | 必要時のみ送信 |
別ウィンドウでのデータ共有 | 可 | 不可 | 可 |
オリジン: プロトコル://ドメイン名:ポート番号 のこと
IE6, 7でWeb Storageを利用することはできないが、jStorageというjQueryプラグインを利用することで、ローカルストレージを実現できる。 ただし、保存容量が128KBになるなどWeb Storageに劣るところはある。
Web Storageで提供されているメソッドは、データの保存・取得・指定キーの値削除・全値クリアの4つです。メソッドはsessionStorageとlocalStorageで共通です。
1 2 3 4 5 6 7 8 9 10 11 |
|
データの上書きをする場合はもう一度keyとvalueを保存します。メソッドの使い方は以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
より詳細な情報は無職のプログラミング Web Storageについて調べるに記載されています。
]]>ローカルリポジトリを作成するにはリポジトリ名を指定する。
1 2 |
|
リポジトリ単位の設定は.git/config、ログインユーザ単位の設定は~/.gitconfigに、システム単位は/etc/gitconfigに格納されている。それぞれ、
1 2 3 |
|
にて値を設定出来る。各値はシステム→ログインユーザー→リポジトリ単位の順で読み込まれ、後から読み込んだほうが優先される。現在の設定は
1
|
|
で参照可能。良く設定するキーは
1 2 3 |
|
gitの場合、ファイルを追加・更新しただけではまだコミット候補ではなく、インデックスに登録する必要がある。
1 2 |
|
ワーキングツリー・インデックスの状態を確認する。リポジトリとの現在のファイルの変更・修正状況、コミット候補としてインデックスに登録されているか確認出来る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
リポジトリとの差分が確認出来る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
1 2 3 4 |
|
コミット済みのファイルを移動・リネームする。コマンド実行するとコミット候補としてインデックスに登録される
1 2 |
|
コミット済み、またはインデックスに登録済みのファイルを削除する
1
|
|
git rmをオプション無しで実行するとワーキングツリーからファイルが削除されるので、新規追加登録したファイルをインデックスから解除してファイルをワーキングツリーに残しておきたい場合は–cachedを使う
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 |
|
–amendオプションを指定すると直前のコミットを追加修正したインデックス登録の差分を含めて差し替えることが出来る
1
|
|
インデックス登録してある差分を含めて直前のコミットを変更する
1 2 |
|
1 2 3 |
|
インデックスやワーキングツリーに対して検索する
1
|
|
1
|
|
1 2 3 |
|
1 2 3 4 5 6 7 |
|
1 2 |
|
1 2 3 4 |
|
1
|
|
ローカルリポジトリにコミットしていない変更がある場合、競合することがあるので、コミットしておくか、git stash saveして一旦ソースを待避してからpullすると良い。
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 |
|
1 2 3 4 5 |
|
以上よく使う21コマンドを紹介した。次回はgit rebaseの使い方とgit cherry-pickなど頻繁には使わないが有用そうなコマンドを紹介する。
]]>1 2 3 4 5 |
|
1 2 3 4 |
|
次にenv.rbにJavascriptドライバーを記述します。
1 2 |
|
これでJacascripがテストで動作する環境ができました。Javascriptを動作させたいところにRSpecだと
1 2 3 |
|
Cucumerだとシナリオに@javascriptタグを付加します。
1 2 |
|
ブラウザ別のテストを実施したいときはSeleniumドライバーを使います。 SeleniumドライバーはFirefox、InternetExplorer、GoogleChromeを実際に起動させてテストします。 SeleniumはCapybaraに同梱されているので、ブラウザエンジンを切り替えるだけで使用可能になります。
1
|
|
デフォルトではFirefoxが起動するので、FirefoxではなくChromeを使用したいときには以下をCapybara.default_driverの前に記載します。
1 2 3 |
|
Seleniumドライバーは実際のブラウザを起動するのでほとんどのJavascriptをテストできますが、オーバーヘッドが大きくなります。 従って、必要なテストにのみSeleniumドライバーを利用するようにします。 RSpecのフィルタで切り替える方法を載せます。この方法は特定のサンプルのみブラウザの切り替えを行います。 フィルタ機能を設定するには、spec_helper.rbにSelenium用のフィルターを用意します。
1 2 3 4 5 6 7 8 9 |
|
あとはSeleniumを実行したいサンプルにseleniumタグを追加します。
1 2 3 |
|
ActionScript は Adobe Flash Player や Adobe AIR のランタイム環境用の開発言語です。 開発環境には Adobe Flash CS6(オーサリングツール)/Adobe Flex Builder(統合開発環境)/Adobe Flex(コマンドラインのコンパイラ)がありますが、 有償であったりコマンドラインでコンパイルしなければならないので、 ここでは無償の統合開発環境である FlashDevelop を使用しています。 ActionScriptで書かれたコードを上記環境でコンパイルすることにより、SWF(Shockwave Flash file)ファイルが生成されます。 このSWFファイルをウェブページなどに組み込めば、ランタイム環境で動作させることができます。
ActionScript には ActionScript 1.0/2.0/3.0 の各バージョンがあり、2.0からオブジェクト指向言語になっています。 ECMAScriptをベースに作られているため、Javascriptに似ており。また、オブジェクト指向言語になり、Javaにも似ている言語となっています。
基本的なことと気になったことについて書いていきます。
var 変数名:型 で宣言します。
1 2 3 4 5 |
|
などがあります。
文字列はシングルクォートかダブルクォートを使って定義します。\n(改行)などの特殊文字を入れることもできます。
1
|
|
文字列を操作するメソッドも用意されており、Rubyみたいに使えます。
1 2 3 4 5 6 7 |
|
上記コードだけでは実行できないので、以下のようにコードを.asファイルに記載して実行(FlashDevelopではF5)します。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
配列用の型があるので、Arrayで宣言します。
1 2 |
|
配列も文字列と同じようにメソッドが用意されており、操作できます。
1 2 3 4 5 6 7 |
|
Object型を使って、ハッシュを作ります。Object型はすべてのクラス定義の基本クラスです。
1 2 3 4 |
|
変数は関数単位で管理しており、ブロック変数として宣言したつもりでも関数スコープになっています。(withを使えば、実現できるらしいです。)
1 2 3 4 5 6 7 |
|
Javaのように例外をキャッチできます。
1 2 3 4 5 |
|
以下のようにクラス定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
ActionScript 3.0 で構築されたアプリケーションには、表示リストと呼ばれるオブジェクトの階層があります。
1 2 3 4 5 |
|
表示オブジェクトの基本コンテナ、各アプリケーションには1つのStageオブジェクトがあり、この中に画面の表示オブジェクトがすべて含まれます。 ステージは、表示リスト階層の最上位にあたります。 それぞれのSWFファイルには関連するActionScriptクラスがあり、これがSWFファイルのメインクラスと呼ばれます。 SWFファイルのメインクラスは、Spriteクラスを拡張して定義します。 SWFファイルが Flash Player または Adobe AIR 上で開かれると、SWFファイルのメインクラスのコンストラクタ関数が呼ばれ、 作成されるインスタンスがStageオブジェクトに子として追加されます。
ActionScript 3.0 では、アプリケーション内で表示される全てのエレメントタイプは、表示オブジェクトです。
表示オブジェクトコンテナは特殊な型の表示オブジェクトです。 表示オブジェクトコンテナ(単にコンテナともいいます)は、それ自体が表示オブジェクトコンテナ/表示オブジェクトを子オブジェクトに含むことができます。 表示オブジェクトコンテナに子オブジェクトを追加するには addChild関数を使います。 表示オブジェクトコンテナとなりうる表示オブジェクトは Stage/MovieClip/Spriteクラスです。
Flash上に「Hello ActionScript」と文字列を表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
ソフトウェアを多言語対応するときの工程として
の各ステップがある。 名前の由来は最初と最後の文字と間の文字数からきている。i18nだとInternationalizationの最初のiと最後のn、その間に18文字あることからきている。
「i18n」とは、ソフトウェアに技術的な変更を加えることなく、多言語、多地域に対応させる枠組みを作っておくことである。 i18nに対応すると次に各言語においての対応を実装していく必要がある。それが「l10n」で、特定の1言語で必要とされる言語特有の機能等を実装し、対応させることである。 多言語に渡ってl10nの対応をし、利用者の言語に合わせて切り替えて表示できる状態が「m17n」対応となり、多言語対応となる。
Railsにはi18nの機能が標準でついており、利用することで多言語対応ができる。 詳しくは次回以降で記載する。
確認した環境はRuby 1.9.3p194, Rails 3.2.8。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
true/falseだからといって特に何も起こらなかった。falseでもそのまま次のbefore_filterが実行されたり、filter後に控えているコントローラのメソッドが実行された。
before_filterやafter_filterはメソッドを優先して実行するかどうかを決めているだけであり、メソッドの返り値を受け取ってどうこうするというモノではないようだ。
ただし、before_filterで呼んだメソッドの中にrenderやredirect_to、raiseなどがあると、その後に控えている他のbefore_filterや以降のコントローラのメソッドは実行されない。
なお、rails:3168によると、rails 1.xではfilterにfalseが返ると、そこで処理が止まっていたようです。
]]>Flashが使えなくなったことでHTML5で対応する必要がでてくる(ていうかHTML5で対応出来ないと詰む)ことが多くなる。なので、各ブラウザアプリUser AgentとCSS 3D Transformsの挙動を実際に試してみる。
ブラウザ | User Agent |
---|---|
Chrome | Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03S) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19 |
Dolphin | Mozilla/5.0 (Linux; U; Android 4.1.1; ja-jp; Nexus 7 Build/JRO03S) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30 |
Firefox | Mozilla/5.0 (Android; Tablet; rv:15.0) Gecko/15.0 Firefox/15.0.1 |
Sleipnir | Mozilla/5.0 (Linux; U; Android 4.1.1; ja-jp; Nexus 7 Build/JRO03S) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30 |
OperaMobile | Opera/9.80 (Android 4.1.1; Linux; Opera Tablet/ADR-1207201819; U; ja) Presto/2.10.254 Version/12.00 |
ICSの標準ブラウザでのUser Agentは後半が「AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30」になっているのでDolphinとSleipnirはJelly Beanになっても以前の標準ブラウザと同一エンジンで同じ挙動を示しそうな感じだ。
Firefoxはバージョン番号が含まれてないのでJelly Beanかどうか判断出来ないという結果に。Flash未サポートかどうかUser Agentで簡単に振り分けられなくなっちゃうので、出来ればバージョン番号も付加して改善して欲しいところ。
次にCSS 3D Transformsの挙動を見てCSS3の対応状況を見てみる。
挙動の確認は6枚の画像をサイコロ風に並べたCube型に配置してFPSの様な視点を作ってグリグリ回して確かめた。結果は以下の通り
ブラウザ | 対応状況 | 挙動 |
---|---|---|
Chrome | △ | CSSは認識しているがグリグリ動かすと画像落ちする |
Dolphin | ◎ | FPSの視点でグリグリOK |
Firefox | △ | 描写は出来て、画像落ちはしないが、使い物にならないくらい激重 |
Sleipnir | ◎ | Dolphinと同じでOK |
OperaMobile | × | CSS/3D is not supported. と出る。3D表示出来ない |
ちなみにPCではFirefoxとChromeはWin/Mac共PCにGPU搭載されていればHWアクセラレーションがきちんと動作して問題なく動作する。
△は(アニメーションしないならもしかしたら使える時もあるかもしれないが)実用不可なのでDolphinとSleipnirくらいしかまともに動かない。ICS標準ブラウザでは動作していたのにJelly BeanでChrome for Androidに変わったことでCSS 3D Transformsに関しては退化してしまったことになる。早急の改善をChrome for Androidにお願いしたい。
]]>step_definitionsフォルダに便利な cucumber_steps を生成してくれるツールがgemの中にパッケージ化されている。 Gemfileのdevelopment環境にcucumber系を含めている必要がある。
1 2 |
|
WidgetモデルのFabricatorが定義されていれば、下記のように書くだけでFabricateできる。
1
|
|
Widgetモデルの属性を指定してFabricateすることもできる。
1 2 3 4 |
|
複数も可
1
|
|
属性付きで複数Fabricateする。
1 2 3 4 5 |
|
既にFabricateされた”widget”に”wockets”を所属させる。
1
|
|
既にFabricateされた”widget”に”wockets”を属性を与えて所属させる。
1 2 3 |
|
既にFabricateされた”widget”と”wockets”を関連付ける。
1
|
|
データベースにいくつのオブジェクトが保持されているか検証する。
1
|
|
オブジェクトの中身も検証できる。
1 2 3 4 |
|
cucumberのステップでテーブルを変換できる。縦横のテーブルでカラムの値を再配置できる。 spec/fabricatorsフォルダにおいておけば、何とでも設定しておける。
例として、全てのフィールドの”company”に変換の定義をする。lambda には返り値の属性をセットしたい文字列を置く。 その結果、”company”のインスタンスオブジェクトが生成される。
1
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
divisions を生成したときに、lambdaによって”company”オブジェクトに渡されている。
特定のモデルのスコープにだけ適用したい場合は、only_forを使う。
1
|
|
これはオブジェクト生成ライブラリで、 オブジェクトの概略だけを定義し、素早くオブジェクトを使うことができるものである。 サポートしているオブジェクトタイプは以下のものなどがある。
Gemfile に Fabrication を記載し、bundle install すれば使える
1
|
|
デフォルトでは以下にFabrication関連のソースを置くと、自動ロードされる。
1 2 |
|
設定を変更したい場合は以下のように、Fabrication.configureで設定変更できる。
1 2 3 4 |
|
1 2 |
|
1
|
|
Fabricator ブロックには変数が必要ではないが、1つ提供される。属性リスト作成時に、宣言もされる。
1 2 3 4 |
|
属性には変数を渡すことができる
1 2 3 4 |
|
属性は処理順に宣言され、上記フィールドのブロック変数を用いることができる。
1 2 3 4 |
|
予約語名をブロック変数と一緒に使うことで属性として参照できる
1 2 3 |
|
他のFabricatorに関連付ける場合は、属性名を書くだけでいい。 これで、「belongs_to」の関連を表現できる。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
countパラメータを使うことで、配列オブジェクトを生成できる。
1 2 3 4 |
|
他の Fabricators から属性を継承する場合は、「:from」 を使う
1 2 3 4 5 6 7 |
|
オブジェクトの初期化を通常の方法でしてほしくないときは、 initialize_withを以下のようにオーバーライドすればよい。
1 2 3 4 |
|
Fabricationのビルドにフックするには、after_build、after_create を使う。
1 2 3 4 |
|
オブジェクトに引数を与えたときのコンストラクタでコールバックするときは、on_initを使う。
1 2 3 |
|
コールバックはスタックになっているので、並列にFabricatorを宣言できるし、継承しても大丈夫。
Fabricatior呼び出し時に:aliasesオプションをつけるとエイリアスが付けれる。
1
|
|
Fabricator内で一時属性を変数として持てるが、クラス生成時にはセットされない。 一時属性は、クラスが生成されるまでの間は普通の属性と同じように扱えるが、生成時に取り除かれる。
1 2 3 4 5 6 7 8 9 10 |
|
Fabricationがロードされた状態にリセットする
1
|
|
Fabricateオブジェクトを作成する簡単な方法は、クラス名を渡すだけでいい。
1
|
|
これで、PersonのインスタンスがFabricatorとして定義される。 Fabricator作成時に、引数としてハッシュを渡せば、属性の追加や、上書きができる。
1
|
|
Fabricateのブロックの引数にハッシュ値を渡せば、オブジェクト生成時に定義され利用できる。
1 2 3 4 |
|
データベースにオブジェクトを持続させたくないときは Fabricate.build を使う。
1
|
|
下記のように、Fabricate.build内でFabricateが呼ばれていてもオブジェクトは持続せず、buildのときの動作と同じになる。
1 2 3 |
|
オブジェクトを生成せずに、属性だけを生成してハッシュで返したい場合は以下のようにする。
1
|
|
Sequencesはそのプロセスにおいての、ユニークな連続した数値が得られる。 Sequencesは指定がなければ、0からはじまる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Rails 3でFabricatorsをモデル生成時に一緒に生成したい場合は、config/application.rb に設定を書く。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
上記設定後、下記コマンドでFabricationのファイルができる。
1 2 3 4 |
|