Goalist Developers Blog

SQLAlchemyでsetattrしたのにupdateされない

こんにちは ゴーリスト開発のモリツグです

最近ちょっとずつPythonを触り始めたひよっこです。
Python3.6でSQLAlchemyを使っていて何故かupdateが行われない現象に悩まされたので、原因と対処法をメモしておこうと思います。

ぶちあたった問題

sessionの取得やcommit flush closeあたりは適切に行われているものとして省略します。 あとPythonなのにキャメル記法なのは一旦みなかったことにしてください。

・・・(sessionの取得)・・・

# 更新したいレコードを取得
dbAccount = session.query(Account) 
    .filter(Account.id == account.id) 
    .first()

# 更新したい値を持っているaccountからdbAccount へ値をコピーして反映
for key, value in account.__dict__.items():
    if callable(value) == False: # 関数は省く
        setattr(dbAccount, key, value)

・・・(commit flush closeの処理)・・・

上記のようなソースコードを書いた場合、デバッガ上ではdbAccount の値が更新されているのに、DB上の値は更新されません。
試行錯誤した結果、setattrのvalueをちゃんとキャストしてやるとDB上の値も更新されました。

# 更新したい値を持っているaccountからdbAccount へ値をコピーして反映
for key, value in account.__dict__.items():
    if callable(value) == False: # 関数は省く
        # setattr(dbAccount, key, value) # valueの型を判定してキャスト
        if isinstance(value, int):
            setattr(updateEntity, key, int(value))
        elif isinstance(value, str):
            setattr(updateEntity, key, str(value))
    ・・・(それ以外の型の処理)・・・

何故こんなことになっているのか、詳しい理由は不明ですが、きっと何か深淵なる理由があるのだと思います。

Observableでクリックイベントを制御してドロップダウンメニューを作ってみる【Angular】

こんにちは。ゴーリスト開発の飯尾です。
AngularでWebアプリを作ったりしています。
世の賢人によるイルなコンポーネントだと微妙に機能が多すぎたり足りなかったりで
結局自作のワックコンポーネント生産したりしますよね。

作りたいもの

  • Airbnb一休の検索条件指定部分みたいなドロップダウンメニュー
  • 内側クリックで閉じず、外側クリックで閉じる
  • 一画面でひとつだけ開く

イメージとしてはこんなやつです。

f:id:y-iio:20180109180913g:plain

参考にしたもの

基本的にはこれパクっ参考にしましたが
ここのところがちょっとな〜だったので書き換えました。

@HostListener('click', ['$event']) onClick(event: Event) {
    if (!this.hideOnClick) {
        event.stopPropagation();
    }
}

変えたいポイント

その1

ドロップダウンを開いている時のみクリックイベントを拾いたい(@HostListenerでイベント登録するとリムーブできない)

github.com

その2

iOSだとdocumentをルート要素としてクリックイベントを登録しても拾ってくれない

qiita.com

解決法を考える

ドロップダウンを開いている時のみクリックイベントを拾いたい 問題

Observableでクリックイベントを制御する

qiita.com

// ドロップダウン開いてる時
const stream = Observable.fromEvent(document, 'click').subsucribe(() => {
  console.log('clicked!');
});

// 閉じたら購読をやめる
stream.unsubscribe();

iOSだとdocumentをルート要素としてクリックイベントを登録しても拾ってくれない 問題

Observable.fromEvent(document, 'touchend')ならOK

そうしてできたもの

import {
  ChangeDetectorRef, Component, ElementRef, HostBinding, Injectable, OnDestroy, OnInit, ViewEncapsulation
} from '@angular/core';
import { Observable, Subscriber } from 'rxjs/Rx';

@Injectable()
export class DropdownRegistry {
  private dropdownMenuComponents: any[] = [];

  constructor() { }

  public add(dropdownMenu: DropdownMenuComponent) {
    this.dropdownMenuComponents.push(dropdownMenu);
  }

