Skip to content

Instantly share code, notes, and snippets.

@aliyome
Created June 25, 2016 05:34
Show Gist options
  • Select an option

  • Save aliyome/23e2446abbd0e3db12fb27dbc86f2fe2 to your computer and use it in GitHub Desktop.

Select an option

Save aliyome/23e2446abbd0e3db12fb27dbc86f2fe2 to your computer and use it in GitHub Desktop.

Rails概要 10%

  • Railsの各コンポーネント(ActiveRecordやActionPack)の説明や、MVCにおける基礎的な知識
    • ActiveRecord
    • ActionPack
      • Action Dispatch
      • Action Controller
    • Active Support Core Extensions
      • blank? false, nil, 空白, 空の配列, 空のハッシュ, empty?
      • present?
      • presence nil or 実体
      • h html_escapeのalias
      • html_safe 「安全」印を付ける.ビューにそのまま表示する.
      • html_safe?
      • try nvlみたいな感じ(nはnil) Ruby2.3では&.が使える?
      • try! 存在しないメソッドの場合は例外
      • in?
      • delegate :method1, :medhod2 to: :target (target.methodが呼ばれるようになる)
      • cattr_accessor :name クラスプロパティ # 値の設定は一度だけ実行される
      • cattr_accessor :name do ... end
    • Railities
      • Railsの起動プロセス、CLI、ジェネレータなど
  • ディレクトリ構造の説明
    • app/
      • controllers/
        • assets, mailers
    • bin/
    • config/
      • routes.rb, database.yml, environments, ...
    • config.ru
    • db/
      • schema.rb, ~.sqlite3
      • migrate/
      • seeds.rb
    • Gemfile
    • Gemfile.lock
    • lib/
    • log/
    • public/
    • Rakefile
    • README.rdoc
    • test/
      • fixtures/ (*.yaml)
    • tmp/
      • cache/, pid/, sessions/
    • vendor/
  • rake、railsコマンド
    • rake
      • T --tasks
      • D --describe
      • stats
      • notes
      • db
        • :seed
        • :setup
    • rails
      • c console
      • d destroy
      • g generate
        • controller
        • model Item name:string{10}:uniq price:decimal{5,2} vendor:references:index
        • view
        • scaffold
      • new
        • r --ruby
        • m --template
        • B --skip-bundle
        • G --skip-git
        • O --skip-active-record
        • S --skip-sprockets
        • d --database
        • s --skip
        • h --help
        • v --version
      • r runner
      • s server
  • ActiveSupport

