u16suzuの blog

日々学んだことのメモブログです。

開発時のみ実行するコードを実現するマクロ

微妙に objc の時と変わった。 毎回、手でやるのがたいへんな画面操作を、自動でやりたいときなどに、この中に組み込んでいたりする。

#if DEBUG
  // こんなかんじで、 画面遷移を自動でさせちゃう。
  let vc = EntryViewController.instantiateFromStoryboard()
  vc.entry = self.entryList[0]
  self.navigationController?.pushViewController(vc, animated: true)
#endif

swiftのコピペコード置き場

UILabel

  • 開発中のデバッグでたまにコードで置いちゃう。
let label = UILabel.init(frame: CGRectMake(0, 100, 0, 0))
label.text = "Test Label"
label.sizeToFit()
view.addSubview(label)

イニシャライザの UILabel.init(frame: frame)UILabel(frame: frame) とも書ける。 個人的には, objc っぽい見た目なので init がある前者のほうがすき。 あと、手早く書きたいならば let label:UIlabel ではなく、 let label = ... と書いちゃって、型推論に任せる。 せっかくあるものだから使っていかないと。

UIButton

let btn = UIButton.init(type: .System)
btn.frame.origin.y = 150
btn.setTitle("button", forState: .Normal)
btn.sizeToFit()
btn.addTarget(self,
    action: "buttonPushed:",
    forControlEvents: .TouchUpInside)
view.addSubview(btn)

// MARK: - Controll Actions

func buttonPushed(sender: UIButton){
    print( "buttonn pushed" )
}

Swift になって、 btn.frame.origin.y = 150 みたいに直接座標を指定できるようになったの便利。

Pragma Mark

// MARK: - Controll Actions

Swift で enumを定義する

以下のように enum で環境を定義して、そこにAPIのBase URLを持たせることをよくする。

enum Env: Int {
    case Local
    case Staging
    case Production

    func baseURL() -> String {
        switch(self) {
        case .Local:
            return "http://localhost:3000"
        case .Staging:
            return "http://stg.hoge.com"
        case .Production:
            return "http://hoge.com"
        }
    }

    func description() -> String {
        switch(self) {
        case .Local:
            return "Local"
        case .Staging:
            return "Staging"
        case .Production:
            return "Production"
        }
    }
}

enum から Int 型への変換は以下の通り rawValue というメソッドを使う。

Env.Local.rawValue

swiftでテーブルビューの delegate と datasource を書く

    // MARK: - UITableViewDelegate
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }
    
    // MARK: - UITableViewDataSource
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }
    
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 50
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = UITableViewCell.init()
        cell.textLabel?.text = "cell\( String(indexPath.row) )"
        
        return cell
    }

ES6について WebDB Press でざっと斜め読みした

  • var ではなく let を使うことでブロックスコープを使える
  • for loop でも let を使うと良い
  • 関数定義にアロー演算子を使えるようになった
  • クラスが使えるようになった
  • constで定数定義できる

会社の人と飲んだ

仕事を早めに切り終えて, 会社の同僚5人と久しぶりに飲みに行った。 自然と話題は会社のことや仕事のことになった。 普段なかなか話せないような、 思っていることをざっくばらんと話せる場があることはとてもいいことだ。

冷や汁を初めて作った

この間の土日に男子ご飯のレシピを参考にして冷や汁を初めて作った。 冷たい汁にキュウリとミョウガのシャキシャキした歯ざわりが心地よかった。

30日間チャレンジ

とてもよかった。 刺激を受けてブログをコツコツと書き始めてみる。

マット・カッツの30日間チャレンジ

今日は rake db 系のコードを読んでみた。 いつもお世話になっているコマンドなので, 内部の処理をあまり理解せずに使っていることに違和感を感じていた。 とくにいくつか,名前がにていて何が異なるのかがわからないコマンドがいくつかあった。

rake db 系のコマンドは以下で定義されている。

/activerecord/lib/activerecord/tasks/database.rake

気になったコマンドをいくつか見てみた。

rake db:migrate:reset

drop, create, migrate をまとめてやる。

desc がコメントアウトされていて -T で表示されないようになっている。 理由はわからない。

# desc 'Resets your database using your migrations for the current environment'
task :reset => ['db:drop', 'db:create', 'db:migrate']

rake db:reset

drop, reset をする。 db/schema.rb から復元する。 seeds の読み込みも行う。 (とコメントに書いてある。)

# desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
  task :reset => [:environment, :load_config] do
    db_namespace["drop"].invoke
    db_namespace["setup"].invoke
  end

次にrake db コマンドの実行からどのようにDB操作の処理が行われているのかを追ってみた

RailsMySQL, PostgreSQL, SQLite に対応しているので, database.rb にある設定を読み込んで 各 DB に対応する DB操作を行うクラスを選択している。 この処理は gems/activerecord-4.2.3/lib/active_record/tasks/database_tasks.rbにある register_task が行っている。

ActiveRecord::Tasks::DatabaseTasks が include された時点で, MySQL, PostgreSLQ, SQLite のタスクとキーのペアが登録される。

def register_task(pattern, task)
  @tasks ||= {}
  @tasks[pattern] = task
end

register_task(/mysql/,        ActiveRecord::Tasks::MySQLDatabaseTasks)
register_task(/postgresql/,   ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
register_task(/sqlite/,       ActiveRecord::Tasks::SQLiteDatabaseTasks)

class_for_adapter メソッドが, DBアダプタから, そのDBに対する ActiveRecord::Tasks を返す。 class_for_adapter の内部処理的には, adapter 引数で指定した DBタイプが @tasks にキーとしてあるかを確認して あれば, そのキーを返すという処理をしている。 detect を使っているのは 正規表現でマッチングさせたいからだと思う。 Array#detect メソッドは Array#find のエイリアス

  def class_for_adapter(adapter)
    key = @tasks.keys.detect { |pattern| adapter[pattern] }
    unless key
      raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
    end
    @tasks[key]
  end

database_configuration メソッドは database.yaml を読み込むメソッドrailties-4.2.3/lib/rails/application/configuration.rb にある。

単純に yaml をパースしてオブジェクトを返すようだが, なぜ ERB.new しているのかはまだ調べ切れていない。

  # Loads and returns the entire raw configuration of database from
  # values stored in `config/database.yml`.
  def database_configuration
    path = paths["config/database"].existent.first
    yaml = Pathname.new(path) if path

    config = if yaml && yaml.exist?
      require "yaml"
      require "erb"
      YAML.load(ERB.new(yaml.read).result) || {}
    elsif ENV['DATABASE_URL']
      # Value from ENV['DATABASE_URL'] is set to default database connection
      # by Active Record.
      {}
    else
      raise "Could not load database configuration. No such file - #{paths["config/database"].instance_variable_get(:@paths)}"
    end

    config
  rescue Psych::SyntaxError => e
    raise "YAML syntax error occurred while parsing #{paths["config/database"].first}. " \
          "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
          "Error: #{e.message}"
  rescue => e
    raise e, "Cannot load `Rails.application.database_configuration`:\n#{e.message}", e.backtrace
  end