MySQLでよく使うコマンド

MySQLでよく使うコマンドたちを載せておきます。

 

MySQLサーバーにログインに指定できるオプションたち

オプション 用途
--passowrd=[パスワード] ログインパスワードの指定
--host=[ホスト名/IP] 接続先のホスト名/IPアドレスの指定
--port=[ポート番号] MySQLサーバーのポート番号の指定
--database=[データベース名] 使用するデータベース名の指定
mysql -u root --password=tamtam --host=127.0.0.1 --port=3306 --database=tw_ics_production < script/sql/optimaize_tables.sql

 

DB単位のエクスポート(ダンプ)

mysqldump -u ユーザ名 -p DB名 > 出力先ファイル名.sql

 

DB単位のインポート

mysql -u ユーザ名 -p DB名 < ダンプファイル名

 

ユーザの作成

GRANT ALL PRIVILEGES ON *.* TO [ユーザー名]@localhost IDENTIFIED BY '[パスワード]'

上記のようにGRANT構文を使用します。

"ALL PRIVILEGES"のところで当該ユーザのユーザの権限を指定しています。この例では全ての権限を持たせていますが、SELECTとINSERTだけできるユーザにしたい場合には"ALL PRIVILEGES"の代わりに"SELECT,INSERT"と入力します。

次に顔文字みたな"*.*"ですが、前のアスタリスクがデータベース名を指定するところで、後ろのアスタリスクがテーブル名を指定するところです。ここではワイルドカードを指定しているので全データベース・全テーブルにおいてこのユーザの権限が有効になります。

ユーザ名@の後ろが"localhost"となっていますが、これはローカルホストからのだけ接続できるユーザであることを指定しています。"localhost"の代わりに"%"を指定すればどのホストからでも接続できるユーザであることを指定できます。

 

ユーザの一覧を表示

SELECT user, host FROM mysql.user;

 

 

 

Objective-Cでよく使うけと忘れてしまいがちなテクニックたち

このメモにはObjective-Cでよく(?)使うけど毎回忘れてしまい、Google検索するところから始めなければならないようなテクニックたちを載せておきます。

 

文字列を置換する

NSStringのstringByReplacingOccurrencesOfStringメソッドを使います。

NSString *result = [targetString stringByReplacingOccurrencesOfString:@"置換対象文字列" withString:"新しく置き換える文字列"];

 

文字列を結合する

いろいろやり方があります。まずは一番単純なものを。

NSString newString = [stringA stringByAppendingString:stringB];

 

double型を文字列に変換する

一度NSNumberにするところがポイントです。

double d = 1.234;
NSString *str = [[NSNumber numberWithDouble:d] stringValue];

 

NSFetchedResultsControllerによってフェッチされたNSManagedObjectを取得する

NSArray *objects = [self.fetchedResultsController fetchedObjects];

 

配列の最後の要素を取得する

NSArray *objects = @[@"A", @"B", @"C"];
NSString *last = [objects lastObject];

 

 

 

Railsでよく使うけと忘れてしまいがちなテクニックたち

このメモにはRailsでよく(?)使うけど毎回忘れてしまい、Google検索するところから始めなければならないようなテクニックたちを載せておきます。

 

redirect_toするときにパラメータを渡す

実は簡単で、遷移先のパスの後ろに括弧書きでパラメータを記述すればできます。

redirect_to users_path(:name => '田村', :age => '7')

 

Assets Pipelineを使っている環境でのCSSにおけるファイルパスの書き方

CSSのbackground-imageプロパティにurlキーワードでファイルパスを指定しますが、RailsではAssets Pipelineを使っていると本番環境ではファイルパスが事前にわかりません。そこでimage-urlというキーワードを使います

background-image: image-url("tamurasouko.png")

 

グローバル定数を定義する場所

いろいろなやり方があるみたいですけど、config/initializers/constants.rbを作成してそこに定義するのが個人的にはしっくりきました。

