u-ryo's blog

various information for coding...

Category: Vue

Learned on Ruby and Vue, Angularjs

| Comments

お仕事でRuby on RailsとVueをやっております。 これまではずっとJavaやAngularな人生だったので、Duck Typingと格闘中です。 新規機能開発で様々な山を超えてきた(知見を得た)ので、忘れないうちに。

  • 破壊的method(Bang Method)って、その響きから何かあんまり良くないのかと無意識に思っていたのですけれども、調べてみると特に忌避すべきというものは見つかりませんでした。内部logicを考えると中で変数を付け替えていると思われますが、bangしないと両方分memoryに持ってなきゃならないから?→そうしたらrubocopに、result[:key]=... if ...と書けと言われました。ナルホドです!
  • 手元ではyarn test:vue通るのにCircleCIでは7 failsと言われて通らないので悩みました。どう目を凝らしてもerrorらしき出力はなく。よく見るとCircleCIの最後にToo long with no output (exceeded 10m0s): context deadline exceededとあり、かかった時間が10:57とか。えー!?そんなにかかっているの?? 手元でtimeで計測するも、1分ちょっと。CircleCI再実行して観察すると、test自体は1分程で終わり、その後ずっとだんまりで、10分程してTimeoutします。何だろう? 手元では再現しないのでとにかく厄介です。考えてみたら、チェックじゃなくて「1)」とか「2)」になっているところが失敗したところなんですね。確かに7)までありますわ。でも、そこがどう間違っているのかが全然出力されないので皆目わかりません。一箇所、describe('...', async () => {ってなっていたから、これか! と消して勇躍試してみたものの、症状変わらず。mountshallowにしてみたり削れるだけのasync/awaitを削っても。何故かdescribeの囲みを解くとtestが失敗します。期待してるobjectのpropsがないと。でももう一つ別のpropsはある。もぅわけわかんない!ですよ。CircleCIにsshで入ったりして色々と調べてみると、特定の2 filesが先にあると失敗する様子。何それ。どちらかがない、もしくはどちらかより先に実行されれば上手く行く。もっと詳しく見てみると、具体的には、shallowした直後のwrapper.html()の中身が全然違うという。どうして? そんなとこどうにもなんないじゃん。...あぁ、ぃゃ、test対象Vue Classできちんとcomponentを定義すると(e.g.components: { 'el-button': Button, 'el-dialog': Dialog })warningが消えてcomponentとして見えるようになることがありますが(特にElementUIはel-...とclass nameが合わないので...(- -;)、そういうわけでもなく。何せ2 filesが組み合わさるとtestにコケるというのが謎です。試しにダメにするspec fileを一つ消してから全体的にnpm run test:vueしてみると、またコケるので、その2 filesはat leastであってもっと他にも組み合わせの悪いのがあるということです。i18nかなぁ? 確かに一方はenで他方はjaでしたが、大して使ってないのでcomment outしても変わらないですし... localでは全体的に通しても通っている、CircleCI上でも単体や相性の悪いものの後でなければ動く、でも全体的に通すとtestに失敗する、というのはとても悔しく、厄介です。結局心折れて、componentが見つからなければtest codeをthroughするようにしました。端からdescribe.skip(...よりはマシでしょう。それにしても何でやねん。大したtestしてるわけでもないclasses(methodがcallされたかどうかをassertしてる程度)に阻まれて、ちゃんと作ったspecのtest(条件がどうならどういう表示状態、input要素をclickしたらどういう文言のdialogが出て、等)を実行できないというのは何とも残念でなりません。
  • Vueのtest、ムズカシイです。child componentの扱い、ですね。何気なく使っているであろうel-tableとかel-dialog、そのままだとそんなcomponent知らないよとwarningが出まくります([Vue warn]: Unknown custom element: <el-table-column> - did you register the component correctly? For recursive components, make sure to provide the "name" option.)。wrapperからはHTML Tagとして扱えるので最後はそうするのですけど、出来ればちゃんとcomponentとして扱いたいところです(でないとtable等でdataをloopさせて表示を作るcodeだった時のdata部分がそっくりないのでtest出来ない)。spec classでshallow(ormount)する時にstubs:するのかと思ってた(前それで頑張った気がした)んですけどそうではなく、spec対象元classでちゃんと定義されていれば?、否、ElementUIなんかは丸っと読み込まれているのでいいのかなぁ?ともあれ、spec classでlocalVue.use(Table)としたlocalVueshallow(ormount)時に読み込んでやる必要がありました。でそのcomponentをfindして.props()して中身をexpectしていくという流れですね。最初はconsole.log(wrapper.html())で何が捕れるのかよく観察すると。でも上記のように、何かが変わるとすぐ取れるcomponentが変わるようなので、怖いです。その辺りの機微がよくわからないので...
  • Vue testにおけるtickの待ち方。it(..., async () => { ... await Vue.nextTick(); ...}); 2 ticks待たないと値が変わらないことも。
  • wrapper.findAll('.cell')で取って来た値はElement Objectなので、見た目上は空でもexpect(cell).to.be.emptyとは出来ません。expect(cell.isEmpty()).to.be.true
  • Vue componentって、初期値propsdataは分けねばならない? 当初、dataに初期値を渡そうとしてどうしても出来ず、途方に暮れました。dataの初期値はdata部に書いた最初に返す値でそれは何でもよく、tagの方で渡す値で上書きされるのかと思ったら違うんですね。ではdataではなくpropsを使うのかと思うとそうでもなく、propsを後から変更しようとすると怒られますし。Stackoverflowにあった解決策は、初期値propsdataを使い分けること。無駄な変数増えて何だかなぁとは思いますれど、そういうもの?
  • slot-scopeって、="scope"ではなく={row}とやればいいんですね。本で知りました。
  • ...mapGettersがなかなか効かなくて苦労しました。computed:に入れる、storeのmodule構造に合わせてmodule(file)名/method名にする、とやったんですが、undefinedって言われて。store経由でthis.store.value_nameとかってやると取れるのに。でもState を直接参照せず、getter 経由で参照することを強く推奨するというので頑張りました。一回は諦めたんですけど、その後retryしたらうまくいくように。結局どうしてうまくようになったのか、決め手が何だったのかよく分からずじまいです。
  • 確認dialogを出すというんですが、非同期のJavascript/Vueにあってはこれが意外とムズカシイです。確認dialogというからには処理を止めなければなりません。よくやるように「flagで表示を制御」ではmain処理止まらないんですよね。そもそもsleepだとて簡単には行かないですよねJavascriptで。とても苦労しました。async/awaitを導入してやっと止めました。要は「dialogを作っているところをnew Promiseでくるんでreturn、それをawait、しているfunctionをasync」ですかね。
  • dialogって自分で$destory()出来るんですね。生成と削除は外からやらないとダメかな、と思っていた(ので$emitして親で受けてdialog.$destory()してた)んですけど、実際生成は外から$mount()呼ばないとならないですけど(created:mounted:はcallbackですよね)、「ボタン押したら消滅」で自己$destroy()は出来るんですねやってみたら。いちいち面倒くさいけどやってみないとわからんもんですね。
  • dialogを出す必要に迫られたんですけど、よくあるようにdialogを予めDOMに仕込んでflagでappear/disposeとするには、2階層上のVue componentに書かないと、loopで大量生産されてしまうことが判明。Vue component間は親との対話だったら$emitと、戻しは何だ??を使えば出来ますが、2階層上は面倒です。情報渡すだけならまだしも、その後の処理を孫でやるならdialogの結果を2階層戻してもらわないとならないですし、じゃぁ処理もgrandparentに渡す? 処理に必要な情報も渡さないとだし、grandparentで知らなくてもいいことを知らなきゃいけないなんて。ということで、何かないかなーと探すと、揮発性dialogというものが(揮発性の高いコンポーネントを作る話)。探すと似たようなことしてる人割と多く。これを理解して、そのままではなく2 filesで済むようにして自分のにapplyするのも頭を使いました。これ結構いいような。Vueのdialogも一般的にこれでいいような。初からDOMについているのではなくって。
  • 既述のように、awaitもうまく行ってよし、じゃぁtestを書くぞ、と試したら、いきなりわけのわからないerrorに見舞われてそもそもtestが動かなくなってしまいました。なんでだろー?! 自分以前では確かに動いていたので、自分のせいです。でもどのfileが悪いとかも出て来ないのでまるで取っ掛かりがなく、途方に暮れました。error messageで検索すると、どうやらなんとasync/awaitを使った場合に出るbable/polyfill系のerrorだとか。えー!! 折角苦労してasync/awaitでdialog止めたのに! 代替手段なんて思い付かないよー! ということで、何とか突破すべく頑張りました。babelの線で色々と調べてみると、こうしたら直った、ああしたら、とか種々書いてあるんですね。新たなgem install以外は全部試しましたけど、うまく行かず。でもこの記事を参考にvueのsetup.js冒頭にrequire("babel-polifill");と書いたら!! 動いてくれました!! 省みれば僅か1行の追加ですけど、この1行には数時間もの汗と涙が詰まっているのです。
  • APIの試験をするのに、curlやPostmanを使うのはよくありますけど、cookieが何か長くてcopyが面倒だなーと思ったので、Chrome Developer toolのConsoleにてfetchでやる手法を。fetch(`/apis/endpoint/${id}`,{method:method,credentials:'include',headers:{'X-CSRF-Token':token}}).then((response)=>console.log(response))とすればBrowserの持っている認証情報をそのまま使ってくれます。credentials:'include'が肝です。どうせ使い捨てcommandですから。
  • Railsは自動的にCSRF対策がなされている、ということで、何してるんだろーと思いきや、session毎に予測困難なX-CSRF-Tokenが付くというものでした。request毎に違うものでなくてもいいのか? いいのか...予測困難なら...
  • Railsの日付、Timezone気を付けないといけないのですけど(AWSはUTCなので)、Time.currentDate.currentのように.current methodを使えばTimezoneを意識してくれる模様。.nowより.currentがということでやはり「ナウい」は死語ということですか。
  • Ruby、共通処理は継承関係作って親クラスに、と思っていたんですけどそれってJava的発想? OOP的というか。RubyではむしろMixin? MixinってAOPかと思ってたんですけど。Duck Typingだからそもそもclass的には無関係でいいんですね。Java屋さんとしては何だかなぁと。
  • Rubyのstream(mapselectrejecteach等)、もうfoolproofとしてlazy...forceを付けるのがいいんじゃないか、と思ったんですけど、そうでもないんですねこれ!! ってかそもそもどうしてlazyがdefaultじゃないんだろう? ってJava屋さんとしては思ってたんですけど、銀の弾丸ではないという話があって衝撃でした何を今更ですけど(古い話のようで今は多少performance上がったそう)。というわけで、lazyは「省メモリ」か「後でかなりの数takeすることがわかっている場合」でないと効果なさそうなんですね。元ネタ
  • 最近何か安易に大量のlogをslackに投げていたので、そうじゃないでしょ基本的にはlog fileでしょ、それもdefaultのfileでいいよね、ということで、Logger.new(...)ってやったんですけどどうして毎回file nameを指定しなきゃいけないのか、しかもfile名指定してnewすると都度file作りやがる、のでappend modeでopenして、とかってやらないとならないの?! なんか面倒臭くね? と思ってたら、Rails.loggerでいいんですね。なぁんだ。@logger ||= Rails.logger
  • controllerで最終的?に全てのerrorを拾うにはrescue_from error_class名, with: :method名、事前validationを定義するにはbefore_action :method名
  • 決まった名前をclass methodにするか定数にするか、は、定数の方が良いようです。ref. Class method vs constant in Ruby/Rails
  • Rubyで「objectの同一性」とは、Javaと違って==eql?hashの3 methodあるんですね。うち==はArrayで、残る2つはSetで使われる模様。Arrayでは比較通るのにSetでは違うと判定され悩みました。Setではobject hashを取っているからなんですね。でも結局、.to_jsonすれば同一性methods定義しなくても行けました。何だかなぁですけどまぁunit testなのでいっかー。
  • すっかり忘れてましたけどroutesresourcesを使えばendpoint定義をまとめられますね。path parameterも積極的に使うべきでしょう(その存在を強制できるので)。parameter nameは基本idですけど変えられるんですね。
  • ActiveRecordで、MySQLみたいに「あれば取得、なければ作る(recordも入れる)」なんてあるかなーと思ったら.find_or_create_byがありました。更にforeign key制約をつけて、その制約に反したらerrorにして欲しい場合は、.find_or_create_by!でした。
  • RubyでVO(Value Object)を作るのは、どうしたらいいんですかね。object = Struct.new(:variables, ...)とobjectとして使えば良い、という記述があったので、今度試してみます。←ここでいうobjectってclasなんですね。
  • RubyにもJavadocのようなcomment流儀あるんですね。YARDですか。@param [引数のクラス] 引数名 引数の説明@return [戻り値のクラス] 戻り値の説明
  • 配列からhash mapを作る手法、色々ありますよね。よくある「[key, value]の配列の配列にしてから.to_set」はloopを2回回すので何だかなぁと思っていました。Rubyにもあるreduce(inject)を使えば出来る!とあったのでやったのですけど、そうしたらrubocopに「そういう時はeach_with_objectを使え」と言われました。ナルホド、それなら確かにblockの最後にhashをreturnせずともよいわけですね! というわけで、list.each_with_object({}){|value,hash|hash[key]=value}、更に一気にhashのhashを作るには、list.each_with_object(Hash.new{|hash,key|hash[key]={}){|value,hash|hash[key1][key2]=value}
  • 同様に、一気にSetを作るには、list.each_with_object(Set.new){|value,set|set<<value}の方が、最後に.to_setよりよいでしょう。
  • reekに「log.debugを複数回使っているからまとめよ」と言われて弱りました。単純にまとめると、毎回引数を評価しちゃうじゃないですか。でもloggingなので遅延評価が必要でしょう。というわけで、blockを残せるようにmethod定義しました。def debug(&block) Rails.logger.debug(&block); end使う時はdebug{...}です。
  • rescue=> eとせずとも$!でerrorを参照できるんですね。rescueretryとすればbeginからまたやってくれるんですね! ただ、上限設けないとずっとretryし続けるので注意ですかね。
  • Railsでmail送信は、configが終わっているのであとは、ApplicationMailerを継承したclassを作成、app/views/class名/method名.html.hamlといったtemplateを用意、という感じでした。html mailだけだとspam判定されやすいとのことなので、app/views/class名/method名.txt.erbも用意しました。classのinstance fieldをmail template中で参照できます。
  • ActiveRecordでの取得はなるべく.pluckにした方が速いし軽い、ということでそうしてますが、でもそうすると何のためのDTOなのかと。model定義の意義が少し薄れるような。modelがfatなのが悪い? .pluckでない場合はせめて.selectで選択するfieldを減らしてやって生成されるobjectを少しでも軽くすると。ただActiveRecordからObjectを生成するcostが高いとのことなので、.pluckの方が推奨されています。....selectって、modelにないfieldもselectできるんですね。そしてdynamicにmethodが生えると。なんかそこまで行くと気持ち悪い気がするのは、やはりJava出身だから??
  • yieldはよく使いました。if block_given?も併せて。
  • instanceからclass variableへの参照はinstance.class::VARIABLEでした。
  • rspecでallow(Rails).to receive(:logger).and_return(spy('logger'))とするとloggingが一律空回しになります。
  • method chainをallowするにはreceive_message_chain(e.g.expect(SomeClass).to receive_message_chain(:joins, :distinct, :where, :pluck)) .with(...)を複数書いても、それぞれのmethodの引数指定ではなく、最後の一つしか評価されていない?
  • rspecで、違ったparameterで同じobjectのmethodをcallするのをstubするには、allow(...).to receive(:same_method).with(...)を並列で何度も書けばよいです。with(...)をmethod chainさせるとかではないんですね。
  • rspecでinstance doubleに引数を連ねるとmethod stubになります。e.g. double('user', id: 1)user.id==1(doubleの最初の引数は任意名)
  • 調べればすぐ出てくることではありますが、Railsのmigrationのcreate_table時にprimary keyを自動で出来るid以外にしたい場合はcreate_tableの行にprimary_key: key名と書きます。更にforeign key constraintを付け加えたい場合は、その下にadd_foreign_key :table名, :foreign_table名と書けば大丈夫でした。
  • RubyでTime format時、.strftime('%X')とすると一文字で15:37:21に、.strftime('%F')とすると2020-03-01になるので便利です。また、.iso8601とするとTを挟んでTimezone付きで2020-03-01T15:39:10+09:00というようにしてくれるのでこれも便利です。
  • 嫁の顔忘れてもTimecop.returnは忘れないでねという話にあるように、Timecop.travel(Time.parse('2020/3/1 0:01:03')) do ... endで囲うのはいいですね。Timecop.travel(特定時刻にしてから時を刻む)と.freeze(特定時刻にして時を止める)では違うので注意です。
  • Rubyで文字列の連結は<<いいみたいですね。C++みたいですね。
  • ActiveRecordでN+1問題を回避するには、なるべくjoinsした方が良いようです。が、図に乗って巨大tableをjoinするとそれはcostがでかいので、分割して引いた方がいいんでしょう。joinsするにはmodelにhas_manyとかの関係が書いてないとダメでした。2つ先の関連も書けて、has_many :second_table, through: :first_tablethrough:で繋げられました。
  • と思ったのは幻想でした。書けちゃいますけど、joinされたものはkeyで結びついたものではなく、雑に合わさったもので、whereで引いてもそうでないものまでついてきていて、bugを引き起こしていました。ちゃんとやらないとダメですね。
  • 「ちゃんとやる」とは、Railsでモデルを4段階joinする方法で、もう一度理解するjoinsとmergeにあるように、ActiveRecordのjoinsで繋ぐ時にjoins(first:[second: :third])とすること。これでちゃんとjoinされました。
  • controllerで、APIっぽくheaderだけ返して中身は不要という場合、head :created(201)とかhead :unauthorized(401)と書けます。
  • Rubyのhere documentはもう<<~でよくないすか? <<だと左端にひっつくので。
  • Rubyのreduceeach_with_objectに取って代わられるのですが、reduce(&:method)で済むところに活路があるようです。使えたのはSetのmergeですね。[Set.new([1,2,3]),Set.new([2,3,4])].reduce(&:merge)==Set.new([1,2,3,4])
  • 複数回.include?するなら絶対Setにすべきですよ。
  • 定数文字列もなるべく.freezeすべきでしょうか。magic comment # frozen_string_literal: trueで(が?)よいのでしょうか。
  • controllerのrspecで、before_actionのtestを書くことになったのですが、色々と悩みました。どこに書くか? 書いたclass? 使うclass? Javaでabstract classのtestだとconcrete classに書きますが、controllerは使う側に書くと多岐にわたるので、application_controller_spec.rbに書きました。
  • curlでtest clientとしてJSONを-dでPOSTしたところ、どうもうまく行かなくて、調べるとserver側に"{\"key\":\"value\"}"なんて渡っていました。どうしてー?! HTTP Request HeaderにContetnt-Type: application/jsonが必要なんですね! そういえば。
  • 今更ですがAngularJSのtestで、window.location.hrefをassertionしようとして四苦八苦しました。How to mock $window.location.replace in AngularJS unit test?等から得たことは、window.location.hrefだとtest(jasmin)で拾えないので$window.location.hrefにする、responseがemptyだとどうしてもtestの方でcatchしてくれないのでdummy値をresponse代入する、testでは$windowがemptyで悩みました。$provide.value('$window',でprovideしてbeforeEach(inject(function($injector, $rootScope, $httpBackend, $window) {でinjectしつつwindow=$window;と付け替えて、assertionのところでwindowを使う、という。
  • diffで相違は出ますが、共通行を抽出するには? comm -1 -2 file1 file2(但しfilesはsort済であること) ref.2つのファイルの共通行を抽出する方法
  • MySQLでindexがついたかどうかを確認するには、describe table名ではMulと付くだけでよくわからず。show create table table名でCREATE文を出すことで。
  • controllerのrspecで、sessionってどう表すのかと。get :index,params:{aaa:'AA'}だからget :index,params{...},session:{...}かと思いきや、実際そう書いてあるところもあるんですが、それではうまく行かず、get :index,{param:'something'},{session:'something'}と。ref. RSpec set session object
  • rspecでprivate variableにsetするには、some_instance.instance_variable_set('variable_name', 'some value')、getするには`someinstance.instancevariableget('variablename')
  • visitor patternを適用しようと思っていたのですけど、諦めました。RubyってDuck Typingだからあんまり効果を見出だせず。Ruby で Visitor パターンをあまり使わない理由,Ruby で Visitor パターンを使うときという投稿もあり。

  • upstart で start した job の設定を変更するには一度 stop する必要がある へーそうなんだ! ってぃぅか何のためのrestartっすか? restartあるんだから機能すると思いますよねぇ...orz

  • 1.hour.agoがあるのに.later.afterはないのでどうするんだろう? と思ったら、1.hour.from_nowっていうんですね。

  • controllerのrspec書いていて、やっと単体で通るようになったので、いざ全体的にrspecかけてみると、コケます。確かに自分の書き足したところ。でも通る時もある。どうして?→そういう、rspecの結果が不安定な時は、実行順序依存性があります。これを紐解かねばなりません。それが厄介でした。といいますか、rspecって全体的にかけると、といいますかspec fileを指定しないでdirectoryだけ指定して実行すると、spec filesの実行順序がrandomなんですね。それはその方がいいですね。なので、色んな手を使って順序依存性を解明していきます。ref. RSpecコマンドのオプションまとめ rspecに--order random:NNNNNを付けてrandom seedを固定、-f dとして出力formatにclass名を出すようにし、--no-colorでescape sequenceを抑制します。-o filename.logでfileに出力、それをうまく行ったときと失敗した時で保存して、class名を比較しました。当該classのtest以前だけが大事なので、そこだけ出してsortしてdiff取ります。失敗事例が複数取れれば、それらの共通classをcomm -1 -2 <(...) <(...)で抽出するのが良いです。

    1
    2
    3
    4
    
    docker-compose exec rails bash -c 'RAILS_ENV=test bundle exec rspec --order random:32510 -f d -o 32510.log --no-color'
    diff <(grep -e '^[A-Za-z]' -e '^  Apis::' controllers2.log|awk '{if(/ApplicationController/){exit}print}'|sort) <(grep -e '^[A-Za-z]' -e '^  Apis::' 32510.log|awk '{if(/ApplicationController/){exit}print}'|sort)|ag '<'
    comm -1 -2 <(grep -e '^[A-Za-z]' -e '^  Apis::' controllers2.log|awk '{if(/ApplicationController/){exit}print}'|sort) <(grep -e '^[A-Za-z]' -e '^  Apis::' 4627.log|awk '{if(/ApplicationController/){exit}print}'|sort)
    comm -1 -2 <(grep -e '^[A-Za-z]' -e '^  Apis::' controllers2.log|awk '{if(/ApplicationController/){exit}print}'|sort) <(grep -e '^[A-Za-z]' -e '^  Apis::' 48327.log|awk '{if(/ApplicationController/){exit}print}'|sort)|grep -r -l -f /dev/stdin spec/controllers|sort -u|tr -d '\r'
    

  • 単体では通るのに全体だと時々こけるというのはどうしてもよくわからないので、何度も何度も実行して観察してみると、コケる時のFの出る位置がまちまちなんですね。あぁ、これって毎回test順序違うのか、とその時初めて思い至りました。それで、rspecにおけるrandom seedの固定方法や出力形式の指定の仕方を調べ、何とか実行順を成功時と失敗時で比較して、怪しいものを試して、辿り着いたのでした。

  • controllerのtestでは、before_actionに指定したprivate methodのtest且つ利用するchild classでのtestではなくbase classでのtestなので、当初はcontorller.send('method_name')とかやってたんですけどこれは本来的ではないな、ということで、Anonymous Controller使いました。といってもdescribeの中でcontroller do ... endして、そこでbefore_action :method_nameしただけのものです。それでそのdescribe内のcontrollerは定義したものになるという、お手軽な。でもここでエラー(Errorをthrow、じゃないRubyだからraiseですか、する筈が正常に終了してしまう)が出て、悩みました。結局、わかってみればどうということはないのですが、他のspec classで、ApplicationController.skip_before_filter :login_requiredbefore do...でやっていて、でもafter do...で元に戻していなかったから、というのが原因でした。

  • そもそも、ApplicationController.skip_before_filterなんてせずに、単にallow(controller).to receive(:method)とmockすれば十分です。そうしたらafter do...だって不要ですし。ref. before_filterを分離してテストする方法(Rspec) 別段true返す必要もないんですねこのbefore_actionって。before_filterは古いんだそう。

  • いつもscheduleの確認をするのに。bundle exec whenever

  • AngularJSでのredirect? になるのかな? は、routesの$stateProvider.state('...')に定義されたところへ、$state.go('...')で飛びます。ref. Angularjs UI Routerの使い方 でも結局、AngularJSのrouting範囲外に飛ばしたかったので、$window.location.href = ...で飛ばしました。

  • ActiveRecordのscopeに引数を取る場合には、scope scope_name ->(arg1, arg2) { ... } 矢印とカッコはくっつけないとreekに怒られます。

  • RubyでStringselectを正規表現でするならgrep(/.../)-vの場合はgrep_v(Ruby equivalent to grep -v)

  • AngularJSのroutingってURLについたanchor(#以下)に出るのですが、それってそもそもbrowserがserver側に送信しないんですね...

  • ActiveRecordで選択して保存を1行で。例えばUser.find(1).update(name:'new name')

  • rspecでActiveRecordのtest dataってfixtureやFactoryGirlを使うものかと思っていたのですけど、普通に.createとか.updateとかして大丈夫なんですね。大丈夫、というのは、後腐れがない、んですね。

  • RSpecでallowでmockした時に、.and_returnだけでなく処理(sleep(1))を入れたかったんですけどどうしたら? と思ったら、単にblockでいいんですね。blockの最終評価値がreturnになる、というなら.and_returnって不要なの?