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歩
この大量のフォルダ群のどこから見ていけばいいのか分からず心が折れそうです。 しかし気を取り直します。 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. 書き込み権限が無いらしい。。。
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' } });
クラスからインスタンスを生成する流れそのままですね。