# constants.rb
COMPANY_NAME = '田村倉庫'
PHONE_NUMBER = '0238-24-2130'

 

DBのテーブルから特定のカラムの値を取り出す

ActiveRecordのpluckメソッドを使います。

@user_names = User.where(:age => 20).pluck(:name)

ちなみにUser.all.pluckとするとエラーになるので注意。この場合はUser.pluckと記述します。

 

日付の操作

Rails、というかRubyの日付処理は以下のように非常に直感的に行えます。

current_date = Date.today
at_next_month = current_date + 1.month # 1ヶ月後の日付
at_next_year = current_date + 1.year # 1年後の日付

 

ActiveRecordで「比較」の検索条件を指定

大なり小なりといった大小を比較するときは以下のようにします。(他にもっといい方法があるような気もしますが)

target_users = User.where("age > ?", 20)

 

ActiveModelのバリデーションを実行

通常、ActiveModelのバリデーションはsaveメソッドやupdateメソッドが実行されるときに行われますが、事前にバリデーションだけを行いたい、というときには以下のようにします。(※@userはActiveModelオブジェクトです)

@user.valid?

 

バリデーションなしでsaveメソッドを実行する方法

@user.save :validate => false

 

Railsに設定したタイムゾーンで文字列をDatetime型に変換する

date = Time.parse('2013/10/23 16:53:07').to_datetime

Datetime.parse('...')としてしまうとRailsに設定したタイムゾーンを無視して変換されてしまうので注意が必要です。

 

モデルからヘルパーメソッドを呼び出す

ApplicationController.helpers.[ヘルパーメソッド名]

 

他のテーブルと結合して他のテーブルの値によってレコードを絞り込む by ActiveRecord

scope :with_role, ->(role_name) { joins(:user_roles).where(user_roles: {role: role_name})}

 

カラムを追加するときに順番を指定する

マイグレーションファイル中でafterを使って指定します。

add_colum :users, :phone_number, :string, after: :name

 

 ActiveRecordでBETWEENのように範囲を条件指定する

# 今日から1ヶ月先までに誕生日があるユーザを抽出
today = Time.current
next_month = today + 1.month
User.where(birthday: today..next_month)

 

環境

Rails 3.2.9

CentOS – セキュリティ

不正アクセス防止のためのセキュリティ対策のメモです。

 

iptables関連

▼特定のIPからのアクセスを遮断する
sudo /sbin/iptables -A INPUT -s [IPアドレス] -j DROP

※iptablesにはポリシーの適用に優先順位があるので設定内容に注意!
上記のコマンドを実行する代わりに/etc/sysconfig/iptablesを編集する方法もあります。

 

環境

CentOS 6.2

 

CentOS – 環境設定

サーバーの初期設定時に行う環境設定のメモを載せます。

ホスト名の変更

/etc/sysconfig/networkファイルを以下のように編集します。

HOSTNAME=[変更後のホスト名]

この設定はサーバーの再起動後に反映されます。

 

ユーザの追加とsudoができるようにする

# useradd tamtam
# passwd tamtam
# (ここでパスワード入力)

sudoをできるようにするにはvisudoを実行して以下のように記述します。

## Allow root to run any commands anywhere
root      ALL=(ALL)       ALL
tamtam  ALL=(ALL)       ALL

 

yumする際のレポジトリを追加

# EPELのレポジトリを追加
yum install epel-release

# remiレポジトリを追加(※CentOS6の場合)
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
sudo rpm -Uvh remi-release-6.rpm

 

不足している基本的なパッケージのインストール

sudo yum -y update # 既存のパッケージの最新化
sudo yum -y install gcc make gcc-c++
sudo yum -y install zlib zlib-devel openssl-devel sqlite-devel glibc-headers libyaml-devel readline readline-devel zlib-devel libffi-devel

もしMultilib version problemsがlibyaml-develのインストール時に発生したら、以下のようにして回復します。

