rails console で group by の結果を確認

やりかったことはemailが重複しているレコードの件数をしらべたかっただけ。 

実行されているSQLが期待通りだったのでこれでいいのかと思ってたけど、全然期待した結果にならない。。

$ User.select('email,count(*)').group('email')
> User.select('email,count(*)').group('email')
User Load (0.3ms)  SELECT email,count(*) FROM "users" GROUP BY "users"."email"
[#<User:0x007fc90f100ce0 id: nil, email: "test@test.com">,
#<User:0x007fc90f0f80b8 id: nil, email: "test2@test.com">,
・・・

結果、こうするらしい

$ User.group(:email).count
> User.group(:email).count
   (0.3ms)  SELECT COUNT(*) AS count_all, "users"."email" AS users_email FROM "users" GROUP BY "users"."email"
{"test@test.com"=>1,
 "test2@test.com"=>1,
 ・・・

慣れかな。以上です

【ionic2】ionicPageで各画面をurlに対応させる

はじめに

ionic1のルーティングまわりはui-routerで検索すれば色々出て来たけどionic2で何で検索すればよいのかまだよくわかってないけどとりあえずやり方はわかったのでメモしておく。デバッグのときとかはブラウザでリロードしたいし。あれ、けど目的はそれくらい。。?

とりあえずHome → Page1 → Page2 みたいな感じで画面遷移できるように。
それぞれ /#/home → /#/page1 → /#/page2 とURLもつようしてみる。 

app/app.component.ts

・・・
import { HomePage } from '../pages/home/home';
@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  //rootPage:any = HomePage;                                                                                                                                                                                       
  rootPage:any = 'home'; // ★ ココをあとでionicPageで指定する名前に変更                                                                                                                                           
                                                                                                                                                                                                                   
  ・・・
}

app/app.module.ts

・・・
@NgModule({
  declarations: [
    MyApp
    //HomePage                                                                                                                                                                                                     
  ],

  ・・・

  entryComponents: [
    MyApp
    //HomePage                                                                                                                                                                                                     
  ],

  ・・・

以降、各ページ

pages/home/home.module.ts

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';

import { HomePage } from '../home/home';

@NgModule({
  declarations: [
    HomePage
  ],
  imports: [
    IonicPageModule.forChild(HomePage)
  ],
  entryComponents: [
    HomePage
  ]
})
export class HomePageModule {}

pages/home/home.ts

import { Component } from '@angular/core';
import { NavController, IonicPage } from 'ionic-angular';

import { Page1Page } from '../page1/page1';

@IonicPage({
  name: 'home'
})
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController) {
  }

  goPage1() {
    this.navCtrl.push('page1');
  }
}

page1、page2も同じように作ればNavControllerにpushするとurlも書き換わることが確認できた。以上です。

【ionic2】画面遷移のアニメーションを変更する

やりたかったこととしては画面の遷移の際のアニメーションでandroidでもiosみたいに左から右にスライドするようにしたいとういこと。
本来はプラットフォームごとに奨励されているアニメーションを使うべきだとは思うのだがやっぱりiosをベースで考えている人だとandroidでもそのように実装してほしいというのはよくあるのかと。

アプリ全体で設定する場合
app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';

・・・

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    SignupPage
  ],
  imports: [
    BrowserModule,
    // ★ ここで設定
    IonicModule.forRoot(MyApp, {
      pageTransition: 'ios-transition'                                                                                                                                                                             
    })
  ],

  ・・・

})
export class AppModule {}

画面ごとに設定したい場合
各pagesのコンポーネント

this.navCtrl.push(MyPage, null, {
  animation: 'ios-transition'
});

app.module.ts で設定するやり方は他にも色々設定できるみたいなので覚えた方がよさそう。
http://ionicframework.com/docs/api/config/Config/

以上です

【ionic2】無限スクロールの使い方

なかなか手をだせにずにいたionic2を次の案件では使えるように準備中。とりあえずionic1でできてたことをionic2でもできるようになることが当面の目標。今回はapiから取得したjsonからリスト表示で、無限スクロールを実装してみる。

