interlude

プログラミングや私的なこと

ActiveRecordをちまちまと読みます その2

引き続き読み進めていきます。

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb

上記リンクの38行目から読みます。ActiveRecordのパラメータの受け取り方についての説明が書いてます。

翻訳文

アクティブレコードは、コンストラクタパラメータをハッシュまたはブロックとして受け入れます。 ハッシュ方式は、HTTPリクエストなどの他の場所からデータを受け取っているときに特に便利です。 これは次のように動作します:

原文

 Active Records accept constructor parameters either in a hash or as a block. The hash method is especially useful when you're receiving the data from somewhere else, like an HTTP request. It works like this:

しかし翻訳すげえなあ。

で、更に下に行くと実例が書いてあります。上からハッシュ形式、ブロック、オブジェクトを作成してからattributesに値をセットする例が紹介されています。ちなみに私のお仕事ではブロックで渡す方法はあまり使っていないですね。 ハッシュで渡すパターンが一番多い印象です。

58行目からは条件(検索)についての説明を書いています。 翻訳

条件は、SQLステートメントのWHERE部分を表す文字列、配列、またはハッシュとして指定できます。
配列フォームは、条件入力が汚染されてサニタイズが必要な場合に使用されます。 文字列形式は、汚染されたデータを含まないステートメントに使用できます。 ハッシュフォームは、等価と範囲のみが可能であることを除いて、配列形式と非常によく似ています。

原文

Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
The array form is to be used when the condition input is tainted and requires sanitization. The string form can be used for statements that don't involve tainted data. The hash form works much like the array form, except only equality and range is possible.

で上から文字列、配列、ハッシュ形式でのwhere句の使い方例が書いてます。安全性を考慮すると配列かハッシュにするべきなんですね・・。AND条件が書きやすいという理由から配列型で書いてました。お恥ずかしい。

本日はここまで。

ActiveRecordをちまちまと読みます その1

はじめに

こんにちは!貧弱スキルなRailsエンジニアです。 ロクにSQLも書けない私がDBをよしなに出来るのも、ひとえにActiveRecord様のおかげであります。しかし普段お世話になっておきながら実は仕組みがあまり良くわかっていない・・。用法、用量を知らなければ使いこなすことは出来ないでしょう。 と、いうことでActiveRecordを深く知るためにソースを少しずつ読んで行こうと思います。

最初の1歩

早速Githubrailsリポジトリを見てみます。

github.com

この大量のフォルダ群のどこから見ていけばいいのか分からず心が折れそうです。 しかし気を取り直します。 ActiveRecordと言えば、modelのトップでBaseを継承してるのでbaseから見ていこうと思います。

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb

yaml、active_support、active_record内のファイルをrequireしていますね。さらにその下にいくと軽くAcitiveRecordについての説明が書いてあります。英語で心が折れそうになります。こんなときはGoogle先生に翻訳してもらいます。

28-34行目までの訳(Google翻訳そのまま)。

Active Recordオブジェクトは、その属性を直接指定するのではなく、
それらがリンクされているテーブル定義 属性の追加、削除、および変更
そのタイプはデータベースで直接行われます。 変更は即座に
アクティブレコードオブジェクト。 特定のActive Recordクラスを特定のActive Recordクラスにバインドするマッピング
ほとんどの一般的なケースで自動的にデータベーステーブルが作成されますが、珍しいデータベーステーブルは上書きされる可能性があります。
より多くの洞察を得るには、table_nameのマッピング規則とlink:files / activerecord / README_rdoc.htmlの完全な例を参照してください。

ちなみに原文

Active Record objects don't specify their attributes directly, but rather infer them from
the table definition with which they're linked. Adding, removing, and changing attributes
and their type is done directly in the database. Any change is instantly reflected in the
Active Record objects. The mapping that binds a given Active Record class to a certain
database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
 See the mapping rules in table_name and the full example in link:files/activerecord/README_rdoc.html for more insight.

すごい!読める!珍しいデータベーステーブルってなんだろう。base.rbを読んだら次はREADME_rdocを見てみたいと思います。