  public remove(dropdownMenu: DropdownMenuComponent) {
    this.dropdownMenuComponents.slice(this.dropdownMenuComponents.indexOf(dropdownMenu), 1);
  }

  public hideAllExcept(dropdownMenu: DropdownMenuComponent) {
    this.dropdownMenuComponents.forEach((component) => {
      if (component !== dropdownMenu) {
        component.hide();
      }
    });
  }
}

@Component({
  selector: 'app-dropdown-menu',
  template: `<ng-content></ng-content>`,
  encapsulation: ViewEncapsulation.None // ここはカプセル化しない
})
export class DropdownMenuComponent implements OnInit, OnDestroy {
  @HostBinding('class.is-visible') isVisible: boolean = false;

  private clickEventStream: any; // Observable<Event>とかObservable<any>だと警告出る
  private subscription: Subscriber<any>;

  constructor(
    private changeDetectionRef: ChangeDetectorRef,
    private dropdownRegistry: DropdownRegistry,
    private elementRef: ElementRef,
  ) {
    this.dropdownRegistry.add(this);
  }

  ngOnInit() {
    // iOSだとボタンとかリンクの要素以外はタッチしてもクリックイベントとしてみなされない
    this.clickEventStream = Observable.merge(Observable.fromEvent(document, 'click'), Observable.fromEvent(document, 'touchend'))
      .catch(e => Observable.throw(e));
  }

  ngOnDestroy() {
    this.dropdownRegistry.remove(this);
  }

  public toggle(event: Event): void {
    if (this.isVisible) {
      this.hide();
    } else {
      this.show(event);
    }
  }

  public hide(): void {
    this.isVisible = false;
    if (this.subscription && !this.subscription.closed) { // stream流れてるなら止める
      this.subscription.unsubscribe();
    }
    this.changeDetectionRef.markForCheck();
  }

  public show(event: Event): void {
    event.stopPropagation();
    this.hideAll();
    this.isVisible = true;
    this.subscription = this.clickEventStream.subscribe((clickEvent: Event) => { // 外側クリック時に閉じる
      clickEvent.stopPropagation();
      if (this.isVisible && !this.elementRef.nativeElement.contains(clickEvent.target)) {
        this.hide();
      }
    });
  }

  private hideAll(): void {
    this.dropdownRegistry.hideAllExcept(this);
  }

}

あとはドロップダウン表示用のトグルボタンとCSSをいいかんじにする
いいかんじにする

こんな感じで動いているよ

f:id:y-iio:20180109181027g:plain

おわりに

もっとドープな書き方を教えてくれるマイメンを募集しています!!

テンソルフローの第一歩、環境構築 (Mac)

こんにちは、ゴーリストのチナパです。 現在の一番人気な機械学習ライブラリがグーグルのテンソルフローです。ここではテンソルフローの環境を作る方法を紹介します。まずは「テンソルとは何か?」についてお話しします。 f:id:c-pattamada:20180104130155p:plain

テンソルとは何か?

テンソルは数学でよく使われるベクターに似ています。それはつまり、テンソルは数字的に情報を表す為の道具です。仮想的な空間で等級と方向の組み合わせで情報を表しています。例えば、

[3 2]

と言うテンソルは「西側3歩、北側2歩」のような二次元空間で場所を表したり出来ます。

ただし、本当の力はこの方向の数を増やしたことによって、[力、魔力、速度、HP] などの「方向」でキャラクターでも表したりすることです。現実的な使い方を想像しましょう。「プラス性」と「マイナス性」を見つける為の便利な方向 [嬉しさ、ワクワク性、モティベーション] と [不満性、怒り、悲しみ]の仮想的な方向で以下の風にツイッターのポストを理解することも出来ます。

f:id:c-pattamada:20180104113222p:plain

