Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Railsを6年間やってきたぼくが最近Railsでハマったこと

rince
September 28, 2017

 Railsを6年間やってきたぼくが最近Railsでハマったこと

9/28にRails Developers Meetup #5のLTで発表した内容です。

Rails2系の時代から約6年程Railsを触ってきましたが、今でもたまに「そこそんな仕様だったのか!」とRailsでハマることがあります。そんなハマったポイントを実際の事例やRailsのコードなどを交えてお話できればと思います。当たり前の内容もあるかもしれませんが、皆さんがRailsでハマった時に思い出して、少しでもお役に立てれば幸いです。

rince

September 28, 2017
Tweet

More Decks by rince

Other Decks in Technology

Transcript

  1. w BSUJDMFTςʔϒϧΛ࡞੒ ࣄྫ class CreateArticles < ActiveRecord::Migration def change create_table

    :articles do |t| t.string :title, null: false t.integer :user_id, null: false, index: true end end end
  2. w ΦϒδΣΫτ͕OJMͰͳ͍৔߹ͷΈϝιουΛ࣮ߦ͠ɺɹ ɹ OJMͷ৔߹͸Կ΋͠ͳ͍ USZͱ͸ user = nil #=> nil

    user.writer? # NoMethodError: undefined method `writer?' for nil:NilClass user.try(:writer?) #=> nil class NilClass def try(*args) nil end ... end BDUJWFTVQQPSUMJCBDUJWF@TVQQPSUDPSF@FYUPCKFDUUSZSC
  3. w Ϣʔβʔ͕ϥΠλʔ͔Ͳ͏͔Λ൑ఆ ࣄྫ user = User.first #=> #<User id: 1,

    name: ...> user.writer? #=> true if user.try(:writter?) 'Ϣʔβʔ͸ϥΠλʔͰ͢ɻ' else 'Ϣʔβʔ͸ଘࡏ͠ͳ͍͔ϥΠλʔͰ͸͋Γ·ͤΜɻ' end #=> "Ϣʔβʔ͸ଘࡏ͠ͳ͍͔ϥΠλʔͰ͸͋Γ·ͤΜɻ"
  4. w ʮUSZʯ͸ϝιου͕ͳ͍৔߹ʢUZQPͳͲʣ΋ྫ֎Λग़͞ ͣʹOJMΛฦ͢ ݪҼ module ActiveSupport module Tryable def try(*a,

    &b) try!(*a, &b) if a.empty? || respond_to?(a.first) end ... end end class Object include ActiveSupport::Tryable end ... BDUJWFTVQQPSUMJCBDUJWF@TVQQPSUDPSF@FYUPCKFDUUSZSC
  5. w ʮUSZʯΛ࢖͏ w ΅ͬͪԋࢉࢠʮʯΛ࢖͏ʢ3VCZʙʣ ରࡦ user.try(:writter?) #=> nil user.try!(:writter?) #

    NoMethodError: undefined method `writter?' for #<User:0x007fcd4b843b20> # Did you mean? writer? user&.(:writter?) # NoMethodError: undefined method `call' for #<User:0x007fcd4b843b20>
  6. GSBHNFOUDBDIFͱ͸ w 7JFXͷҰ෦෼ΛΩϟογϡ͢Δػೳ w Ωϟογϡͷ৚݅΍ظݶΛݸผʹઃఆͰ͖Δ w ΦϒδΣΫτ΍)5.-͕มߋ͞ΕΔͱߋ৽͞ΕΔ <% cache @article,

    expires_in: 5.minutes do %> ɹɹΩϟογϡ͍ͨ͠HTML <% end %> WJFXTBSUJDMFTEEDBGCDCD⒎FF BSUJMDMF@JE BSUJMDMFͷVQEBUFE@BU Ωϟογϡ͞ΕΔϏϡʔϑϥάϝϯτͷ ಺༰͔Βࢉग़͞Εͨ.%ϋογϡ ੜ੒͞ΕΔΩʔ
  7. w هࣄϖʔδͰϑϥάϝϯτΩϟογϡΛར༻ ࣄྫ BQQWJFXTBSUJDMFTTIPXIUNMTMJN - cache @article, expires_in: 5.minutes do

    ... = render 'common_partial' ... BQQWJFXTBQQMJDBUJPO@DPNNPO@QBSUJBMIUNMTMJN p | ڞ௨ͷύʔγϟϧͰ͢ɻ p | ڞ௨ͷύʔγϟϧͩΑʂ มߋ
  8. w UFNQMBUF͕ݟ͔ͭΒͳ͍ͷͰμΠδΣετ͕ܭࢉͰ͖ͣ ΩϟογϡΛߋ৽͢Δ͔Ͳ͏͔ͷ൑ఆ͕Ͱ͖ͳ͍ ݪҼ 3FOEFSJOHBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO $PVMEOUpOEUFNQMBUFGPSEJHFTUJOHBSUJDMFTDPNNPO@QBSUJBM 3FBEGSBHNFOUWJFXTBSUJDMFTEEDBGCDCD⒎FF NT  3FOEFSFEBQQMJDBUJPO@DPNNPO@QBSUJBMIUNMTMJN

    NT  8SJUFGSBHNFOUWJFXTBSUJDMFTEEDBGCDCD⒎FF NT  3FOEFSFEBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO NT 3FOEFSJOHBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO $PVMEOUpOEUFNQMBUFGPSEJHFTUJOHBSUJDMFTDPNNPO@QBSUJBM 3FBEGSBHNFOUWJFXTBSUJDMFTEEDBGCDCD⒎FF NT  3FOEFSFEBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO NT มߋલ มߋޙ
  9. Ωϟογϡ͕ΫϦΞ͞ΕΔ 3FOEFSJOHBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO 3FBEGSBHNFOUWJFXTBSUJDMFTCGDEC NT  3FOEFSFEBQQMJDBUJPO@DPNNPO@QBSUJBMIUNMTMJN NT  8SJUFGSBHNFOUWJFXTBSUJDMFTCGDEC NT

     3FOEFSFEBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO NT 3FOEFSJOHBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO 3FBEGSBHNFOUWJFXTBSUJDMFTFFGECDD NT  3FOEFSFEBQQMJDBUJPO@DPNNPO@QBSUJBMIUNMTMJN NT  8SJUFGSBHNFOUWJFXTBSUJDMFTFFGECDD NT  3FOEFSFEBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO NT มߋલʢΩϟογϡͳ͠ʣ มߋޙ 3FOEFSJOHBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO 3FBEGSBHNFOUWJFXTBSUJDMFTCGDEC NT  3FOEFSFEBSUJDMFTTIPXIUNMTMJNXJUIJOMBZPVUTBQQMJDBUJPO NT มߋલʢΩϟογϡ͋Γʣ
  10. ϓν৘ใᶃ w 3BJMT͔Β͸ʮSBJMTEFWDBDIFʯίϚϯυ͕௥Ճ͞Εͯ ؆୯ʹΩϟογϡ0/0''Λ੾Γସ͑ΕΔΑ͏ʹͳͬͨ config.action_controller.perform_caching = true 3BJMT $ bin/rails

    dev:cache Development mode is now being cached. 3BJMT DPOpHFOWJSPONFOUTEFWFMPQNFOUSCΛҎԼͷΑ͏ʹฤूͯ͠ɺαʔό࠶ىಈ ҎԼͷίϚϯυΛୟ͘ͱɺUNQDBDIJOHEFWUYU͕ੜ੒͞Εͯαʔό΋࠶ىಈ͞ΕΔ
  11. .PEFM class Article < ApplicationRecord has_one :ogp_info, dependent: :destroy ...

    end class OgpInfo < ApplicationRecord belongs_to :article ... end BQQNPEFMTBSUJDMFSC BQQNPEFMTPHQ@JOGPSC
  12. $POUSPMMFS class OgpInfosController < ApplicationController before_action :set_article def new @ogp_info

    = @article.build_ogp_info end def create @ogp_info = @article.build_ogp_info(ogp_info_params) if @ogp_info.save redirect_to article_ogp_info_url(@article), notice: 'OGP৘ใΛ࡞੒͠·ͨ͠ɻ' else render :new end end ... private def set_article @article = Article.find(params[:article_id]) end end
  13. w IBT@POFʹEFQFOEFOUEFTUSPZ͕෇͍͍ͯΔͱɺ CVJME@YYY࣌ʹϨίʔυ͕࡟আ͞ΕΔ ݪҼ article = Article.first #=> #<Article id:

    1, title: ...> ogp_info = article.build_ogp_info(title: 'hoge') #=> #<OgpInfo id: nil, title: "hoge", ...> ogp_info.save #=> true article.ogp_info #=> #<OgpInfo id: 23, title: "hoge", ...> ogp_info = article.build_ogp_info(title: 'fuga') # (0.3ms) BEGIN # SQL (0.5ms) DELETE FROM `ogp_infos` WHERE `ogp_infos`.`id` = 23 # (1.8ms) COMMIT #=> #<OgpInfo id: nil, title: "fuga", ...> article.reload.ogp_info #=> nil