swift プロジェクトで Other Swift Flags を設定する時は $(inherited) の指定を忘れないようにする

2016年01月20日
区分
Swift
報告者:
namikata

Alamofire のライブラリを CocoaPods 経由でダウンロードしようと思ったら、以下のような警告が表示されました。

[!] The `hoge [Debug]` target overrides the `OTHER_SWIFT_FLAGS` build setting defined in `Pods/Target Support Files/Pods/Pods.debug.xcconfig'. This can lead to problems with the CocoaPods installation
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.

原因としては swift で #if DEBUG を使いたくて Other Swift Flags に -D DEBUG を設定していたことでした。設定には問題がなかったんですが $(inherited) を設定していなくて -D COCOAPODS が反映されなくなっていた(カスタマイズしなければ、デフォルトで $(inherited) が指定されるのかな?)

メッセージの通り target -> hoge -> Other Swift Flags で $(inherited) を指定することでエラーが解消されました。

rspec の change マッチャで assigns が nil になる

2016年01月08日
区分
Rspec
報告者:
namikata

change マッチャの挙動をきちんと理解していなくてつまづきました。

class User < ActiveRecord::Base
  has_many :blogs
end
class Blog < ActiveRecord::Base
  belongs_to :user
end
class UsersController < ApplicationController
  def index
    @user = User.new(name: 'popo')
    @user.save

    b = Blog.new(title: 'mudotaosenai', user_id: @user.id)
    b.save

    render nothing: true
  end
end

といったソースがあるとして(かなり適当です、ごめんなさい) 最初は spec をこう書きました。

require 'rails_helper'

RSpec.describe UsersController, :type => :controller do
  it 'assigins(:user)' do
    get :index
    expect(assigns(:user)).to eq User.last
  end

  it 'blogs.count' do
    expect {
      get :index
    }.to change { assigns(:user).blogs.count }.by(1)
  end
end

assigns(:user) は Green ですが blogs.count は Red です。

Failures:

  1) UsersController blogs.count
     Failure/Error: }.to change { assigns(:user).blogs.count }.from(0).to(1)
     NoMethodError:
       undefined method `blogs' for nil:NilClass

最初はなんで assings(:user) が nil になるのか分からなかったのですが、change メソッドはブロック内に記述した処理の実施前、実施後に値を取得しに行くことを理解し原因がはっきりしました。

このケースでは expect { get: index } とあるので、 get: index が実行される前に一度 @user の値を取得しようとしますが、ruby ではインスタンス変数は呼び出されて初めてセットされるので、get: index の実施前は @user は nil となります。

例があまり良くないですが、 change メソッドでは assigns は nil になるといったことでした。

参考にした記事

change matcher

before_destory の prepend 指定について

2016年01月07日
区分
Rails
報告者:
namikata

ユーザーがブログを書けるアプリケーションとかで、ユーザーが退会したら、関連するブログを削除する指定をすることは良くあると思います。

以下のような設定です。

class User < ActiveRecord::Base
  has_many :blogs, dependent: :destroy
end
class Blog < ActiveRecord::Base
  belongs_to :user
end

退会しても、ブログ情報はアーカイブして持っていたいと思った時とかは before_destroy を使って、削除前にブログのアーカイブ処理をやろうとか思っている時には、ちょっと注意が必要です。何かと言うと、before_destroy が実行される時には、すでに Blog 情報は削除されているといった問題です。

class User < ActiveRecord::Base
  has_many :blogs, dependent: :destroy

  before_destroy :ekusdesu_taosenai

  private
  def ekusdesu_taosenai
    puts Blog.first.title
  end
end
class Blog < ActiveRecord::Base
  belongs_to :user
end

こんなコードを書いたとして、ユーザーを削除すると、エラーになります。

[1] pry(main)> u = User.new(name: "popo")
=> #<User:0x007fcd95dacf18 id: nil, name: "popo", created_at: nil, updated_at: nil>
[2] pry(main)> u.save
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "popo"], ["created_at", "2016-01-06 09:31:19.952772"], ["updated_at", "2016-01-06 09:31:19.952772"]]
   (2.0ms)  commit transaction
=> true
[3] pry(main)> b = Blog.new(title: "エクスデス強すぎ", user_id: u.id)
=> #<Blog:0x007fcd95c8d948 id: nil, title: "エクスデス強すぎ", created_at: nil, updated_at: nil, user_id: 18>
[4] pry(main)> b.save
   (0.1ms)  begin transaction
  SQL (0.3ms)  INSERT INTO "blogs" ("title", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["title", "エクスデス強すぎ"], ["user_id", 18], ["created_at", "2016-01-06 09:32:04.797796"], ["updated_at", "2016-01-06 09:32:04.797796"]]
   (2.1ms)  commit transaction
=> true
[5] pry(main)> u.destroy
   (0.1ms)  begin transaction
  Blog Load (0.2ms)  SELECT "blogs".* FROM "blogs" WHERE "blogs"."user_id" = ?  [["user_id", 18]]
  SQL (1.1ms)  DELETE FROM "blogs" WHERE "blogs"."id" = ?  [["id", 12]]
  Blog Load (0.1ms)  SELECT  "blogs".* FROM "blogs"  ORDER BY "blogs"."id" ASC LIMIT 1
   (1.9ms)  rollback transaction