yum downgrade -y libyaml
yum install -y libyaml-devel

hostやdigなどのコマンドを使えるようにします。

sudo yum install bind-utils

セッションが切れても大丈夫なようにtmuxも入れとく。

sudo yum install tmux

gitも忘れずに。

 

公開鍵認証のみ有効にする

まずはサーバー側に.sshのディレクトリを作成し、authorized_keysファイルを作成し、その中にクライアント側の公開鍵の内容をコピーします。また、このファイルの権限設定が600になっていないとちゃんと動いてくれないので忘れずに設定します。

ssh-keygen -t rsa
cd .ssh
vi authorized_keys
chmod 600 authorized_keys

次にsshデーモンの設定をします。

sudo vi /etc/ssh/sshd_config
Port 24223 # ポート番号
RSAAuthentication yes # RSA認証の許可
PubkeyAuthentication yes # 公開鍵認証の許可
PasswordAuthentication no # パスワード認証の禁止
PermitRootLogin no # rootユーザの直接ログイン
sudo service sshd restart

 

iptables(ファイヤーフォール)の設定

# 設定を一旦クリア
sudo iptables -F
#SSH接続ポートを開放
sudo /sbin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT
#HTTP通信ポートを開放
sudo /sbin/iptables -A INPUT -p tcp --dport 80 -j ACCEPT
#SSL通信ポートを開放
sudo /sbin/iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# DNS応答の受信を許可
sudo /sbin/iptables -A INPUT -p udp --sport domain -j ACCEPT
# サーバから接続開始したTCP通信の受信パケットを許可
sudo /sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#自ホストのループバックは全て許可
sudo /sbin/iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT

# INPUTの基本ポリシーをドロップにする(※注意:これを最初にやってしまうとホストから切断されて以降アクセス不能になってしまう)
sudo /sbin/iptables -P INPUT DROP

# 設定内容の確認
sudo iptables --list

# 設定を保存(※これをしないとiptables再起動時に設定が消えてしまうので注意)
sudo service iptables save

iptablesの参考文献

 

 

sudo時に参照するパスを追加

/user/local/binをsudo実行時に参照するパスをsudo visudoを実行して追加します。

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

 

MySQLのインストール&設定

インストールはremiレポジトリを参照してyumでインストールするとVersion 5.5以上がインストールできます。

sudo yum install mysql-server mysql-devel --enablerepo=remi

もし上記の方法でうまくいかなければ(CentOS7以上等)ここのサイトを参考にインストールします。

/etc/my.cnfに以下の設定を追加します。

# 文字コードの設定
character-set-server=utf8
# クライアントに合せて文字コードを判断するのではなく、DBサーバーの文字コードを適用する
character-set-client-handshake

サーバー再起動時にMySQLデーモンが起動されるように設定します。

sudo /sbin/chkconfig mysqld on

MySQLデーモンを起動し、rootユーザーのパスワードを設定します。

sudo /etc/init.d/mysqld start # もしくは sudo service mysqld start
mysqladmin -u root password '新しいパスワード'

 

rbenvを使ってrubyをインストール

ここの情報が参考になります。

ちなみにrbenvを最新化する方法は以下の通り。

cd ~/.rbenv
git pull origin master
cd ~/.rbenv/plugins/ruby-build
git pull origin master

gemを更新してbundlerも入れておきましょう。

gem update --system
gem install bundler

NginxとPassengerのインストール

順番が逆のように思えますが、Passengerをインストールした後に、それに付属にNginxのインストーラーを利用してNginxのインストールを行います。

必要なパッケージを予めインストールしておきます。

sudo yum install openssl-devel curl-devel libyaml-devel ruby-devel
sudo rbenv exec gem install passenger
sudo passenger-install-nginx-module # もし「そんなものはない」とエラーになったらsudoにパスが通ってないので、フルパスで実行すればいい