さらに説明が下に続きますが本日はここまで。

MySQLでカラム名にcurrent_timeを使ってはいけない

表題のままなんだけど、where句で'current_time'というカラムに対して比較演算子を用いて抽出しようとしたけど期待される結果が出なくておかしいな?と思って調べたところcurrent_timeは予約語なんですね。。本来はカラム名に使わないのがベターなんですが、使用してしまった場合はSQL文書く際にバッククォートで囲うとエスケープしてくれます。

SELECT
*
FROM
test_table
WHERE
current_time > 0

SELECT
*
FROM
test_table
WHERE
`current_time` > 0

予約後は以下に一覧があるのでご参考まで。intervalとか危ないですね。 MySQL :: MySQL 5.6 リファレンスマニュアル :: 9.3 予約語

railsのaccepts_nested_attributes_forでhas_oneな時の注意点

Railsでモデル同士がhas_oneの関連を持っている時、buildしようとしたらundefined buildと怒られたので原因を調査したところ、子モデルをbuildしたい時は以下のようにすることが分かった。

has_many → 親.子.build
has_one → 親.build_子

例えばUserという親モデルにItemという子モデルがhas_oneで関連を持っている場合は、user.build_itemとすることでbuildできる。

class User < ActiveRecord::Base 
  has_one :item, :dependent => :destroy
  accepts_nested_attributes_for :item
end

class Item < ActiveRecord::Base  
  belongs_to :user
end

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M001834

gemfileでmysql2をbundle installしようとしたら失敗した件

bundle installしたら An error occurred while installing mysql2 (0.3.18), and Bundler cannot continue. Make sure that gem install mysql2 -v '0.3.18' succeeds before bundling. というエラーが出た。

gem install mysql2 -v '0.3.18'を実行するも、 ERROR: Error installing mysql2: ERROR: Failed to build gem native extension. とエラーが出現。

エラーメッセージを頼りに調べてみると、以下の記事が http://stackoverflow.com/questions/10051448/error-failed-to-build-gem-native-extension-mysql2-on-rails-3-2-3

どうやらmysqlをインストールすれば良さそう。 brew install mysqlでインストール

すると You can try again using: brew link mysql

Error: Could not symlink share/aclocal/mysql.m4 /usr/local/share/aclocal is not writable.

と出てきたのでbrew link mysqlすると Error: Could not symlink share/aclocal/mysql.m4 /usr/local/share/aclocal is not writable. 書き込み権限が無いらしい。。。

sudo brew link mysqlした後に

gem install mysql2 -v '0.3.18'したら成功。

bundle installしたらこちらも成功。

やっぱmysqlがローカルに無かったからみたいね。

bundle installが失敗した時の解決法

やったこと

gemのバージョンを最新にした。

gem update --system

エラーメッセージは以下のとおり

Gem::RemoteFetcher::FetchError: Errno::ETIMEDOUT: Operation timed out - connect(2) for "rubygems.global.ssl.fastly.net" port 443 (https://rubygems.org/gems/guard-rspec-4.6.3.gem)
An error occurred while installing guard-rspec (4.6.3), and Bundler cannot
continue.
Make sure that `gem install guard-rspec -v '4.6.3'` succeeds before bundling.

gem install guard-rspec -v '4.6.3'したけど同じように失敗したので、ひょっとして、と思いgemを最新のものにしたら問題無くbundle install出来た。

Backbone.jsでモデルを作成する

Backbone.jsとは?

jsのフレームワーク。煩雑になりがちなjsのコードを管理しやすくするためのもの。

Backboneモデルについて

アプリケーションで使うデータを構造化したもの。

早速例として連絡先モデルを作ってみる。

// extend()メソッドを呼び出すことでオブジェクトの複製を作ることが出来る。
var Contact = Backbone.Model.extend({
  //defaultプロパティで初期値を設定する。
  defaults: {
    name: 'hogename',
    email: 'hoge@mail.com'
  }
});

クラスからインスタンスを生成する流れそのままですね。