NoMethodError: undefined method `title' for nil:NilClass
from /Users/namikata/work/before_destory/before_destory/app/models/user.rb:9:in `ekusdesu_taosenai'

この問題を回避するには before_destroy に対して prepend: true を指定します。prepend は英単語としては存在してなくて pre + append を組み合わせた造語らしいです。指定すると Blog を削除する前に、処理を行ってくれるようになります。

class User < ActiveRecord::Base
  has_many :blogs, dependent: :destroy

  before_destroy :ekusdesu_taosenai, prepend: true

  private
  def ekusdesu_taosenai
    puts Blog.first.title
  end
end
[1] pry(main)> u = User.new(name: "popo")
=> #<User:0x007fcd93432f48 id: nil, name: "popo", created_at: nil, updated_at: nil>
[2] pry(main)> u.save
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "popo"], ["created_at", "2016-01-06 09:29:40.860009"], ["updated_at", "2016-01-06 09:29:40.860009"]]
   (2.0ms)  commit transaction
=> true
[3] pry(main)> b = Blog.new(title: "エクスデス強すぎ", user_id: u.id)
=> #<Blog:0x007fcd95e97018 id: nil, title: "エクスデス強すぎ", created_at: nil, updated_at: nil, user_id: 17>
[4] pry(main)> b.save
   (0.1ms)  begin transaction
  SQL (0.3ms)  INSERT INTO "blogs" ("title", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["title", "エクスデス強すぎ"], ["user_id", 17], ["created_at", "2016-01-06 09:30:03.992078"], ["updated_at", "2016-01-06 09:30:03.992078"]]
   (2.0ms)  commit transaction
=> true
[5] pry(main)> u.destroy
   (0.1ms)  begin transaction
  Blog Load (0.1ms)  SELECT  "blogs".* FROM "blogs"  ORDER BY "blogs"."id" ASC LIMIT 1
エクスデス強すぎ
  Blog Load (0.1ms)  SELECT "blogs".* FROM "blogs" WHERE "blogs"."user_id" = ?  [["user_id", 17]]
  SQL (0.4ms)  DELETE FROM "blogs" WHERE "blogs"."id" = ?  [["id", 11]]
  SQL (0.2ms)  DELETE FROM "users" WHERE "users"."id" = ?  [["id", 17]]
   (2.7ms)  commit transaction
=> #<User:0x007fcd93432f48 id: 17, name: "popo", created_at: Wed, 06 Jan 2016 09:29:40 UTC +00:00, updated_at: Wed, 06 Jan 2016 09:29:40 UTC +00:00>

参考にしたサイト

Active Record Callbacks

Unicorn と Nginx と Rails の関係

2015年11月13日
区分
Rails
報告者:
namikata

皆さん。初めまして。最近アクトインディに入社した namikata です。

  • エンジニア職未経験
  • 30歳を超えている

といったプロフィールを持っていますが、チャレンジするのに年齢は関係ありませんの精神で、これから頑張ってエンジニアライフを送っていきたいと思います。

子供とお出かけ情報「いこーよ」 は、Nginx + Unicorn + Rails で構成されています。勉強していて Nginx と Unicorn と Rails の関係性が自分の中でちょっと不明瞭だったので、調べた結果をまとめてみました。間違ってたらゴメンなさい。

各役割は以下になります。

名称 役割
Unicorn Rack Webサーバー
Nginx Webサーバー
Rails フレームワーク

Rack は WSGI に影響されて開発された Ruby におけるサーバとアプリケーション/フレームワーク間のインターフェースの役割を果たすライブラリ 第23回 Rackとは何か(1)Rackの生まれた背景

Unicorn は Rack Webサーバー の分類で、Rack と Webサーバーの機能を合わせて持つ。Webrickも同様。ただ、Webサーバーとしてのレスポンス処理はApacheやNginxに劣る。Railsを公開するときは、Unicorn + Rails の環境で公開することは可能だが、モチはモチ屋の発想で Nginx + Unicorn + Rails の構成を取るのが一般的。Nginx単体では、Rackの機能をサポートしていない為、Nginx + Rails ではアプリケーションは動作しない。

以上です。これからも勉強した内容はまとめていきたいと思いますので、どうか宜しくお願いします。

参考

Rack Webサーバ(Rack Web Server)は、RubyアプリケーションとWebサーバをつなぐための中間サーバ、として扱われることが多い。通常のWebサーバはRackのような機能をサポートしていないが、Rack Webサーバを挟むことで、RubyアプリケーションなどをWebサーバ上で動作させることができる。Rack Webサーバ単体でも機能するにはするみたいだけど、Apacheなどの既存のWebサーバはレスポンスの処理がうまいので、それらと組み合わせて使うことが多いらしい。 ApacheとNginxとPassengerとUnicornの違い【すごい初心者向け】

Rack はWebサーバー(Nginx)とフレームワーク(Rails)の間を取り持つライブラリ 5分でわかるRack

技師部隊からの
お知らせ

【求人】エンジニア募集しています。

本頁の来客数
八十七万千百七十六名以上(計測停止中)

メンバー一覧

アクトインディ技師部隊員名簿

アクトインディ技師部元隊員

アクトインディへ

カテゴリー

アクトインディ

aaaa