Nginxのインストールが起動したら、Nginxのサービスファイル(起動・停止用スクリプト)を/etc/init.dに配置します。[ここからダウンロード]

次にサーバー再起動にnginxも起動されるようにchkconfigに登録します。

sudo chkconfig --add nginx

このとき、 サービスファイルに以下の記述がないとエラーになります。chkconfigパラメータは左からランレベル、起動優先順位、停止優先順位を表しています。

# chkconfig: 2345 98 20
# description: nginx web server

Nginxの設定ファイルの内容が正しいかどうかは以下のコマンドで確認できます。

sudo /opt/nginx/sbin/nginx -t

 

Railsアプリをインストール

CarrierWaveを使うための準備

sudo yum -y install libjpeg-devel libpng-devel
sudo yum -y install ImageMagick ImageMagick-devel

nokogiriを使うための準備

sudo yum -y install libxml2-devel libxslt-devel
sudo yum install -y patch

mysql2 gemを使うための準備

sudo yum -y install mysql mysql-devel

 

rbenvを使ってRubyをインストールしたときの注意点

rubyのインストール先が通常と違うのでnginxのpassengerの設定のところをデフォルトから変える必要があります。

#passenger_ruby /usr/bin/ruby;
passenger_ruby /home/user_name/.rbenv/shims/ruby;

 

PHPのインストール

まずremiレポジトリの設定を変えてPHP 5.6がインストールできるようにします。

sudo vi /etc/yum.repos.d/remi.repo

上記を実行して[remi-php56]となっているセクションをenabled=1にした後、下記を実行します。

sudo yum install --enablerepo=remi php php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit php-pecl-xdebug

以下のようにPHPの設定を行います。

sudo vi /etc/php.ini
default_charset = "UTF-8"
date.timezone = "Asia/Tokyo"
mbstring.language = Japanese

 

php-fpmのインストール

sudo yum --enablerepo=remi install php-fpm

設定が必要であれば /etc/php-fpm.d/www.conf の設定ファイルを編集します。

AWS S3とファイルを同期

ここのページのまとめがすばらしい!

 

 

環境

CentOS 6.2

 

 

 

 

Rails – 親子テーブルを一度に更新する方法

parent_and_child_model_insert上記のような一画面に基本情報(宛先、住所)と複数の明細情報(物品名、数量)がある画面で入力された情報を親子関係にある基本テーブル(発送テーブル)と明細テーブル(物品テーブル)に同時に登録したい場合が業務アプリではけっこうあると思います。

Railsではこのようなケースに簡単に対応するための便利機能が用意されています。具体的にはモデルでaccepts_nested_attributes_forという設定を、ビューでfield_forメソッドを利用します。この機能を利用すると以下の2つメリットがあるので是非活用することをオススメします。

  1. ソースコードが短くてすむ
    ⇒ 後述しますが、特にコントローラー側の記述量は激減します。
  2. 明細データへのバリデーション結果が画面にキレイに表示できる
    ⇒ 親子関係をRailsに認識させることで明細データのバリデーション結果を表示するロジックを個別に実装する必要がなくなります

以下、モデル、コントローラー、ビューの順に実装方法を載せていきます。

 

モデル

まずモデルですが、物品の発送指示に対応するShippingモデル(親)と、その発送指示の明細にあたるGoodモデル(子)があるとします。それぞれのソースは以下のようになります。

# shipping.rb
class Shipping < ActiveRecord::Base

  has_many :goods
  accepts_nested_attributes_for :goods

  attr_accessible :to_name, :address

  # 子モデルの要素にもアクセスできるようにする
  attr_accessible :goods_attributes

  validates :to_name, :presence => true
  validates :address, :presence => true
end
# good.rb
class Good < ActiveRecord::Base

  belongs_to :shipping

  attr_accessible :name, :quantity

  validates :name, :presence => true
  validates :quantity, :presence => true
end