ActiveRecord 40%

  • ActiveRecordの構造
    • CUコールバック
      • before_validation
      • after_validation
      • before_save
      • around_save
      • before_create / before_update
      • around_create /
      • after_create /
      • after_save
    • Dコールバック
      • before_destroy
      • around_destroy
      • after_destroy
  • モデルの定義
    • inet, cidr, macaddr
    • composed_of :user, class_name: 'User', mapping: ['username', 'name'] # class_nameは省略可
  • リレーション
    • belongs_to, has_one
    • hmt(has_many, through)
    • habtm(has_and_belongs_to_many)
    • ポリモーフィック関連
      • rails g model Picture img:references{polymorphic}
      • ↑ create_table :pictures do |t| t.references :img, polymorphic: true, index: true
      • ↑ 同義 t.integer :img_id \n t.string :img_type
      • class Employee has_many :pictures, as: img
      • class Product has_many :pictures, as: img
  • バリデーション
    • validates :hoge, :presence true, if: -> {@foo.blank?}
    • バリデーションヘルパー
      • presence
      • absense
      • length { minimum:0, maximum: 10}
      • numericality { greater_than_or_equal_to: 0 }
      • format {with: /\A hoge \z/}
      • confirmation
        • hoge_confirmation
      • inclusion {in: []} / inclusion []
      • exclusion
      • acceptance
      • uniqueness
    • create(戻り値false), create!(例外)
    • valid?
    • カスタムバリデーション
      • ActiveModel::Validator モデル単位
        • validates_with HogeValidator
        • class HogeValidator < ActiveModel::Validator
        • def validate(record) record.errors[:fieldname] = 'error msg'
      • ActiveModel::EachValidator フィールド単位
        • validates: hoge, foo_bar: true
        • class FooBarValidator < ActiveModel::EachValidator
        • def validate_each(record, attribute, value) record.errors[attribute] = 'error msg'
    • model.errors.full_messages # ['aaa', 'bbb', 'Field ccc']
    • モジュール
      • ActiveModel::Model, ActiveModel::Validation
  • CRUD操作
    • find # id配列を渡すと、全て存在するなら配列が返ってくる
    • find_by # 常に一つ
    • find_by_sql(sql), find_by_sql([sql, param]) # 常に複数
    • find_each # 常にidで昇順
    • pluck
    • select # モデルのインスタンスが返る
    • ids
    • includes(:hoges)
    • joins(:hoges)
    • t = Item.arel_table \ Item.where(t[:id].eq(8).or t[:id].eq(9))
    • where.not
    • ActiveRecord::Base.connection.select_rows("select * from hoges") #
    • ActiveRecord::Base.connection.select_values # rowsとは違い、最初の列の値のみ取得
  • スコープ
    • scope :s1, ->(val){ where("hoge") }
    • default_scope {}
    • Item.unscope
  • マイグレーション
    • yyyyMMddHHmmss_add_hoge_to_items.rb
    • schema_migrations
    • rake:db version
    • CreateHoge, AddHogeToItems, RemoveHogeFromItems, CreateJoinTableHogeFoo
    • rails destroy migration CreateHoge
    • def change
      • create_table :items do |t|
        • t.string :hoge, limit: 20
        • t.decimal :val, precision:5, scale: 1
      • rename_column :items, :price, :value
      • add_column, add_index, add_reference, add_timestamps
      • create_table, create_join_table
      • drop_table, drop_join_table
      • remove_reference, remove_timestamps
      • rename_column, index, table
  • トランザクション
    • optimistic locking
      • lock_version # デフォルト値0を入れる, 名前変更可能

ルーティングとActionContorller 20%

  • config/routes.rb
    • resources :items # index, show, new, create, edit, update, destroy
      • only: [:index, :show]
      • except: [:create, :edit, :destroy]
      • constraints: {id: /[1-9]/}
      • format: false # /items/1.mp3 <- 不可
      • format: true # /items/1.mp3 <- 必須
      • controller: :i # i#index
      • as: :i # i_index
      • resources :hoge do
      • collection do get 'foo' end
      • member do get 'bar' end
      • get :foobar, on: :new # /hoge/new/foobar
      • get :foobar, on: :callection # /hoge/foobar
      • get :foobar, on: :member # /hoge/1/foobar
      • end
      • resurces :items do
      • resources hoges # /items/1/hoges/1
      • shallow do
      • resources :items do
      • resources :hoges
        
      • namespace :foo do
      • resources :items # foo_items_index /foo/items foo/items#index
      • scope :foo do
      • resources :items # items_index /foo/items items#index
      • scope module: :foo do
      • resources :items # items_index /items foo/items#index
      • concern :hogeable do # 名前付け
      • collection do
      • get 'hoge'  # resources :items, concerns: :hogeable
        
    • resource :item # show, create, edit, update, destroy # show(:id)は無い
    • root to: redirect('foo/bar')
    • root to: 'items#index'
    • get '/:action(.:format)', controller: :items
    • get '/にほんご', to: 'foo/bar#index'
    • match '/u', to: 'items#index', via: :get # matchはvia必須
    • root_path # /
    • item_path # /item
    • item_url(1) # http://example.com/items/1
    • new_item_url # http://example.com/items/new
  • RESTとコントローラ
    • request.headers['User-Agent']
    • request.headers['HTTP_USER_AGENT']
    • response.headers['Content-Type'] = 'application/pdf'
    • パラメータ
      • クエリパラメータ(url?keyword=ruby&hoge[]=1&hoge[]=2&foo[bar]=3)
        • request.query_parameters
      • パスパラメータ(/:action/.format)
        • request.path_parameters
      • リクエストパラメータ(Postのbody)
        • request.request_parameters
      • 全部
        • params
        • params.fetch(:sonzaisinai) # ParameterMissing例外
        • params.fetch(:hoge, "default value") # デフォルト値設定
      • Mass Assignment
        • require(:hoge) # :hogeがない場合はParameterMissing例外
        • permit(:foo, :bar) # :foo, :barだけに絞る
        • params.require(:user).permit(:name, :age) # みたいに使う
  • コントローラとデータの入出力
    • render 'index' # 'index'は省略可 # この行自体省略可
    • @x = 10 # Viewで使用可能
    • render(locals: {x: 10} ) # Viewで使用可能
    • render(partial: 'layout', locals: {x:10}) # Partialで使用可能
    • render html: '<%= "OK" %>' # htmlエスケープされる
    • render plain: # そのまま
    • render inline: # OKだけ
    • render content_type: 'text/plain' # とかできる
    • render action: :index # index.html.erbをレンダリング
    • render :index # action:は省略可能
    • render template 'hoge/foo'
    • render file '/var/hoge/foo.html.erb'
    • url_for # コントローラとビューで使える
      • controller: :hoge
      • action: :foo
      • only_path # trueなら/コントローラ以降のみ
      • 'items#index' # これはできない!!
    • url_for(:back) # javascript:history.back()
    • url_for hoge_path(114514) # ヘルパー使うことが多い
    • redirect_to # url_forと同じオプションを使用できる
  • メディアタイプに合わせた出力フォーマット
    • respond_to do |format|
    • format.xml { render xml: hoge }
    • format.json { render xml: hoge }
  • フィルタ
    • before_action :hoge_check, except: [:foo]
    • skip_before_action :hoge_check, only: [:bar]
    • before_action内でrenderを呼ぶとactionが呼ばれない
    • around_action
    • do something

    • yield # このタイミングでactionが呼ばれる
    • do something

    • http_basic_authenticate_with name: "user", password: "pass"
    • before_action :auth
    • def auth
    • authenticate_or_request_with_http_basic("hoge") do |user, pass|
    • user == "user" && pass == "pass"
      
  • セッション
    • sessions[:count] = 1
    • sessions[:count] = nil # del
    • reset_session # delete all session
    • Rails.application.config.session_store : cookie_store, key: 'hoge', expire_after: 2.hours
    • cookies[:count] = "1"
    • cookies[:count] = { value: "1", expire: 1.hour.from_now, secure: true, httponly: true } # https only, can't access from js
    • cookies.delete(:count)
    • cookies.signed[:count] = 1

