TECH EXPERT 39日目

TECH::EXPERT

4日も連続でサボったので火水木金の4日で個人アプリ開発をするはめになった。まあなんとなく形になればいいか。とりあえず、軽量アプリをデプロイまでいきたい。

一応、基礎をやってた頃に作りかけにしたアプリがあるのでそれを実装まで持っていく。今日の段階で大枠は出来たので、あとはcssやhtmlをそれっぽくしあげれば明日にはデプロイできるかな。

ネックになっているのが自動的にスクレイピングを行う処理。cronってのがよくわからないのと、何分おきに実行させたらいいのか、その負荷はどの程度になるのかが判断しかねる。AWSに乗せた時に通信量オーバーで費用がかかるのも嫌だしね。

ruby

文字コード

.ord .chr

  • .ord ・・・ 文字コードに変換(整数)
  • .chr ・・・ 文字コードから文字に変換

.codepoints{|cp|ブロック}

文字列に対して使う。
1文字ずつ取り出して文字コードに変換し、ブロック処理を行って返す。

char = "frqjudwxodwlrq"
puts char.codepoints.collect{|cp| (cp-3)}.join("\\")
=> 99\111\110\103\114\97\116\117\108\97\116\105\111\110

文字のコードポイントを16進数で表示

char.codepoints {|cp| print cp.to_s(16)}

シーザー暗号

英字を3つずらして書く

puts char.codepoints.collect{|cp| (cp-3).chr}.join

classの定義

通常はこう。


class クラス名
end

ちょっと特殊なやり方。
このやり方だとHogeクラス内の処理でclassブロック外の変数も使える。
例だとHogeクラス以下の処理にaaaを呼ぶことができる。

aaa = fuga
Hoge = Class.new do
# 処理
end

定数にclassオブジェクトを渡してもclassが生成できる。

self.class.const_set :'Creature', Class.new do
# 処理
end

class内でclassを定義することもできるので動的な生成も可能。

rails

複数形

sをつける以外の複雑な複数形にも対応されている。
company -> companies

asset pipeline

アセットファイルを管理する仕組み。
アセットファイル = javascriptやcssなどの付帯情報

sprockets

Sprocketsは、そのAsset Pipelineの基盤となるgem。
アセットファイルのパス管理やコンパイルをしてくれる。

コンパイルする際にはマニュフェストファイルと呼ばれるapplication.cssやapplication.jsなどを元にファイルを参照する。

プリコンパイル

rake assets:precompile

public/assets/以下にコンパイルされたファイルが配置される。
production環境ではassetフォルダではなく、こちらを読みに行く。

scaffold

rails g scaffold product name:string price:integer

これを実行すると以下が作成される。
要点はmigrationファイル、コントローラ、ビュー(jsonも)
さらにルーティングやアセットファイルの作成まで。

Running via Spring preloader in process 56483
      invoke  active_record
      create    db/migrate/20190820033625_create_products.rb
      create    app/models/product.rb
      invoke    test_unit
      create      test/models/product_test.rb
      create      test/fixtures/products.yml
      invoke  resource_route
       route    resources :products
      invoke  scaffold_controller
      create    app/controllers/products_controller.rb
      invoke    erb
      create      app/views/products
      create      app/views/products/index.html.erb
      create      app/views/products/edit.html.erb
      create      app/views/products/show.html.erb
      create      app/views/products/new.html.erb
      create      app/views/products/_form.html.erb
      invoke    test_unit
      create      test/controllers/products_controller_test.rb
      create      test/system/products_test.rb
      invoke    helper
      create      app/helpers/products_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/products/index.json.jbuilder
      create      app/views/products/show.json.jbuilder
      create      app/views/products/_product.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/products.coffee
      invoke    scss
      create      app/assets/stylesheets/products.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss

Model

モデル内に定義したメソッドはモデルに対して使う。

モデル
def add_tax
  self.price = (price * 1.08).round
end

コントローラ
def create
  @product = Product.new(product_params)
  @product.add_tax
end

rails 新規プロジェクトの始め方

新規プロジェクトを作成

-dオプションで使うデータベースの種類を指定する。

rails new new_project -d mysql

rails gで不要なファイル群を作成しないように設定変更

config/application.rbに以下を記述

module NewProject
  class Application < Rails::Application
    config.generators do |g|
      g.stylesheets false
      g.javascripts false
      g.helper false
      g.test_framework false
    end
  end
end

Model関係

データベースの作成

rails db:create
or
bundle exec rake db:create

モデルの作成

rails generate model モデル名

migrationファイルとモデルが作成される。
model名を単数形で指定しておけば自動的にテーブル名は複数形にされます。

create    db/migrate/20190820042025_create_irs.rb
create    app/models/ir.rb

migrationファイルの編集

class CreateIrs < ActiveRecord::Migration[5.2]
  def change
    create_table :irs do |t|
      t.string           :title
      t.references       :company, foreign_key: true
      t.timestamps
    end
  end