has_many、belongs_toでモデル間の親子関係を記述するのはおなじみですね。それ以外に重要なポイントが親モデルのShippingに2つあります。 accepts_nested_attributes_for :goods という記述でGoodモデルの要素をShippingモデルの子要素として認識させます。加えて、attr_accessible :goods_attributes という記述でGoodモデルへのアクセスを許可しています。

 

コントローラー

通常、親子関係のデータを処理する場合はコントローラーがごちゃごちゃになってしまうのですが、モデルに上記のような設定をしたおかげで以下のように記述量が恐ろしく少なくなります。(newメソッドとcreateメソッドを抜粋して載せます)

  def new
    @shipping = Shipping.new

    # 明細を3行分用意する(このあたりのロジックは要件によって変えてください)
    3.times do |
      good = Good.new
      @shipping.goods << good
    end
  end

  def create
    @shipping = Shipping.new(params[:shipping])

    if @shipping.save
      redirect_to @shipping
    else
      render :action => 'new'
    end
  end

ポイントは1つだけ。 @shipping.goods << good としてShippingオブジェクトの子要素のインスタンスを設定しています。

 

ビュー

ポイントはform_forの変数からfield_forメソッドを呼び出して子要素のフィールドを表現しているところです。

<h1>発送指示</h1>

<% if @shipping.errors.any? %>
<div id="error_explanation">
  <ul>
    <% @shipping.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
    <% end %>
  </ul>
</div>
<% end %>

<%= form_for(@shipping) do |shipping_form| %>
  <%= shipping_form.label :to_name %>
  <%= shipping_form.text_field :to_name %>

  <%= shipping_form.label :address %>
  <%= shipping_form.text_field :address %>

  <table>
    <tr>
      <th>物品名</th>
      <th>数量</th>
    </tr>
    <% @shipping.goods.each do |good| %>
      <%= shipping_form.fields_for :goods, good do |good_field| %>
      <tr>
        <td><%= good_field.text_field :name %></td>
        <td><%= good_field.text_field :quantity %></td>
      </tr>
    <% end %>
  </table>

<% end %>

ビューの前半にバリデーション結果を表示するためのロジックがありますが、ここをよくみてみると、 @shippingオブジェクトだけにアクセスしています。このオブジェクトには子オブジェクトであるgoodオブジェクトのバリデーション結果も含まれているため、わざわざ@shipping.goodとして子オブジェクトのバリデーション結果を取り出さずとも済みます。これがメリットの2番目として挙げたものです。

 

環境

Rails 3.2.9

参考文献

Ruby on Rails Documentation の field_forの箇所

やっぱり公式のドキュメントは鉄板ですね。

 

Rails – テーブルなしのモデルを利用する方法

RailsではモデルとDBのテーブルが1対1の関係になっていることが多いですが、対応するテーブルはないけどモデルを利用したい、というシーンがあると思います。

特に画面の入力内容が1つのテーブルに対応していない場合によく使われるとおもいます。例えば、CSVファイルの内容をインポートして各テーブルにデータを登録する場合のファイルアップロード画面用でテーブルなしモデルを使うと便利です。

このメモではこの「テーブルなしモデル」する方法を紹介します。

 

なぜ「テーブルなしモデル」を使うか

テーブルなしモデルを利用することで以下の3つのメリットが得られると思います。

  1. ActiveModelの強力なバリデーション機能を使える
    ⇒ 自分でバリデーションロジックを書かなくて済みます
  2. 他のソースコードとの統一性が保てる
    ⇒ 入力をモデル化することでform_forなどのメソッドが使えるため、テーブルありの場合のロジックと同様に処理することができます
  3. ソースコードが汚くならない
    ⇒ 無理にテーブルなしモデルを使わないで実装しようすると、既存のテーブルありモデルのソースに多くのロジックが追加され、何がしたいソースなのかわけけがわからなくなってしまいます

 

テーブルなしモデルの実装