blankでプロジェクト作成

$ ionic start test blank

まずはhttpをつかえるように。

app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';

・・・

import { HttpModule } from '@angular/http'; ## ★ これを追加

@NgModule({

    ・・・ 

    imports: [
        BrowserModule,
        IonicModule.forRoot(MyApp),
        HttpModule ## ★ これを追加
    ],

    ・・・ 

})
export class AppModule {}

つづいてコントローラ?を実装

src/pages/home/home.ts

import { Component } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
c})
export class HomePage {

  page = 1;
  items = [];
  completed = false;

  constructor(public http: Http) {
    this.getUsers().subscribe(data => {
      if (0 < data.users.length) {
        this.items = this.items.concat(data.users);
        this.page++;
      } else {
        this.completed = true;
      }
    });
  }

  doInfinite(infiniteScroll) {
    this.getUsers().subscribe(data => {
      if (0 < data.users.length) {
        this.items = this.items.concat(data.users);
        this.page++;
      } else {
        this.completed = true;
      }
      infiniteScroll.complete();
    });
  }

  getUsers() {
    return this.http
      .get('http://localhost:3000/users?page=' + this.page)
      .map(res => res.json());
  }

}

さいごにテンプレートを実装

src/pages/home/home.html

・・・

<ion-content padding>
  <ion-list>
    <ion-item *ngFor="let item of items">
      {{ item.name }}
    </ion-item>
  </ion-list>
  <ion-infinite-scroll (ionInfinite)="doInfinite($event)" *ngIf="completed">
    <ion-infinite-scroll-content></ion-infinite-scroll-content>
  </ion-infinite-scroll>
</ion-content>

typescriptとかrxjsとかまだ全然わかってないけどとりあえずこれでできた。以上です。

rails5のapiモードを試した

はじめに

勉強もかねて簡単なapirailsで実装してみる。やりたいことは以下

・ローカルPCで動作させてみる
apiモード使ってjsonを返す
・dbからデータを取得する
・ページングに対応する

ローカルPCで動作させてみる

まずは rbenv を使って ruby環境でrailsをインストールするところまでやる。

http://kimagureneet.hatenablog.com/entry/2017/09/27/143151
基本的にはここに書いた通りだが
・今回はrails5を使いたいのでバージョンの固定はしない
apiモードを使いたいのでプロジェクト作成のコマンドに --api をつける

$ bundle exec rails new myapp --api
apiモードを使ってjsonを返す

とりあえずユーザの一覧を返すAPIを作ってみる。

routes に追加

Rails.application.routes.draw do
  get '/users', to: 'users#index'
end

routes の確認

$ ./bin/rails routes
Prefix Verb URI Pattern      Controller#Action
 users GET  /users(.:format) users#index

users コントローラの作成

$ ./bin/rails g controller users

controllers/users_controller.rb が作成されるのでjsonをかえすコードを追加

class UsersController < ApplicationController
  def index
    render json:{ users:[{id:1, name:'test1'},{id:2, name:'test2'}] }
  end
end

ここまで作ったら http://localhost:3000/users にアクセスすると json が返されることを確認できた。

{"users":[{"id":1,"name":"test1"},{"id":2,"name":"test2"}]}
dbからデータを取得する

まずはdbを作成

$ ./bin/rails db:create

つづいて model の作成

$ ./bin/rails g model user

model を作成するとmigrationファイルも作成されるのでここにカラムを追加する。
db/migrate/20171009182615_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|

      t.string :email
      t.string :name

      t.timestamps
    end
  end
end

migrate を実行

$ ./bin/rails db:migrate

ここまでにテーブルが作成されるのでコマンドラインからデータを登録して確認してみる

$ ./bin/rails console
# 登録
> user = User.new
> user.name = "test1"
> user.email = "test1@test.com"
> user.save

# 確認
> User.all

データが登録されたことを確認できたので、APIとしてもusersデータをかえすように修正
contorollers/users_controller.rb