もちろん、これは簡単にする為の軸を選んでいるんです。実際にパソコンがどんな方向や軸が使っているは人間にはもうちょっと分かりにくいでしょう。 自分よりまともな説明ができる人がいるんですが、リンクします。
(日本語版) テンソルとは何か? - YouTube (数学的な説明)

(英語版) What's a Tensor? - YouTube

環境構築

では、少しテンソルについて話しましたが、そろそろ環境を作りましょう。自分はマック使っているので、マックのPythonインストールのやり方を紹介します。

まずは、必要なもののダウンロードです。マックのターミナルを開いて、

sudo easy_install pip
pip install --upgrade virtualenv

を入力します。sudo なのでパスコードが必要です。

それから、この仮想環境を立ち上げてテンソルフローを使う為のディレクトリを作りましょう。例えば、
mkdir ~/tensorflow

そしてこのディレクトリで仮想環境を作りましょう
virtualenv --system-site-packages -p python3 ~/tensorflow

f:id:c-pattamada:20180104115234p:plain

(python 2を使いたい場合には virtualenv --system-site-packages ~/tensorflow)
出来ましたら、source ~/tensorflow/bin/activateで発動出来ます。うまく行きました場合、
(tensorflow)[パソコン名]$_
見たいなものが見えます。

ここで、また

easy_install -U pip
pip3 install --upgrade tensorflow

(また、python 2.7の場合は pip install --upgrade tensorflowです) で必要なものをダウンロードし、準備オッケーです。

パイソンを起動し、テンソルフローをimportしましょう
python
import tensorflow as tf

うまく行きましたら、いかの画像のように見えます。

試して見ましょう、

c = tf.constant([3, 2])
c

f:id:c-pattamada:20180104120454p:plain このような結果が出てくれば、バッチリです!
様々なインストールのやり方がこちらです。 

Installing TensorFlow  |  TensorFlow (英語)

iOS11になって変わったAppStoreまとめ

こんちは。渡部です。

f:id:watabe1028:20171222193758j:plain

この季節の「気づいたら指先が切れてた」現象をなんとかしたいです。はい。

今回はiOS11になって変わったことAppStore編を思いつく限り書いていきます。
ご参考までに。
 
 

1.アイコン

 アイコンが変わってます。
 筆者は訳あってiOS10を保ってます。
 (画像サイズが違うのは勘弁)

 iOS10
f:id:watabe1028:20171222194229p:plain
 
 iOS11
f:id:watabe1028:20171222194241j:plain
 
 

2.トップセールスランキングが削除

 インストール基準の一つがなくなるのは
 ゲーム系開発会社にはかなりの痛手かと。
 なのでこれからは流入経路は広告か
 検索からのインストールに偏っていきそうです。
 
 iOS10
f:id:watabe1028:20171227103502j:plain
 
 iOS11
f:id:watabe1028:20171227103518j:plain

 
 

3.タブが「Today」「ゲーム」「App」に

 2ともかぶるんですが「見つけやすい」ようにリニューアルされてると思います。
 ランキングは勝手に入ってくる情報ですが
 検索は目的のアプリを探す行為です。
 なので見つけやすさ、ファーストオンボーディングが重要になってくるかと。
 
f:id:watabe1028:20171227103049j:plain

 
 

4.ストアのアプリ一覧で横画面が可能に、スクショの枚数は3枚に

 今までは検索後の一覧画面では2枚のスクショが表示されてましたが
 iOS11からは3枚表示されます。
 また1枚の横画像の設定も可能になりました。
 
 iOS10
f:id:watabe1028:20171227103157p:plain
 
 iOS11
f:id:watabe1028:20171227103219p:plain

 
 

5.コメントへの返信機能

 レビューに対して返信できるようになりました。
 CXという言葉が流行り始めているように
 これからはアプリもカスタマーへのサポートが大事になっていきます。
 また、レビューをリセットすることもできます。
 ASO的にはレビューの件数や星の数が非常に大事になってくるので
 レビューリセットは考えものですね。

 
 

所感