ActionViewとヘルパー 15%

  • ERBによるHTMLの出力
    • <%#= hoge %>
    • <% if false %> <%= foo %> <% end %>
    • <% =begin %> <%= foo %> <% =end %>
    • <%== hoge %> # escapeされない
    • <%= raw(hoge) %> # escapeされない
    • <%= hoge.html_safe %> # escapeされない
    • レイアウト
      • app/view/layout/application.html.erb # デフォルト
      • app/view/layout/{{controller}}.html.erb # 優先
      • render layout: hoge # 最優先
      • コントローラの layout オーバーロード(layout 'hoge', except: :edit) # 優先
    • <%= yield :hoge %> # ↓を読み込む (レイアウト)
    • <%= content_for :hoge do %> # ↑に読み込まれる (ビューテンプレート)
    • <%= if content_for? hoge %> # 分岐もできる
  • JSONの出力
    • jbuilderはRails4デフォルト
    • json.name @user[:name] # hoge.json.jbuilder
  • ヘルパー
    • <%= form_for :form do |f| %> # authenticity_tokenが隠しフィールドとして作られる
    • # 手動で作る
    • f.text_field :name, size: 40 # id="form_name" name="form[name]" size=40
    • f.text_area :message, size: "40x3" # cols="40" rows="3"
    • f.hidden_field :secret
    • f.password_field :password
    • f.check_box :hoge
    • f.radio_button :foo
    • f.label :hoge, "ほげ"
    • f.collection_radio_buttons(:item, item.all, :name, :price)
    • f.button "fooooo", type: :reset # default submit
    • f.button(type: 'button') do
    • content_tag(:strong, 'ほげ') # ほげ
    • f.submit # button, submitは Create User, Update Userとか表示される
    • f.range_field :range, min: 0, max: 100, step: 20
    • f.search_field :keyword
    • f.date_field :date
    • f.telephone_field :tel # input type="tel"
    • f.select :rank, ["a", "b"] # a</>b</> f.select :color, {"a" => "red", }, {include_blank: "foo"} # foo</>a</>
    • f.collection_select(:area, Area.all, :id, :name)
    • image_tag 'logo.png', alt: "logo", width: 320, height: 240 # /app/assets/images/logo.png
    • image_tag 'logo.png', alt: "logo", size: "320x240" # ↑と同じ
    • image_tag 'logo.png' # alt="logo.png"
    • form_for @order do |f| # accepts_nested_attributes_for :order_details
    • f.fields_for :order_details do |builder| # @order.order_details
    • builder.text_field :item                # @order.order_details[i].item
      
    • builder.number_field :count             # @order.order_details[i].count
      
    • ↑のコントローラ params.require(:order).permit({order_details_attributes: [:id, :item, :count]})
    • app/helpers
    • helper_method :hoge # viewで使用できるようにする
    • app/controllers/concerns
      • module Hello # コントローラ側でinclude Helloするとhelloが使える
      • extend ActiveSupport::Concern
      • included do
      • helper_method :hello
        
      • end
      • private def hello
      • end
  • その他
    • フラグメントキャッシング
      • ビュー内のブロック単位のキャッシング、デフォルトではproductionのみ
      • config/environments/development.rb config.action_controller.perform_caching = true
      • <% cache do %> # <% cache('key') do %> とすると、キャッシュブロックを分けられる
      • キャッシュされる
      • <% end %>
      • config.cache_store = :file_store # default時(tmp/cache) :memory_storeに変更できる
      • expire_fragment(controller: 'hoge', action: 'index', action_suffix: 'key') # キャッシュを期限切れにする
    • ディレクティブ
      • *= require_tree . # カレントディレクトリ以下を再帰的に読み込む
      • *= require_self # このファイルを読み込む
      • *= require jquery # gem jquery を読み込む
      • *= require_directory # 指定したディレクトリ
      • *= include # 指定したファイル
      • *= でも //= でも #= でもいい
      • <%= style_sheet_link_tag 'application' %> # 読み込む
      • <%= javascript_include_tag 'application' %>
    • ajax
      • gem 'jquery-rails'
      • *= require jquery_ujs
      • <%= link_to '削除', user, method: :delete, remote: true %> # data-remote: はAjaxで実行される
      • コントローラ側で respond_to do |format| format.js {render text: ''} # Ajaxリクエストに応答
      • Ajaxの結果はajax:success, ajax:errorイベントとかをjs側で使う

