ActiveHash は、Ruby のHash をActiveRecord-like のモデルとして使用するためのbase class です。
./lib
以下のコード量は、800行程度ですので決して多くはないと思います。
コードリーディングをするのは初めてですので、このぐらいの量がちょうど良いかなと思いました。
目的
- ActiveRecord-like にHash を扱えるようにしている実装
- ActiveYaml 読み取りの実装
基本情報
Version
コード量
$ cloc ./active_hash/lib/ 11 text files. 11 unique files. 0 files ignored. github.com/AlDanial/cloc v 1.80 T=0.03 s (395.3 files/s, 36405.0 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- Ruby 11 190 5 818 ------------------------------------------------------------------------------- SUM: 11 190 5 818 -------------------------------------------------------------------------------
階層構造
他の人のブログを読んでいるときに、階層構造見るたびに「描くの大変そうだなー。」と思っておりました。
皆さん恐らくtree
コマンド使ってたのですね、、、勉強になりました。。。
$ tree ./lib/ ./lib/ ├── active_file │ ├── base.rb │ ├── hash_and_array_files.rb │ └── multiple_files.rb ├── active_hash │ ├── base.rb │ └── version.rb ├── active_hash.rb ├── active_json │ └── base.rb ├── active_yaml │ ├── aliases.rb │ └── base.rb ├── associations │ └── associations.rb └── enum └── enum.rb 6 directories, 11 files
使い方
# active_hash 無し # ./app/models/person.rb class Person < ActiveRecord::Base COUNTRIES = ['US', 'Canada'] end # in some view <%= collection_select :person, :country_id, Person::COUNTRIES, :to_s, :to_s %>
# active_hash 有り # ./app/models/country.rb class Country < ActiveHash::Base self.data = [ {id: 1, name: 'US'}, {id: 2, name: 'Canada'} ] end # in some view <%= collection_select :person, :country_id, Country.all, :id, :name %>
このように、Ruby のハッシュで書いたものをActiveRecord-like に利用することができます。
下記のようにすれば、クラスの外側でもデータを設定することもできます。
# ./app/models/country.rb class Country < ActiveHash::Base end # ./config/initializers/data.rb Rails.application.config.to_prepare do Country.data = [ {id: 1, name: 'US'}, {id: 2, name: 'Canada'} ] end
データを呼び出したいときは、ActiveRecord を呼び出すときのように呼び出せます。
Country.all # => returns all Country objects Country.count # => returns the length of the .data array Country.first # => returns the first country object Country.last # => returns the last country object Country.find 1 # => returns the first country object with that id ...
ちなみに、詳細は省きますがHash だけではなく、YAML・JSON 等の形式でもデータを格納できます。
詳細: README.md
実装内容
ActiveRecord-like にHash を扱えるようにしている実装
ActiveRecord-like なので、当然といえば当然なのですがDB 保存の処理は全く有りません。 その代わり、インスタンス変数にHash の内容を格納しているようです。 全くわかりませんが、本家のActiveRecord もDB 処理を除いては同じような実装なのでしょうかね??? また今度、ActiveRecord の方のコードリーディングにも挑戦してみたいと思います。
ActiveYaml 読み取りの実装
require 'yaml' module ActiveYaml class Base < ActiveFile::Base extend ActiveFile::HashAndArrayFiles class << self def load_file if (data = raw_data).is_a?(Array) data else data.values end end def extension "yml" end private def load_path(path) YAML.load(ERB.new(File.read(path)).result) end end end end
先日、YAML から読み取ったデータの処理を実装したばかりなので気になっていた箇所です。
ActiveYaml::Base
でModule ActiveFile::HashAndArrayFiles
をextend
する形でデータの読み取りを行なっています。
Module ActiveFile::HashAndArrayFiles
にYAML・JSON 共通の処理をまとめたという感じなのでしょうかね???
まだまだ設計的な話は全くわかりません。。。
気になった箇所・メソッド
まとめ
初めてのコードリーディングでどこから始めていいのか全くわかりませんでした。全体的な進め方に関しては、nipe0324さんのコードリーディングを参考にさせていただきました。少しずつ自分なりのコードリーディングのやり方を固めていきたいです。
ソースコードに関してだけでなく、cloc
コマンドやtree
コマンドに関しても知る機会になり、よかったと思います。
次回はクラス図の作成にも挑戦して見たいと思います。一つ一つできることを増やしてきたいと思います!