end

foreign_keyを使う場合には関連テーブルが先に存在する必要があるので、migrationファイルを作る順序に注意してください。

asociationの設定

1対多

has_many :irs
belongs_to :company

多対多

has_many :users, through: :user_companies

Controller関連

controllerの作成

rails g controller コントローラー名

この際、特別な理由がなければコントローラー名は複数形で指定します。

create  app/controllers/irs_controller.rb
invoke  erb
create    app/views/irs
invoke  assets
invoke    coffee
invoke    scss

最初に出力されるファイルを変更しているので、ここではcontrollerとviewのみ生成されます。

Devise関連

細かいポイントはDeviseの使い方を参照。

Gemのインストール

 gem 'devise'
bundle install
rails g devise:install

ユーザーモデルの作成

rails g model hogehogeではなく、devise用のコマンドを利用する。

rails g devise user

model作成時と同様にmigrationファイルも作成される。

invoke  active_record
create    db/migrate/20190820051145_devise_create_users.rb
create    app/models/user.rb
insert    app/models/user.rb
  route  devise_for :users

必要に応じてmigrationファイルを編集します。
標準だとnameとか無いのでこんな感じで足します。

class DeviseCreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :name,               null: false, unique: true, index: true
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
rails db:migrate

params.permitに追加

application_controller.rbに増やした項目を受け取るように設定します。
devise_parameter_sanitizerはdeviseのメソッドなのでbefore actionも条件を付けておきます。

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
  end
end

Routing

devise_for :users以外には特に記載がないのでコントローラに対応するルートを作っていきます。
rootも設定します。

Rails.application.routes.draw do
  devise_for :users
  root  'hogehoges#index'
  resources :users, only: :show
end

View関連

hamlを使う前提です。

haml-railsのインストール

gem "haml-rails", "~> 2.0"
bundle install

erbファイルをhamlへ変換

rails haml:erb2haml

Would you like to delete the original .erb files? (This is not recommended unless you are under version control.) (y/n)

こんなことを聞かれるのでerbが不用ならdeleteします。

deviseのview

viewファイルの生成

rails g devise:views

deviseのview参照先を変更

config/initializers/divise.rb
#config.scoped_views = false
↓
config.scoped_views = true

これで対応するviewファイルを変更すれば反映されます。

CSS関連

application.css削除
application.scss追加し@import "hogehoges";と記載
hogehoges.scssを_hogehoges.scssへリネーム
_reset.scssを作成し、リセットCSS内容をコピペ
application.scssに@import "reset";と記載

whenever

GitHub - javan/whenever: Cron jobs in Ruby
CronjobsinRuby.Contributetojavan/wheneverdevelopmentbycreatinganaccountonGitHub.

定期的にバッチ処理をさせる。cronを簡単に使えるようにするgem。

gemfileに以下を追記してbundle install

gem 'whenever', require: false

設定ファイルを作成

bundle exec wheneverize .

dotが付いてるのを忘れずに。
実行されるとschedule.rbが作成されます。

[add] writing `./config/schedule.rb'
[done] wheneverized!

crontabを確認して設定

設定を確認。
以下のコマンドはscadule.rbをcrontabに変換して表示するのみで、書き込みも保存もしない。

bundle exec whenever

設定を反映するにはこっちを実行。

bundle exec whenever --update-crontab

設定を削除する場合はこちら。

bundle exec whenever --clear-crontab

Action Mailer

rails g mailer メーラー名

以下が生成される。

Running via Spring preloader in process 61351
      create  app/mailers/hogehoge.rb
      invoke  haml
      create    app/views/hogehoge_mailer

mailers/メーラ名.rb

いわゆるコントローラみたいなもの。
メーラーに対してアクション(?)を定義していく。

class HogeMailer < ApplicationMailer
  default from: "hogehoge@example.com"

  def fuga(com,ir,user)
    @com = com
    @user = user
    @ir = ir
    mail(
      subject: "IR from #{com.name}", 
      to: @user.email
    ) do |format|
      format.text
    end
  end
end

mailer/アクション名.text.erb

いわゆるviewファイル。通常のviewと同じ感じで書けばOK.
htmlでメールが送れない時に備えて、textファイルとhtmlファイルと用意するのが普通らしい。

/views/hoge_mailer/fuga.text.erb
<%= @user.name %> 様

<%= @com.name %> からIRの発表あり。
<%= @ir.title %> 

メールの送信

メーラー.アクション().deliverで順に指定すればOK。

HogeMailer.fuga(com, ir, user).deliver

letter_opener_web

gemfileに以下を追記

group :development do
  gem "letter_opener_web"
end

config/environments/development.rbに以下を記述。

  config.action_mailer.delivery_method = :letter_opener_web

routes.rbに以下を追記。

  if Rails.env.development?
    mount LetterOpenerWeb::Engine, at: '/letter_opener'
  end

コメント