重複しますがストアが全体的に「見つけやすく」なるようにリニューアルされた気がします。
またレビューの返信機能など、アプリをサービス化し、サポートもしっかりやれよ!的な
メッセージのようなものも感じます。
改善が停止されてるアプリが溢れてますからね。。。
 
アプリのインストール基準でもあるレビュー件数と星の数がさらに重要度が増した気がします。
ランキングよりも評価やサポートがユーザーのインストール基準になっていく傾向でしょうか。
 
アプリの露出からサポートまで、UXの定義がまた広くなりそうです。
 
 

Selenium2を3に上げてみる

こんにちは ゴーリスト開発のモリツグです

そろそろSelenium2から危険な香りがするので、3に上げることしました。
ChromeのヘッドレスがEC2を利用してクローリングする時にすごい便利ですね。
今回はJavaでSelenium3 WebDriverを動かしてみたいと思います。

手順

公式サイトのダウンロードからJavaのライブラリをダウンロードする
・EclipseやInteliJなど好みのIDEでライブラリ参照するように設定する
ドライバダウンロードページから環境にあったchromeドライバを落としてくる
・ソースコードを書いて確かめる

今回落としてきたSeleniumのバージョンは3.8.1でした、知らない間に4になりそうな勢いです。
注意点としてはchromeブラウザのバージョンにドライバのバージョンが対応しているかどうかを確認することです。
「同じソースコードなのにある日突然動かなくなった!」という場合は、だいたいChromeが更新されてバージョンが上がったせいで、ドライバが対応できなくなったパターンが多いです。

Chromeは公式サイトからは最新版しか落とせないので、Chromeが最新になっちゃったけど、それに対応した最新のドライバが出ていない状況というのは起こりえます。
「今すぐに動かさないとやばい!古いバージョンのChromeが欲しい!」という場合は、以下のサイトから落とせます。古くした後は忘れずに自動更新はoffにしときましょう。

www.slimjet.com

では最後にver2と全く同じソースコードで動くのか確認します

public void exec() throws Throwable {
    System.setProperty("webdriver.chrome.driver", "path to your chrome driver");
    WebDriver driver = new ChromeDriver();
    // ヘッドレスの場合
//     ChromeOptions chromeOptions = new ChromeOptions();
//     chromeOptions.addArguments("--headless", "window-size=1280,1024"); // xvfbとか一切無しでdislayサイズも指定できちゃう
//     WebDriver driver =  ChromeDriver(chromeOptions);
    

    driver.navigate().to("https://www.google.co.jp/");

    WebElement input = driver.findElement(By.cssSelector("#lst-ib"));
    input.sendKeys("goalist");
    input.sendKeys(Keys.chord(Keys.ENTER));

    ExpectedCondition<List<WebElement>> waitFunc = new ExpectedCondition<List<WebElement>>() {
        public List<WebElement> apply(WebDriver driver) {
            List<WebElement> curTitleEle = driver.findElements(By.cssSelector("#search .rc .r a"));
            if (curTitleEle == null || curTitleEle.size() == 0) {
                return null; // NoSuchElementExceptionかreturn nullしてるあいだは続行
            }
            return curTitleEle;
        }
    };

    Wait<WebDriver> wait = new WebDriverWait(driver, 15);
    try {
        System.out.println("start wait");
        List<WebElement> result = wait.until(waitFunc);
        result.get(0).click();
        System.out.println("end wait");
    } catch (TimeoutException e) {
        e.printStackTrace();
        System.out.println("time out");
    }
}

まとめ

Chromeを使う限りではselenium2と全く同じソースで動くようです。
今すぐ3に上げましょう。

Angularで転職用ウェブアプリのフロント開発を開始!

f:id:TinkerJack:20171215191005p:plain皆さん、

お疲れ様です! コードで遊ぶのが好きなティンカーです! 最近コトリンの勉強をしつつ充実してる感もありますけども、やっぱりウェブでの開発もしたいと思って(現在本業)、Angularで簡単なアプリを作ってみようかと思います!

