rails備忘録(mapとかfixtureなど)
railsの備忘録です。触ってて分かったこととか。
/config/application.rbはrails sのときに読まれる
railsは読み込みを早くするために、画面リロードでは読まれない設定があります。
/config/application.rbもそのひとつ。
deviseを入れてると、currrent_userという変数が使えます。あと、requestはユーザエージェントとかリファラの情報が入ってる。
ようこそ!<%= @user.email %> さん的に使える
mapを使った検索条件の記法
下記のように書くことで、commentsテーブルのcontent,name,email,site_urlカラムのsearchに入った文字列を含むレコードをすべて取得できる。こう書くことで、commentsテーブルのcontent,name,email,site_urlカラムのsearchに入った文字列を含むレコードをすべて取得できる。
test/fixtures/hoge.ymlのロード
予め、テストデータをhoge.ymlに書いておくと、データ壊れてもまたロードできて便利。でもdevelop環境のテーブルのデータ上書きされてしまうので注意。あと、主キーのidは1から書いていくこと。書かないとランダムな値が勝手に挿入されてテストデータとして使いモンにならない。
まとめ
学習のために作ってる本の販売サイト的なやつがあんまり詰まることなく、テーブルデータの抽出部分はなんとなく作れたのでやっぱRailsは使いやすいな印象です。
bookSearch/taskapp at master · tixture55/bookSearch · GitHub
railsのgemまとめ
railsの学習の家庭で、下記のgemをGemfileに追加しました。自分用の備忘録です。
- kaminari
- rails-footnotes
両方とも簡単に導入できるところがいいですね。
githubにこの2つのgemを盛り込んだ簡単な検索アプリを公開しました。
kaminariはいわずとしれたページネーション実装用のモジュールです。
実際のサービスではerbのCSSいじってもっと見栄えをよくしたいところ。下記ソースだけ(viewもすこしいじるけど)で3件ずつ表示させるようにできます。
rails-footnotesはデバッグ用モジュールです。
画面したの方に実行されたSQL、セッション、コントローラとアクション、読み込まれたjsやcssなどが表示できるリンク集が表示されます。cakeにもdebugToolというのがあったのですが、あれよりシンプルで使いやすいです。
まとめ
laravelやcakeよりシンプルでかつ細かくいろいろ設定できるrailsは癖があって初期段階でけっこう文法とかで苦戦しました。ActiveRecordもreadonlyかどうかやcastした上でupdateするかなど細かく方法を使い分けられるようなので、いろいろPHPフレームワークと違っていておもしろいですね。
参考サイト
ActiveRecord の attribute 更新方法まとめ - Qiita
Railsの値取得とrailsコマンドを使ったDB接続
Railsを使ったアプリのソースコードを読んでいて戸惑ったこと、理解したことの雑記です。
突然viewファイルに登場するみたことないコロン付きのメソッド、どこから来ているのか調べました。(下記ソースでいうところの:titleや:content)
具体的には
①のソースを追加したところエラーになってしまったので(突然:contentというわけわからんパラメータ書いたので当たり前だけど)、:titleがエラーにならない理由はなんなのか調べました。
DBのテーブルのカラム名と直接紐付いているのかなと思ったので、rails dbconsoleコマンドでテーブル定義を確認しました。
projectsテーブルのテーブル定義は
titleフィールドがありました。contentフィールドを追加すると、①のソースコードを追加した状態でもエラーがでなくなりました。テーブルのフィールドに直接Railsがアクセスしてることが分かりました。
Railsでのモデルの書き方
Railsでのモデルの書き方の学習の記録です。
今回はアソシエーションとか複雑なクエリを何回も書かなくて済むスコープの書き方です。
railsのhas_manyの書き方
上が一番分かりやすい例だと思います。Postの下にCommentがぶら下がっている1対多の定義です。
dependentの定義
下記例だと、Episodeの下にcommentsとtaggingsとtagsがぶら下がっているイメージである。
この場合、親に当たる投稿が削除されたら、コメントの扱いをどうするか、それを定義するのがdependentである。投稿が削除されたら、紐づくコメントも削除する場合は下記のように書く。
1の場合はComment::destroy()が毎回よばれるのに対し、2はdestroy()をスルーして1の場合はComment::destroy()が毎回よばれるのに対し、2はdestroy()をスルーして 削除するSQLを走らせる。
通常はdestroy()を使う
Railsのスコープ機能
モデルのスコープ機能とは、共通的に使うクエリをモデルのメソッドのように定義できる機能モデルのスコープ機能とは、共通的に使うクエリをモデルのメソッドのように定義できる機能 何度も複雑なSQLを何度も書かなくてよくなり、保守性が高まる。
上の定義をしたうえで
とすると、publishedカラムがtrueのPostのみを取得できる。
スコープ同士のマージ
scopeを組み合わせれば複雑なSQLロジックを分離して考えることができる。
他のモデルのスコープを利用する方法
これで内部結合postsテーブルと内部結合させるSQLが作れる。ロジックが分割されているので、仮にmodelクラスがもっと増えても、scopeの組み合わせでいろんなバリエーションのSQLを作ることができる。
参考サイト
ruby on rails4のおさらい(MVC)
railsのおさらいです。私の環境では、railsは4.1.1でした。
controllerのaction定義の仕方
またbefore_actionを指定することで、showやindexアクションの前に特定のアクションをフックできます。
privateキーワードを使う
rubyのprivateキーワードはJavaなどとは違い、親で指定したprivateなメソッドに子供クラスからアクセスできます。
Rails4のrequire,permit
rails4ではストロングパラメータというメソッドが追加されました。(require, permit)
requireを指定することで特定のキーを条件にフィルタをかけられます。またpermitを使えば取得したいレコードだけ取得できます。
viewのフォームの書き方の一例
※ @で始まる変数をインスタンス変数という。インスタンス変数は頭文字は小文字という規則がある。
- <%= @project.errors.messages[:title][0] %>で使われるエラーメッセージはmodelに書くことになる。
- <%= form_for @project do |f| %> のfは別にどんな名前でもいい。ここで使われている@projectはcontrollerのアクションで生成した変数、例えば、@project = Project.find(params[:id]) を参照している。
modelクラスの記述
上記のようにアソシエーションの指定やバリデーションルールを定義する。ActiveRecordのBaseクラスを継承しているのでORMが使える。
javascript雑記(scrollTopとかiterableとか)
javascript(jquery)を書いていて、いろいろ気になったところをまとめます。
Chromeで仕様変更になってたところ
普段Chromeしか使わないので、他のブラウザとの仕様の差とかあんまり意識してコーディングする機会ないのですが、他のブログ記事読んでて気になったので下記にまとめます。
$('body').scrollTopが効かなくなってたみたい
Chromeでは上記値は常に0を返します。(Chrome51.0で検証)
Firefoxと同じ仕様みたいです。つまり、$('body').scrollTopがきかなくなり、htmlタグを読むタイミングでscrollTopが効くようになってみたいです。
HTML CollectionとNodeListのイテレータサポートについて
Arrayはiterableかつ長さを持ちます。
古いChromeとかだと、イテレータが使えないので、下記のような処理が必要かと思います。
C#で非同期でダウンロードする処理を書く
C#で非同期処理を書く際の文法やルールをまとめてみました。非同期処理にはasync/awaitを使いますが、これが使えるようになったのはC#5.0からです。
同期処理でファイルをダウンロードする処理
using System.IO;
using System.Net; public static string ReadFromUrl(Uri url) { using (WebClient webClient = new WebClient()) { using (Stream stream = webClient.OpenRead(url)) { TextReader tr = new StreamReader(stream, Encoding.UTF8, true); string body = tr.ReadToEnd(); return body;
} } } public static void Download() { Uri url = new Uri("https://github.com/hoge/master/README.md"); string body = ReadFromUrl(url); Console.WriteLine(body); } |
StreamReaderで文字列として読み取ります。非同期に書き換えると、下記のようになります。
using System.IO; public static async Task<string> ReadFromUrlAsync(Uri url)
return body; public static async Task DownloadAsync() |
意外と非同期に書き換えるやり方は単純で「非同期だよ」と書いてやることがまずやることみたいです。それは前提として、非同期処理は呼び出し元から末端まで、「全て非同期メソッドで実装する必要がある」と言う事です。
非同期処理の挙動
非同期処理を行うメソッドはそれが実行中でもUI側は動かすことができます。例えば、非同期メソッドでwaitする処理が走っても、UI側まで待機になって固まることはないわけですね。
非同期処理を書く際のポイント
- メソッドの中で、awaitキーワードを使うためには、そのメソッド定義時にasyncキーワードを付けてやる必要があります。
- 同期させたい処理の戻り値がstringなら、それに合わせて非同期処理の戻り値はTask<string>にする必要がある。
- Task=非同期ではない。非同期処理ではないメソッドをTaskを使って書くこともできる。
- 非同期メソッドの戻り値は、Task型かTask<T>型かvoid型にしてやる必要がある。voidはほぼ使わない。
- 返されたTask<T>をawaitすると、目的の文字列が得られる。
awaitキーワードの効果は、「指定したTaskの完了を待つ」「そして、その結果を取り出す」です。
非同期処理の怖い所
非同期処理で扱うTaskはただの処理の集合体で、ポリシーとしては「書かれている処理が順番どおり実行できればOK」なので、どのスレッドが実行したかとかお構いなしなわけです。というかTaskはただの作業手順書なので、そもそもスレッドの存在など気にしていません。
なので、デッドロックやスレッドの実行順序するプログラムが別途必要となります。
デッドロックになるパターン
そもそもawaitとは「〜を待つ」という意味で、このキーワードが付いたメソッドは呼び出し元のメソッドの完了を待ってから実行されます。なので、呼び出される側でTask.Wait()をした場合、呼び出し側を待機中にしてしまうので結果、デッドロックとなってしまいます。
デッドロック対策
- 今後非同期処理に改修する可能性があるならTask.Wait()は使わない
- とにもかくにも、awaitを使う際には、必ずConfigureAwait(false)を書く。
private async void Page_Load(object sender, EventArgs e)
{ await HeavyProcessingAsync().ConfigureAwait(false); } |
Task.Wait()使わなくても、WhileループやResultプロパティの参照とかで余裕でデッドロックになるみたいです。(Result プロパティは、タスクが終了するまで呼び出し元のスレッドをブロックします。)
ConfigureAwait(false)をつければ、特定のスレッドに戻らなくても良いので、デッドロックを防げます。しかし、ListなどのUI処理では特定のスレッドに戻る必要があるので、そこだけ留意すればよいらしいです。
参考サイト
方法: タスクから値を返す | Microsoft Docs