tezu memo blog

日々行った作業をメモしていきます

GoogleAnalyticsとウェブマスターツールの連携

実施頻度が低く失念してしまったのでメモ

  1. GA トラフィック→検索エンジン最適化→検索クエリーを選択
    f:id:tezu35:20130204103332j:plain

  2. GA ウェブマスタツールサイト 編集リンクを選択。ウェブマスタツールに移動
    f:id:tezu35:20130204104610j:plain

  3. ウェブマスタツール 対象のサイトを選択後に保存ボタンを選択
    ウェブマスタツールにサイトを追加ボタンでは無い
    f:id:tezu35:20130204104618j:plain

  4. GA ウェブマスタツールで指定したサイトの紐付けを確認して、適用ボタンを選択
    f:id:tezu35:20130204105107j:plain

  5. GA トラフィック→検索エンジン最適化→検索クエリーを選択
    ウェブマスタツールの検索クエリがGAにも表示出来る
    GA
    f:id:tezu35:20130204103241j:plain

    ウェブマスタツール
    f:id:tezu35:20130204105431j:plain

Grails GORM Enum

Domainクラスのint型属性をEnumに変更

1. Enum作成。#getIdを実装。これで任意の値をDBに登録出来る
[#GRAILS-3633] Enhanced Enum support - Grails JIRA

If the enum has an instance method "getId()" which has a return type

public enum Sex {
    MAN(1),WOMAN(2);
    private int id;
    private Sex(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }
}

2. Domainクラス intからEnumに変更

import groovy.transform.ToString

@ToString
class Member {
    Date dateCreated
    Date lastUpdated

    String mail
    String firstName
    String lastName
    String password
//  int sex;
    Sex sex;
    String tel
    String zip
    String prefectures
    String address1
    String address2
    String memo
}

3. 初期データ 数値からenumに変更(sex:2 → sex:Sex.WOMAN)。Groovy SQL便利ですね

import groovy.sql.Sql
import jp.gr.java_conf.tezu.grails.ec.Member
import jp.gr.java_conf.tezu.grails.ec.Sex

class BootStrap {

    def sessionFactory

    def init = { servletContext ->
        if (Member.count() != 0) {
            Member.getAll().each { entity ->
                entity.delete()
            }
        }
        def entity = new Member(mail:"xxxxx@gmail.com",firstName:"Taro",lastName:"Grails",password:"password",sex:Sex.WOMAN,tel:"0611112222",zip:"1008924",prefectures:"東京都",address1:"千代田区永田町1-10-1")
        if (!entity.save(flush:true)) {
            entity.errors.each { println it }
        }
        
        def conn = new Sql(sessionFactory.currentSession.connection())
        println conn.rows('SELECT * FROM INFORMATION_SCHEMA.TABLES')
        println conn.rows('SELECT SEX FROM MEMBER')
    }
    def destroy = {
    }
}

4.期待通りの結果。SEXカラムの型がgetIdメソッドの戻り値と一致、共にINTEGER型。値はWOMANの2

| Loading Grails 2.1.1
| Configuring classpath.
| Environment set to development.....
| Packaging Grails application....
| Running Grails application
==================================================================
            Application: sample-grails-ec-admin 0.1            
            ---------------------------------------            
  Environment: DEVELOPMENT
  Database configuration: 
    Hibernate DDL mode: create-drop
    URL: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000
    Driver: org.h2.Driver
    User: sa
==================================================================
[[TABLE_CATALOG:DEVDB, TABLE_SCHEMA:PUBLIC, TABLE_NAME:MEMBER, TABLE_TYPE:TABLE, STORAGE_TYPE:MEMORY, SQL:CREATE MEMORY TABLE PUBLIC.MEMBER(
    ID BIGINT DEFAULT (NEXT VALUE FOR PUBLIC.SYSTEM_SEQUENCE_02BEEBC1_0499_4CA9_AE69_566A56FEE7FA) NOT NULL NULL_TO_DEFAULT SEQUENCE PUBLIC.SYSTEM_SEQUENCE_02BEEBC1_0499_4CA9_AE69_566A56FEE7FA,
    VERSION BIGINT NOT NULL,
    ADDRESS1 VARCHAR(255) NOT NULL,
    ADDRESS2 VARCHAR(255),
    DATE_CREATED TIMESTAMP NOT NULL,
    FIRST_NAME VARCHAR(255) NOT NULL,
    LAST_NAME VARCHAR(255) NOT NULL,
    LAST_UPDATED TIMESTAMP NOT NULL,
    MAIL VARCHAR(255) NOT NULL,
    MEMO VARCHAR(255),
    PASSWORD VARCHAR(255) NOT NULL,
    PREFECTURES VARCHAR(255) NOT NULL,
    SEX INTEGER NOT NULL,
    TEL VARCHAR(255) NOT NULL,
    ZIP VARCHAR(255) NOT NULL
)
[[SEX:2]]

Grails GORM Domain作成・データ登録・確認

1.Domain作成

>grails create-domain-class jp.gr.java_conf.tezu.grails.ec.Member

| Loading Grails 2.1.1
| Configuring classpath.
| Environment set to development.....
| Created file grails-app/domain/jp/gr/java_conf/tezu/grails/ec/Member.groovy
| Created file test/unit/jp/gr/java_conf/tezu/grails/ec/MemberTests.groovy


2.Domainに属性を追加
dateCreatedとlastUpdatedはGrailsが登録・更新時に自動でタイムスタンプをセットする属性。詳細は 6 Object Relational Mapping (GORM) 2.2.0のAutomatic timestampingに書いてある

package jp.gr.java_conf.tezu.grails.ec

import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TupleConstructor

@ToString
//@EqualsAndHashCode
//@TupleConstructor
class Member {
    Date dateCreated // automatically set date/time when created
    Date lastUpdated // automatically set date/time when last updated

    String mail
    String firstName
    String lastName
    String password
    int sex;
    String tel
    String zip
    String prefectures
    String address1
    String address2
    String memo

    static constraints = {
        mail nullable:false,blank:false,unique:true
        firstName nullable:false,blank:false
        lastName nullable:false,blank:false
        password nullable:false,blank:false
        sex nullable:false
        tel nullable:false,blank:false
        zip nullable:false,blank:false
        prefectures nullable:false,blank:false
        address1 nullable:false,blank:false
        address2 nullable:true
        memo nullable:true
    }
}

@EqualsAndHashCodeと@TupleConstructorをコメントアウトしたのは、以下のエラーが発生したため
原因不明、、、

| Loading Grails 2.1.1
| Configuring classpath.
| Environment set to development.....
| Packaging Grails application....
| Running Grails application
grails-ec-admin load MockPersistenceContextInterceptor
| Error 2013-01-31 15:07:09,450 [localhost-startStop-1] ERROR pojo.BasicLazyInitializer  - Javassist Enhancement failed: jp.gr.java_conf.tezu.grails.ec.Member
Message: duplicate method: <init> in jp.gr.java_conf.tezu.grails.ec.Member_$$_javassist_0
    Line | Method
->>  514 | createClass3 in javassist.util.proxy.ProxyFactory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    491 | createClass2 in     ''
|    427 | createClass1 in     ''
|    399 | createClass  in     ''
|    334 | innerRun . . in java.util.concurrent.FutureTask$Sync
|    166 | run          in java.util.concurrent.FutureTask
|   1110 | runWorker .  in java.util.concurrent.ThreadPoolExecutor
|    603 | run          in java.util.concurrent.ThreadPoolExecutor$Worker
^    722 | run . . . .  in java.lang.Thread


3. 起動時に呼び出されるBootStrap.groovyでデータを登録

import jp.gr.java_conf.tezu.grails.ec.Member

class BootStrap {

    def init = { servletContext ->
        if (Member.count() != 0) {
            Member.getAll().each { entity ->
                entity.delete()
            }
        }
        def entity = new Member(mail:"xxxxx@gmail.com",firstName:"Taro",lastName:"Grails",password:"password",sex:1,tel:"0611112222",zip:"1008924",prefectures:"東京都",address1:"千代田区永田町1-10-1")
        if (!entity.save(flush:true)) {
            entity.errors.each { println it }
        }
    }
    def destroy = {
    }
}


4.確認用にGrails Plugin: Console PluginをInstall。起動後にConsoleControllerを選択
f:id:tezu35:20130131162136j:plain

jp.gr.java_conf.tezu.grails.ec.Member.list()

を入力して実行、右側にBootStrap.groovyで登録したデータを表示
f:id:tezu35:20130131162241j:plain

要求を仕様化する技術・表現する技術と「派生開発」を成功させるプロセス改善の技術と極意

こんなことに困っていた時に助けてくれた本です。内容がちょっと冗長的ですが、、

  • 要求・要件・仕様・設計とか現場毎に意味が違うような
  • この要件ってどの設計書・プログラムで実現してるのか分からん
  • 何でこんな仕様になったんだろう?分からんから直せない

内容がかぶってるので、どちらか一冊あれば良いかな
改修案件が多いなら派生開発がオススメです

[改訂第2版] [入門+実践]要求を仕様化する技術・表現する技術 -仕様が書けていますか?

[改訂第2版] [入門+実践]要求を仕様化する技術・表現する技術 -仕様が書けていますか?

「派生開発」を成功させるプロセス改善の技術と極意

「派生開発」を成功させるプロセス改善の技術と極意

資料作成が苦手な同僚に貸したりしてますが、なかなか返さないので買えよと思いますね

Grails Platform UI Install

Grails Plugin: Plugin Platform UIをインストール

index.gspを3 Getting Started 1.0.RC2のコードに差し替えてみた

これが
f:id:tezu35:20130130152619j:plain

こんな感じに。カッコ良いです!
f:id:tezu35:20130130174217j:plain

欲を言えば、generate-allコマンドやgenerate-viewsコマンドで出力するgspファイルもこのUI tagで出力して欲しい