class UsersController < ApplicationController
  def index
    render json:{ users:User.all }
  end
end
ページングに対応する

kaminari という gem が有名ぽいので使ってみる。

なにはともあれ kaminari をインストール

Gemfile

・・・
gem 'kaminari'                                                                                                                                                                                                     
・・・

以下でインストールと設定を行う

# インストール
$ bundle install

$ vi config/initializers/kaminari_config.rb
Kaminari.configure do |config|
  config.default_per_page = 2 ## デフォルト表示数を定義
・・・

controllers/users_controller.rb

class UsersController < ApplicationController
  def index
    users = User.all.page(params[:page])
    total = User.all.page.total_pages

    render json:{ total:total, users:users }
  end
end

http://localhost:3000/users

{"total":3, "users":[{"id":1,"name":"test1"},{"id":2,"name":"test2"}]}

http://localhost:3000/users?page=2

{"total":3, "users":[{"id":3,"name":"test3"}]}

とりあえずやりたいことはできた。以上です。

【angularjs】セレクトボックス(プルダウン)の使い方メモ

angularjs使うときはまたやりそうなのでメモしておく

まず、配列はどこかに一箇所に定義しておく

angular.module('myApp')
  .value('define', {
    'area': {
      1: '北海道',
      2: '東北',
      3: '関東',
      ・・・
    },
  });

テンプレートから参照できるようにコントローラで $scopeにいれる

angular.module('myApp')
  .controller('SampleCtrl', function(define) {
    $scope.areas = define.area;
  });

テンプレートで select box を作る

<select ng-model="user.area" ng-options="k as v for (k, v) in areas"></select>

これでもいける

<select ng-model="user.area">
  <option value="">選択して下さい</option>
  <option ng-repeat="(k, v) in areas" value="{{k}}">{{v}}</option>
</select>

以上です

【ionic】angular-messageで入力フォームのバリデーションとエラーメッセージを実装する

はじめに

今回やりたかったことは入力フォームにバリデーション機能を実装して、不備があった場合は送信ボタンを押せなくして不備の内容を画面に表示するということ。今回は angular-messages というライブラリを使った。

angular-messagesのインストール

$ bower install angular-messages#1.5.3

index.html

<script src="lib/angular-messages/angular-messages.js"></script>

実装する項目としては以下のようなかんじ。
・名前
・名前カナ(カタカナのみ)
・生年月日(正しい日付のみ)
・郵便番号(数字7桁のみ)

実装

テンプレート

<form name="form novalidate>

  <label>名前</label>
  <input type="text" name="name" ng-model="user.name" ng-required="true" ng-model-options="{updateOn: 'blur'}" />

  <label>名前カナ</label>
  <input type="text" name="kana" ng-model="user.kana" ng-required="true" ng-pattern="/^[ァ-ン\s]+$/" ng-model-options="{updateOn: 'blur'}" />

  <label>生年月日</label>
  <input type="date" name="birthday" ng-model="user.birthday" ng-required="true" />

  <label>郵便番号</label>
  <input type="tel" name="zipcode" ng-model="user.zipcode" ng-required="true" ng-pattern="/^[0-9]{7}$/" maxlength="7" />

  <!-- エラーメッセージ -->
  <div>
    <span ng-messages="form.kana.$error" ng-show="form.kana.$dirty">
      <p ng-message="pattern">名前カナはカタカナで入力してください</p>
    </span>
    <span ng-messages="form.birthday.$error" ng-show="form.birthday.$dirty">
      <p ng-message="date">生年月日に正しい日付を入力してください</p>
    </span>                                                                                                                                                                                                        
    <span ng-messages="form.zipcode.$error" ng-show="form.zipcode.$dirty">
      <p ng-message="pattern">郵便番号は数字7桁で入力してください</p>
    </span>
  </div>

  <!-- 送信ボタン -->
  <buton class="btn" ng-click="form.$valid && save()" ng-class="{btn_invalid: !form.$valid, btn_valid: form.$valid}">送信</button>

</form>

以上です