ActionMailer 5%

  • (メール)
    • rails g mailer UserMailer welcome
    • config/environments/development.rb
      • config.action_mailer.smtp_settings = { address: '', port: , user_name: '', password: '''}
      • config.action_mailer.delivery_method = :smtp # :sendmail, :file, :test
    • attatchments['hoge.png'] = File.read("/Users/hoge.png") # ビューでは
    • attatchments.inline['foo.png'] = File.read("/Users/foo.png") # <%= image_tag attachments['foo.png'].url %>
    • def receive(email)
    • p email.subject, email.body
    • if email.has_attachments?
  • メールの送信
    • welcome.deliver

テスト 10%

  • ユニットテストにおけるテスト手法
    • class HogeTest < ActiveSupport::TestCase
    • test "fooo bar test" do
    • assert_equal "lllllllll"
      
    • rake test # testは省略可
    • BACKTRACE=1 rake test # 完全なバックトレースを表示する
  • モデルのテストとコントローラのテスト
    • test/models
      • test "hoge foo bar" do
      • user = User.create(name: '')
      • assert_equal('', user.name)
      • assert user.errors.any?
      • assert user.errors[:nae].include? "can't be blank"
      • test "hoge" do
      • assert_difference('User.count', 1) do # 1増えるのを確認
      • user = User.create(name: 'taro')
        
    • test/controllers
      • class HogeControllerTest < ActionController::TestCase
      • test "foooo" do
      • get :new  # get :post, get :patch, get :delete, ...
        
      • assert_response :success  # :redirect, :missing, :error
        
      • assert_select('form')
        
      • assert_select("form input[name='user[name]']")
        
  • ヘルパー
    • ActiveSupport::Testing::Assertions
      • assert_difference, assert_no_difference, assert_not
    • Rails::Generators::Testing::Assertions
      • asser_class_method, assert_directory, ...
    • minitest/unitのリファレンスを読むこと

TODO

  • composed_of
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment