2014年7月20日日曜日

Railsにて複合主キーのテーブルをupdateしたい場合

Railsはデフォルトでは複合主キーに対応しておらず、検索は問題なくできるが、更新系(update,delete)はエラーが発生してしまう。
『rails update Mysql2::Error: Unknown column where clause』的なエラーに遭遇してしまうはず。

そういう場合は、composite_primary_keysというモジュールを組み込むと解決できるので試してみるとよい。

Gemfileに下記を記述
gem 'composite_primary_keys'

その後、bundle install
bundle install

それから、modelを修正する
class UserClassRelation < ActiveRecord::Base
  self.primary_keys = :user_id, :class_id
end

上記を書いたら、アプリケーションサーバを再起動してupdateなどを試してみてください。

2014年7月12日土曜日

Dockerfileを利用してMySQLのインストールとRuby2.1、Railsのインストールを行い、かつソースもGithubからcloneする

Mac上で開発をしてもいいが、あんまり環境を汚したくないのでDocker上のCentOS上で開発ができる用にする再現の装備を整える手順です。

Docker上に設定しきってしまいたい部分。
OS:CentOS
ミドルウェア:MySQL,Ruby2.1,Rails
ソース:Githubのclone

MySQLに関してはutf-8がいいので、設定ファイルをホストOSからコピーさせています。

> cat Dockerfile 

FROM centos
MAINTAINER sample_name 

RUN echo "Install lib"
RUN yum install -y git vim sudo tar wget
RUN yum install -y gcc make gcc-c++ zlib-devel httpd-devel openssl-devel curl-devel sqlite-devel

RUN echo "Install mysql"
RUN yum install -y mysql mysql-server mysql-devel
ADD etc/my.cnf /etc/my.cnf
RUN touch /etc/sysconfig/network

RUN echo "Install ruby"
RUN cd /root/ && wget http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.1.tar.gz
RUN cd /root/ && tar zxvf ruby-2.1.1.tar.gz
RUN cd /root/ruby-2.1.1 && ./configure && make && make install
RUN gem install bundler --no-ri --no-rdoc -V
RUN gem install rb-readline --no-ri --no-rdoc -V

RUN echo "Install rails"
RUN gem install rails --no-ri --no-rdoc -V
RUN gem install mysql2 -v '0.3.16' --no-ri --no-rdoc
RUN echo rails -v

RUN git clone https://github.com/{githubユーザID}/{プロジェクト名}

RUN bundle install

ADDって箇所が、ホストOSのファイルをDocker上にコピーしている部分です。
Dockerfileのディレクトリからのファイルパスを記述します。
ADD ホストOS側のファイルパス Docker上のファイルパス

Dockerfileを利用してのdockerの起動は下記コマンドになります。
docker build -t {docker imageを保存する名前} .
例)
docker build -t ak220/ruby:1.0 .

本来なら、Monitとかのインストールもしてしまって、MySQLの起動などをMonitに任せる感じにしたいところだが、Docker上でシステム開発をすることを目的としているので、この状態で今回は終わりです。

MySQL起動時に /etc/sysconfig/network: No such file or directoryと言われたら

Dockerを利用してCentOS上のMySQLを起動しようとすると下記感じでエラーが出る事がある。
$ /etc/rc.d/init.d/mysqld start
/etc/rc.d/init.d/mysqld: line 23: /etc/sysconfig/network: No such file or directory

その場合は、networkファイルを作ってあげれば解決する。
$ touch /etc/sysconfig/network

git push で 403 Forbidden が発生したら

Githubにpushしたら下記エラーが発生した。
git push
error: The requested URL returned error: 403 Forbidden while accessing https://github.com/{githubユーザ名}/{プロジェクト名}/info/refs

fatal: HTTP request failed

・対処方法
pushするURLを見失っている状態っぽいので、下記コマンドを実施。
git remote set-url origin https://{githubユーザ名}@github.com/{プロジェクト名}
git push
これで正しくpushできるようになるはずです。

2014年6月8日日曜日

Java8のlambda式について

Java8が公開されてそれなりに時間が経ちましたが、さすがにそろそろLambda式に慣れないとまずいということでメモとして残していきます。

Java7までの書き方から始まり、徐々にラムダ式の簡略記法に変換していく感じでまとめています。
go1メソッド→go4メソッドまで順序だてる感じで簡略化していきます。
簡略化の仕方に関しては各メソッドにコメントとして記載しているのでそちらを参照してもらえるとわかりやすいかと思います。

package lambda1;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.UnaryOperator;

public class Main {

 private static final List list = Arrays.asList("a", "b", "c", "d",
   "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
   "r", "s", "t", "u", "v", "w", "x", "y", "z");

 public static void main(final String[] args) {
  Main m = new Main();
  m.go1();
  m.go2();
  m.go3();
  m.go4();
 }

 /**
  * Java8以前の記述方法。
  * この記述を徐々に簡略化していきます。
  */
 public void go1() {
  System.out.println("go1");
  final List l = new ArrayList(list);
  System.out.println(l.toString());
  l.replaceAll(new UnaryOperator() {

   @Override
   public String apply(String str) {
    return "==" + str;
   }

  });
  System.out.println(l.toString());
 }

 /**
  * replaceAllの引数のUnaryOperatorインタフェースは
  * @FunctionalInterfaceのアノテーションが付いているので、
  * ラムダ式で記述を置き換えられる。
  */
 public void go2() {
  System.out.println("go2");
  final List l = new ArrayList(list);
  System.out.println(l.toString());
  l.replaceAll((String t) -> {
   return "==" + t;
  });
  System.out.println(l.toString());
 }

 /**
  * 処理が1行の場合は{}で囲う必要がないので削除。
  * さらにreturnも1行の場合は削除できるので削除。
  */
 public void go3() {
  System.out.println("go3");
  final List l = new ArrayList(list);
  System.out.println(l.toString());
  l.replaceAll((String t) -> "==" + t);
  System.out.println(l.toString());
 }

 /**
  * 型は推論してくれるし、かつ引数が1個なのでカッコも不要。
  */
 public void go4() {
  System.out.println("go4");
  final List l = new ArrayList(list);
  System.out.println(l.toString());
  l.replaceAll(t -> "==" + t);
  System.out.println(l.toString());
 }
}


しかし、便利ですね。
最初はPHPみたいな矢印マークでとっつきにくかったですが、こうやって徐々に簡略化していくと色々とわかりやすく学べました。
これなら、自分で関数インタフェース(@FunctionalInterface)を利用して、便利に色々と作れる気がしてきました。