P学習帳

書いておぼえるブログ

エンターキーが押された時のページ遷移を防ぎたい

状況

任意のテキストボックスに何か文字列を入力していて、入力を確定するつもりでエンターを押したら、意図せず変なところにジャンプしてしまうのを防ぎたい。

コード  

$('input[type="text"]').on('keypress', function(e) {
  if( e.which == 13 ) {
     e.preventDefault();  
   }
});

DEMO

codepen.io

thisを関数に渡したい

状況  

jsでthisを関数の引数として渡したい。 しかしそのまま引数の名前をthisとするとエラーになる。予約語だから引数の名前にはできないのだ。  

かわりに_thisとすればよい。  

コード    

$('input[type="text"]').on('click', '#mandatory', function() {
   do_something(this);
}

function do_something(_this) {
  // なんかの処理
}

DEMO

codepen.io

【ActiveRecord】3つ以上のテーブルをJOINしたい

状況

3つ以上のテーブルをJOINしたい。

想定するモデル

記事、段落、文といったモデルを考えてみる。記事は複数の段落を含む。段落は複数の文を含む。以下のモデルがあるものとする。   

# articles
has_many :paragraphs

# paragraphs
belongs_to :article
has_many :sentences
 
# sentences   
belongs_to :paragraph

 

書き方

A) 特定のsentenceが所属するarticleを取得する(孫から先祖へ)。

Sentence.eager_load(paragraph: :article).where(sentences: {id: ?})

B) 特定のarticleに含まれるsentencesを取得する(先祖から孫へ)。

Article.eager_load(paragraphs: :sentences)
       .where(articles: { id: ? })

whereにはテーブル名につづけてハッシュでカラムと値を指定する。テーブル名を渡さないとエラーになる。

OK

.where( sentences: { id: ? })

NG

.where( id: ? )

どのテーブルのidなのかがわからないからダメ。

SQLなら

上記コードから以下のクエリが生成される。  

A)

SELECT * 
FROM sentences 
  LEFT OUTER JOIN paragraphs
    ON paragraphs.id = sentences.paragraph_id
  LEFT OUTER JOIN articles
    ON paragraphs.article_id = articles.id
  WHERE sentence.id = ?

B)

SELECT * 
FROM articles 
  LEFT OUTER JOIN paragraphs
    ON articles.id = paragraphs.article_id
  LEFT OUTER JOIN sentences
    ON paragraphs.id = sentences.paragraph_id
  WHERE sentence.id = ?

モデル名、単数/複数?

複数形または単数形のどちらにするのかはモデルの関連付けに従う。
たとえば上記 B)の場合、Articleは複数のParagraphsをもつので、eager_loadの第一引数は複数形のparagraphsとする。同じように、paragraphsは複数のsentencesをもつので、第二引数も複数形のsentencesとする。   

もっとJOINしたい

たとえば記事の筆者も表示したくなったとする。そのためにauthorsモデルを追加でJOINしたい。このとき、任意の著者によるsentence、paragraph、articleは次のようにして取得できる。

Sentence.eager_load(paragraph: {article: :author})
.where(authors: {name: ?})

モデル名をハッシュでネストすればOK。  

(paragraph: {article: :author})

雑感

Railsガイドに複数モデルの関連付けの方法が紹介されている。読んでもわからなかったので、色々ググって3つ以上のテーブルをつなぐ記法を調べる必要があった。 

Active Record クエリインターフェイス | Rails ガイド

Active Recordの記法がわからない場合、生SQLを食わすという手段もある。

https://railsguides.jp/active_record_querying.html#sql%E3%81%A7%E6%A4%9C%E7%B4%A2%E3%81%99%E3%82%8B

find_by_sqlに生クエリを渡して実行するやり方についてメモした。

gijutsumemo.hatenadiary.jp

任意のディレクトリをパスに通す

useしたモジュールが見つからないとき次のエラーが出ます。

Can't locate App/Module.pm in @INC (...

エラーを解消するには、モジュールをパスに通してやればOKです。

パスに通す方法は複数あるようですが、今回はuse libを使いました。

ディレクトリ構成

.
├── App
│   ├── Tengsample
│   │   ├── Model
│   │   │   └── Schema.pm
│   │   └── Model.pm
│   └── teng_sample.pl

teng_sample.pl

こう書きます。

use lib '/Users/taro/App';

すると、teng_sample.plで次のようにモジュールをuseできます。

use Tengsample::Model; ## ./App/Tengsample/Model.pm

Test::Simpleを使ってみる

Test::Simpleを使ってテストを書きました。 自作モジュールがちゃんと動くかを確認します。

テスト対象は、映画のレビュー情報を管理するMovieモジュールです。

package Movie;

sub new {
    my ($class, %args) = @_;
    bless ({%args} => $class);
}

sub title {
    my $self = shift;

    return $self->{title};
}

1;

titleを返すメソッドのみがあります。

このメソッドが期待通りに使えることを確かめたいです。

テストを書きます。

    use Test::Simple tests => 1; #テストの数を書く
    use Movie;

    my $title = "Independence day";
    my $expected = $title;

    my $movie = Moview->new(
        title => $title,
    );

    # 引数1:式 引数2:テストの名前
    ok( $movie->title eq $expected, "title() get ---> $expected");

    # テストの終わりに書く
    done_testing();

はい、モジュールとテストが準備できました。

早速テストを実行してみます。

% perl movie_test.pl
# 1..1
# ok 1 - title() get --> Independence day

おめでとうございます。 オーケーです。

Perl - 2次元配列の生成とアクセス

プログラミングPerl Vol.1の同名セクションにあるサンプルコードを写経する。

#配列リファレンスのリストを配列に代入する
 @AoA = (
     [ "fred", "barney" ],
     [ "george", "jane", "elroy" ],
     [ "homer", "marge", "bart" ],
 );

 print $AoA[2][1]; # marge

 #配列リファレンスの配列へのリファレンスを作成する
 $ref_to_AoA = [
     [ "fred", "barney", "pebbles", "bamm bamm", "dino", ],
     [ "fred", "barney" ],
     [ "george", "jane", "elroy", "judy", ],
 ];

 print $ref_to_AoA->[2][3]; #elroy   

ううむ、配列をハードコーディングするのは大変だ。。

ファイル名グロブ演算子

カレントディレクトリにあるファイルを条件を指定して取得できるファイル名グロブ演算子の使い方メモ。

my @scripts = glob('*.pl');
for ( @scripts ) {
    print "$_\n";
}

@scriptに.plファイルが入る。
取得したファイルを実行したり、または何か処理を加えたりもできる。

while ( glob "*.pl" ) {
   perl $_;
}

(プログラミングPerl Vol.1 第3版 p98)