ActiveAttr」というgemを利用すると「テーブルなしモデル」が少ない記述量で実現できます。このgemを利用しなくてもテーブルなしモデルは実現できますが、コードの可読性も高まるので利用することをオススメします。

ActiveAttrのインストールはGemfileに以下のように記述してbundle installコマンドを実行します。

gem 'active_attr'

 

このgemがインストールされていると以下のようにテーブルなしモデルを記述できます。

class Someone
  include ActiveAttr::Model

  attribute :name
  attribute :age

  validates :name, :presence => true

 end

ポイントはActiveAttr::Modelをインクルードしている点と、attributeというキーワードでカラムを定義している点です。以上でテーブルなしモデルが実現できました。

ただし、注意点があります。通常のテーブルありモデルはActiveRecordを基底クラスとしたクラスですが、ActiveAttrではActiveModelクラスを利用しています。そのため、テーブルありモデルでは使えたメソッドがテーブルなしモデルでは使えない場合もあります。(そんなにないですが)

また、モデルの属性名やバリデーションメッセージのja.ymlにおける記述場所も以下のようにActiveRecordとActiveModelでは異なっているため、注意が必要です。

ja:
 activemodel:
    attributes:
      someone:
        name: 名前
        age: 年齢
    errors:
      models:
        inventory_import:
          attributes:
            csv_file:
              blank: が入力されていません
  activerecord:
    attributes:
      item:
        name: 商品名
    errors:
      models:
        item:
          attributes:
            name:
              blank: が入力されていません

 

環境

Rails 3.2.9

参考文献

#326 ActiveAttr

 

 

iOS – カメラデバイスが存在するか判定する方法

iPod touchは機種によってはカメラがないものもあります。そのため、カメラを使うアプリの場合にはカメラが搭載されているか判定する必要があります。

この判定はとても簡単にできます。以下のような分岐を入れるだけです。

if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
  // カメラがある場合
}
else {
  // カメラがない場合
}

 

環境

XCode 4.6.2

 

バージョンアップしたアプリをApp Storeに申請する方法

既にApp Storeに登録されてるアプリを改良して、新しいバージョンとしてApp Storeに載せたい場合は、バージョンアップしたことを申請する必要があります。申請方法は新たにアプリを登録するよりもはるかに簡単ですが、知らないと戸惑うこともあるので、メモとして残しておきます。

 

iTunes Connectで新バージョンを申請

まず、iTunes Connectにサインインし、[Manage Your Apps]の画面に行き、その画面からバージョンアップしたいアプリを選択します。

アプリを選択すると画面下部に現在のバージョンのアプリの情報と、その右に"Add Version"と表記されたボタンが表示されているので、このAdd Versionボタンを押します。

where_is_add_version

そうすると、いろいろな質問が画面に表示されますので答えていきます。そして以下のようなバージョン番号バージョンアップ内容を記述する画面が出てくるので、それぞれの言語ごとにバージョンアップ内容を記述してください。

new_version_apply

最後まで行くと、バージョンアップ前(つまり現在バージョン)のアプリの情報が引き継がれた新しいバージョンのアプリ情報が作成されます。変更点があればアプリ情報を修正し、同画面の右上にある"Ready To Upload Binary”ボタンを押します。これでiTunes Connectでの作業は完了です。

 

XCodeで新バージョンのアプリをApp Storeに送信する

次はXCode上での作業です。プロジェクト内にある"[ターゲット名]-info.plist"を開きます。このファイルの2つの項目"Bundle version"と"Bundle versions string, short"にそれぞれ先ほどiTunes Connectで申請した新しいバージョン番号を以下のように入力します。

change_app_version

後はアプリ申請時同様、このバージョンのArchiveを作成し、Organizer経由でApp Storeに新しいバージョンのアプリを送信して完了です。このあたりの手順については以前の記事「App Storeへのアプリの登録手順」を参考にしてください。

 

環境

XCode 4.6.2