本日のグロサリー:

  • Angularとは。

  • 環境構築。

  • アプリ作成!

Angularとは

AngularはJavascriptにコンパイルされる言語でウェブアプリの開発をさせるフロントエンドフレイムワークです!

まずは環境設定から始めたいかと思っています!

環境構築

こちらのブログの前提はMac OS何ですが、Windowsの方は同僚の飯尾さんが作ってくれたWindows用の環境構築の記事を読んでください!

developers.goalist.co.jp

npmとnodejsが必要になるので、そこから始めます! ですが、先にHomebrewと言うMac OS専用のパッケージマネージャーを使ってインストールしますので、 まずは下記の用にhomebrewのインストールをしましょう!(詳しくは下記のリンクで)

qiita.com

次は下記のコマンドでNodeJSとNPMのインストールをしましょう!

f:id:TinkerJack:20171215163159p:plain

これでよし! 後はangular-cliのインストールをすれば、、、

f:id:TinkerJack:20171215163348p:plain

オーケー! これでAngularのアプリを生成するための環境設定は完了しました!

アプリ作成!

いよいよですね!

まずはAngularのアプリのgenerateをしましょう!

f:id:TinkerJack:20171215163613p:plain

下記の通り色んなディレクトリーが自動生成されます!

f:id:TinkerJack:20171215163808p:plain

"Project 'JobNetworker' successfully created." と言うメッセージが見れたら、プロジェクトが無事作成されたら合図と見なします!

次はサーバーを起動するコマンドを打ちます!

f:id:TinkerJack:20171215164246p:plain

よーし!次はようやく、localhost:4200に遷移すると、デフォページとしてAngularの正式のチュートリアルが反映されると無事アプリ作成ができました!!

f:id:TinkerJack:20171215165648p:plain

おめでとうございます!

次からここにある物を消し、ゼロから転職サイトアプリを作るので、楽しみです!!

次回の用意としては、お好きなIDEをインストールしてください!

現在使っているIDE / エディターに関しては、ウェブストームを使用して、開発しています。

www.jetbrains.com

ただし、データの使用もすると思うので、いずれかバックエンドの開発もするつもりです。 なのでIntelliJ IDEAの購入をお勧めしますが、お好きなテキストエディタやIDEでももちろんオーケーです!

www.jetbrains.com

本日の記事の内容は以上となります!

次回は本格的な転職サービスの開発を開始します!

来週までお元気で!

See you next week!

P.S: もしかたら、いやもしかしたらの話何ですけども、まさかのkotlinを使用したこのアプリのバックエンド開発も。。。?

次回のお楽しみにー

ゴーリストエンジニア
イムラーン

Angularで WARNING in Circular dependency detected だよ〜ドラえも〜〜ん

はい。
ゴーリスト開発の飯尾です。

タイトルの通りなんですけど
別に解決してないんですけど

Angular CLI を1.1.3から1.5.5にアップデートしたら
アラ〜〜〜

WARNING in Circular dependency detected:
src/app/services/auth.service.ts -> src/app/services/request.service.ts -> src/app/services/auth.service.ts

WARNING in Circular dependency detected:
src/app/services/request.service.ts -> src/app/services/auth.service.ts -> src/app/services/request.service.ts

とはいえ、コンパイル自体は通るしプロダクション用ビルドも普通にできる……

どうする???

github.com

「Angular CLI 1.3.0から起こる」
「showCircularDependenciesをfalseにして見えなくすればOK」

そんな……
うるせーから黙らせる的な発想でいいの……

いったん、循環参照になっちゃうメソッドを別サービスに出してそれぞれDIする

警告オフにして他の問題に気づかないとかちょっと避けたいので……

社内Angularの雄にきいてみる

f:id:y-iio:20171215182535p:plain

ウオ〜〜〜
そういう!ことなのか!!?