Pythonとサラリーマンと

2020年6月にPythonを始めたサラリーマンのブログです。

Rails 5.2 credential.yml.encについて調べたこと

credential.yml.enc

production環境用の秘密情報(Credentials)を記述するためのファイル。
Rails5.2から採用された。
それまでは別の方法で秘密情報を管理していた。

使い方

credential.yml.encにawsなどの外部サービスへ接続するためのキーを記述する。
このファイルは暗号化されているため直接編集ができない。
編集するには、以下のRailsコマンドを使用する。

$ rails credentials:edit

環境変数にデフォルトエディタを登録していない場合は、以下。

$ EDITOR="vi" bin/rails credentials:edit

こうすることでターミナルからcredential.yml.encを編集できる。

どうやって複合しているのか?

master.keyというファイルに複合化キーが記載されている。
Rails 5.2でrails newすると、credential.yml.encとmaster.keyファイルは自動的に作成される。
master.keyは超重要情報なので、初めから.gitignoreの対象になっている。

Herokuへmaster.key情報を渡すためには

.gitignoreになっているので普通にgit push heroku masterしてもmaster.keyファイルはHerokuに渡っていない。 そのため、以下を実施する必要がある。

$ heroku config:set RAILS_MASTER_KEY=マスターキーファイルの値

設定でmaster.keyのHerokuアップ忘れを防止

以下をconfig/environment/production.rbに設定。
これによりmaster.keyが設定されていなければエラーが出るようになる。

config.require_master_key = true
#コメントアウトするだけ

secret_key_baseについて

credential.yml.encに初期状態で入っているsecret_key_baseは、暗号化cookieや署名つきcookieの生合成確認に利用される。
これも超大事な秘密鍵なので、もしも漏れたなら以下のコマンドで再生性すること。

$ rails secret

HerokuにPushしてcssとjavascriptが反映されていないとき:Rails5

CSS

・本番環境では、アセットパイプラインを通る処理が自動実行されない
→Herokuなどの本番環境でcssjavascriptが反映されない

・解決策は2つ
→本番環境上でアセットパイプラインを通るようにプリコンパイル処理を実行する
→Herokuにファイルを送付する前に

$rake assets:precompile RAILS_ENV=production

を実行。

or

→本番環境時でアセットパイプラインを自動で通るように設定を変更する
→config/production.rbのファイルの

config.assets.compile = false

をtrueに変更。

Javascript

・Asset PipelineでJavascriptが読み込まれる仕組みは以下

nisshiee.hatenablog.jp

・上記の記事の通りDevelop環境とProduction環境ではCSS/Javascriptが読み込まれる仕組みが違う
 →そのため、application.jsの各種ライブラリを読み込む順序が大切
  →以下の記事の通りBootstrapはjqueryの後に読み込まれないといけない

lilac-xi.hatenablog.com

・で、筆者がハマったのは、

 ・Bootstrapは反映されたが、Chartkickが反映されていなかった
 ・ChromeのコンソールでChrtkickに以下のエラーが発生してた

uncaught referenceerror: chartkick is not defined

 ・で、その周りばっかり調べてたけど、上記エラーより前に出ていた、以下のエラーがそもそもの原因のようだった

uncaught typeerror: cannot read property 'fn' of undefined

 ・一番最初の記事の通り、Production環境ではJavascriptで一つエラーが出ると、そのあとのコードが実行されない

 ・Develop環境ではtypeerrorが出てもChartkickが読み込まれてたが、Prodction環境では、そうはいかない、という感じ

Rails5でReact使うとき実施すること

・gemファイルに以下を追記

  gem 'react-rails'
  gem 'webpacker'
  gem 'foreman' #group :development doに

・ターミナルで以下を実行

$bundle install
$rails webpacker:install
$rails webpacker:install:react
$rails generate react:install

・views/application.html.erbで以下の変更

<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

・foreman startのためのprocファイル作成
(react-rails使えばrails sでもjavascript反映されるっぽいので不要かも)
アプリのルートディレクトリにProcfileというファイル名で

rails: rails s --port=3000
webpack: bin/webpack-dev-server

→ これで、

$foreman start

することで

$rails s
$bin/webpack-dev-server

の両方を実行できる。
(foreman startが失敗するときは、gem install foremanを実施)

コンポーネント作成

rails g react:component コンポーネント名

・Viewのコンポーネントを呼び出したいところで

<%= react_component("コンポーネント名", {プロップス名: 値})%>

React 備忘録 Progate

・return()の中に処理を記載する

・JSX = Javascriptのなかでhmtl構文のような構文をかける
→render()メソッドの中のretrurn()の中にJSXを記述する
→return()のなかは複数要素を一つの要素にまとめないといけない
(複数要素のままではエラー)
→JSXの中でJavascriptの変数を呼び出す場合は{}で囲む
→JSX内で同じクラスのメソッドを呼びだすときはthis.メソッド名

・JSXでは、/ / でコメントアウト

・JSXとHTMLでは書き方が微妙に異なってる

例えば、

<img src='画像のURL'>は  
<img src='画像のURL'/>  

・render()メソッドの中でも、return()の外ではjavascriptがかける
→return()の中ではJSXを記述する
→returnの中でJavascriptを使いたい場合は{}で囲む
(変数など)

・JSX部分、つまりreturn内ではコメントは/ /になる
Javascript内では、コメントはあくまで//

・JSXにボタン要素などが用意されている

・イベント
→イベントを使って、何かが起こった時に、処理を実行するように指定できる
→書き方は

<button イベント名={() => {処理} }> </button>

→のように、タグ内にアロー関数を記載する
→アロー関数はJavascriptなので{}で囲む必要あり
→使えるイベントは、JSXであらかじめ用意されている

onClick → ボタン押されたら

・state
→ユーザの動きに合わせて変わる値のこと
→stateの定義・stateの表示・stateの変更

・stateの定義

constructor(props) {
  super(props);
  this.state = {name: 'にんじゃわんこ'};
 }

→ stateの定義はオブジェクトを使って定義する。
プロパティと値を自分で決める。
constructor(props)/ super(props)は定型文。

・stateの表示 →
render()メソッドの return()の中で定義したstateを呼び出せる

constructor(props) { }
render() {

 return( <h1> {this.state.name} </h1> );

 }
}

・stateの変更

イベントの関数の中でthis.setState()を使えばstateの値を変更できる

<button onClick={ () => {
  this.setState({name: "にんじゃわんこ"})
}}></button>

・stateの変更はイベント操作をメソッド化しておくと便利

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name: 'にんじゃわんこ'};
  }
  
  // handleClickメソッドを定義してください
  handleClick(name) {this.setState({name: name})}
  
  render() {
    return (
        <div>
          <h1>こんにちは、{this.state.name}さん!</h1>
          {/* onClickイベント内の処理を、handleClickメソッドを呼び出す処理に書き換えてください*/}
        <button onClick={() => {this.handleClick("ひつじ仙人")}}>ひつじ仙人</button>
        
          {/* onClickイベント内の処理を、handleClickメソッドを呼び出す処理に書き換えてください*/}
        <button onClick={() => {this.handleClick("にんじゃわんこ")}}>にんじゃわんこ</button>
      </div>
    );
  }
}

・Reactの処理の流れ
→ xx.js/ index.js/ index.htmlの3つのファイルを用いる。
xx.js -> 処理(JSX)の内容を書く index.js -> xx.jsの処理(JSX)をhtmlに変換し、ここで指定したhtmlのidへ変換後のコードを挿入する。
index.html -> reactの内容を表示したい場所をid指定してく

・JSXにスタイルをつける
→ JSX内のhtmlタグには、ちゃんとCSSのスタイルが適用される。
タグにクラスをつけるときは、className='title'というようにclassNameを使うことに注意

コンポーネント

Webページの画面を部品に分けて作る。 React.Componentクラスを継承して作る。

import React from 'react';

class Language extends React.Component{
 render(){
  return(

   JSX

    )
  )}
}

・各種コンポーネントは、export/importと<コンポーネントクラス名/>を使って一つのJSファイルにまとめるっぽい 直接呼び出さない。
→index.jsで呼び出すファイルのJSXに記載する

コンポーネントは一度作れば、何度でも呼び出せる

・JSXの中で呼び出すコンポーネントへpropsを使って値を渡すことができる

<コンポーネントクラス名 
  props名=値
  props名=値
>

・propsを私たコンポーネントの中でthis.props.プロップス名とすれば指定の値を表示できる

・配列のmapメソッドで連続した同じコンポーネントの値を自動で変更していく →別ファイルのコンポーネントを呼び出し、自らのコンポーネントを定義する

mport React from 'react';
import Lesson from './Lesson';

class Main extends React.Component {
  render() {
    const lessonList = [
      {
        name: 'HTML & CSS',
        image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/html.svg',
      },
      {
        name: 'Sass',
        image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/sass.svg',
      },
      {
        name: 'JavaScript',
        image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/es6.svg',
      },
      {
        name: 'React',
        image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/react.svg',
      },
    ];
    
    return (
      <div className='main-wrapper'>
        <div className='main'>
          <div className='copy-container'>
            <h1>Hello, World.</h1>
            <h2>プログラミングの世界へようこそ!</h2>
          </div>
          <div className='lesson-container'>
            <h3 className='section-title'>学べるレッスン</h3>
            {/* lessonListに対して、mapメソッドを用いてください */}
            {lessonList.map((lessonItem) => {
            return(
              <Lesson
                  name={lessonItem.name}
                  image={lessonItem.image}
                />
              )
            }
             )
            }
            
          </div>
        </div>
      </div>
    );
  }
}

export default Main;

・JSファイルの分け方例 f:id:minipe555:20190817165900p:plain f:id:minipe555:20190817170200p:plain

・ifによって表示する内容を変更するコンポーネント

import React from 'react';

class ContactForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      /* isSubmittedというstateを定義してください */
      isSubmitted: false
    };
  }

  render() {
    /* 空の変数contactFormを定義してください */
    let contactForm;
    
    /* isSubmittedを条件式とするif文を作成してください */
    if(this.state.isSubmitted === true){
        contactForm = (
        <div className='contact-submit-message'>
          送信完了
        </div>)
    }
    else{
      contactForm = (
        <form>
          <p>メールアドレス(必須)</p>
          <input />
          <p>お問い合わせ内容(必須)</p>
          <textarea />
          <input
            type='submit'
            value='送信'
          />
        </form>
        )
    }
    
    return (
      <div className='contact-form'>
        {contactForm}
        
        
        {/* 削除ここまで */}
      </div>
    );
  }
}

export default ContactForm;

・入力値のstate管理

stateで入力値を管理して、{input value=}で紐付ける

・入力イベントはonChangeイベントで取得

eventとevent.taerget.value

import React from 'react';

class ContactForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isSubmitted: false,
      email: '',
      hasEmailError: false,
    };
  }

  handleEmailChange(event) {
    const inputValue = event.target.value;
    /* 定数isEmptyを定義し、入力チェックの結果を代入してください */
    const isEmpty = inputValue === '';
    
    /* hasEmailErrorを更新してください */
    this.setState({email: inputValue, hasEmailError: isEmpty});
    
  }

  handleSubmit() {
    this.setState({isSubmitted: true});
  }

  render() {
    let emailErrorText;
    if (this.state.hasEmailError) {
      emailErrorText = (
        <p className='contact-message-error'>
          メールアドレスを入力してください
        </p>
      );
    }

    let contactForm;
    if (this.state.isSubmitted) {
      contactForm = (
        <div className='contact-submit-message'>
          送信完了
        </div>
      );
    } else {
      contactForm = (
        <form onSubmit={() => {this.handleSubmit()}}>
          <p>メールアドレス(必須)</p>
          <input
            value={this.state.email}
            onChange={(event) => {this.handleEmailChange(event)}}
          />
          {emailErrorText}
          <p>お問い合わせ内容(必須)</p>
          <textarea />
          <input
            type='submit'
            value='送信'
          />
        </form>
      );
    }

    return (
      <div className='contact-form'>
        {contactForm}
      </div>
    );
  }
}

export default ContactForm;

・isEmpty = inputValue === '' → inputValueが空文字列かどうかを代入

Javascript 備忘録(Progate)

・console.log("hello, world");

丸括弧内に入力された文字をコンソールに出力
コンソールとはWebコンソールのこと
文字列はシングルクオート or ダブルクオート
文章の最後はセミコロン;で終了

・コメントは//

・コンソールログは数字もOK

console.log(4+5);
* 掛け算
/ 割算
% 余り

・文字列の連結

console.log("文字列の" + "連結")

・変数

let 変数名 = 値; で定義

let name = "Jone";  
console.log(name);  
#=> Jone  

・式の中で変数を使う

let name = "Jone";
console.log( name + "Michel" );

let number = 5;
console.log( number + 6 );

・望ましい変数 nubmer
oddNumber

・変数の再定義
→ letはいらない

let name = Jone;
name = Michael;

・変数の中身の数値へ足し算し、変数を書き換える

let number = 5;
number = number + 5;
number += 5;

・定数

const 定数名 = 値 定数は値を更新することができない

const name = Jone;

・テンプレートリテラル(式展開みたいな)
→ 文字列の中に定数や変数を埋め込める
${定数 or 変数}
テンプレートリテラルを使うときはバッグクオートで囲む

const name = "ともあき";
console.log(`こんにちは。${name}さん`);

・条件式
if (条件式) { 処理; }

if (条件式) { 条件がtrueの処理; } else {  条件がfalseの処理; }

if (条件式A) { 条件Aがtrueの処理; } else if(条件式B) {  条件Bがtrueの処理; } else { AもBもfalseの処理; }

・比較演算子

console.log(number > 10)
#=> true

・等価演算子

=== 等しい
!== 等しくない

・かつ &&

number > 10 && number < 5

・または ||

x < 10 || x< 5

・switch文

switch (条件の値) {
   case 値1 :
   条件の値が値1と等しい場合の処理;
   break;
   case 値2 :
   条件の値が値2と等しい場合の処理;
   break;
   default:
   caseのどれにも一致しなかった場合の処理;
   break;
}

breakが重要。これがないと次のcaseも評価してしまう。
defaultはelseみたいなもの。
条件が多いときはswitch文の方が読みやすくなる。

・繰り返し処理 while

while(条件) {
   処理+
}

let number = 1;

while(number <= 100){
   console.log(number);
   number += 1
}

・繰り返し処理 for(whileよりシンプル)

for(変数の定義 ; 条件式 ; 変数の更新{
   処理;
}

for(let number = 1 ; number <= 100 ; number ++){
  console.log(number);
}

・number += 1 と number ++ は同じ

・number -= 1 と number -- は同じ

・配列 []

const animals = ["cat", "dog", "sheep"];

console.log(animals);
console.log(animals[0]);

・配列の要素の上書き

animals[0] = "mouse"

・配列の要素数の取得
→ anmimals.length

・オブジェクト(rubyのハッシュ)

{ プロパティ1 : 値1, プロパティ2: 値1 }
{ name: "手裏剣",  price: 300}

・オブジェクトの値の取り出し方

console.log(anminals.name);

・オブジェクトを要素を持つ配列

[{プロパティ1: 値1, プロパティ2: 値2}]
const = items [
{name: "手裏剣", price: 300},
{name: "忍者刀", price :1200}
];

console.log(items[0]);
console.log(items[1].price);

・存在しないインデックス番号やプロパティを指定した場合

undefinedと出力される。
undefinedは値が定義されていない、という意味。

・undefinedと出力したくない場合、ifを使って回避する

for (let i = 0; i < characters.length; i++) {
  console.log("--------------------");
  
  const character = characters[i];
  
  console.log(`名前は${character.name}です`);

  if(character.age === undefined) {
    console.log("年齢は秘密です");
  } else {
    console.log(`${character.age}歳です`);
  }
  
}

・オブジェクトの値には、オブジェクトを用いることもできる
→オブジェクト名.プロパティ.プロパティで呼び出す

const character = {
 name: "にんじゃわんこ",
 favatrite: { food: "ラーメン"
 },
};
console.log(character.favarite);
console.log(character.favarite.food);

・関数
→いくつかの処理をまとめたもの

const introduce = function() {
  console.log("hello");
  console.log("goodbye");
}

introduce(); ⇦これが関数の呼び出し方法

・アロー関数 →関数をシンプルに記載する(ES6から導入)

const introduce = () => {
処理
}

・引数 →関数に与える追加情報
→引数は複数個設定できる、第一引数, 第二引数といった感じ

const introduce = (name) => {
  console.log(name);
}

introduce("にんじゃわんこ");

・戻り値
→returnを使うことで関数の処理結果を呼び出し元で受け取れる
→定数や変数に代入して使う
→比較演算子など使うと、戻り値にtrueやfalseを返せる
→returnの後の処理は実行されない(returnは関数を終わらせる)

・引数と関数の中の定数や変数
→その関数の中でしか使えない
→定数や変数を使える範囲のことをスコープという
→関数の外で定義した定数や変数は冠すの中でも使える

・オブジェクトの値には関数を用いることができる

const 定数名 = {
 プロパティ名: () => {
  処理;
 }
};

定数名.プロパティ名();  ⇦ オブジェクトの値が関数の場合の呼び出し方

・クラス

class クラス名 {

}

class Animal {

}

const animal = new Animal(); ⇦インスタンス作成

・コンストラク
インスタンスが生成された時に実行したい処理

class Animal {
 constructor() {
 
 }
}

インスタンスにプロパティと値を持たせる
→コンストラクタに設定 f:id:minipe555:20190815153924p:plainインスタンス.プロパティでクラスの外で呼び出せる

・コンストラクタに引数を渡す

class Animal [

  constructor(name, age) {

   this.name = name;
   this.age = age;
  }
}

→new Animal()の()はコンストラクタの()やな

・メソッド
→ メソッドはdefとか不要。
クラウスの中にgreet(){}とか書き出せが良い。

class Animal {

 constructor(){

  {

  greet)0{

  }
}

・メソッド内でインスタンスの値を使う
→this.nameはどthis.プロパティ名でOK

・メソッド内で他のメソッドを呼び出す
→this.メソッド名

・継承の仕方

class Dog extends Animal {

}

→サブクラスはスーパークラスの全ての機能を引き継ぐ

・サブクラスでスーパークラスと同名のメソッドを定義した場合、オーバーライドされる。

・コンストラクタのオーバーライド

constructor(name, age, greet) {

  super(name, age);

 this.greet = greet

}

→super()でスーパークラスのコンストラクタを呼び出す

・クラスを他のファイルで使えるようにする

class Animal {

}
export defaule Animal;
clas Dog {

}
import Animal from "./Animal.js";

・エクスポートはクラスだけでなく、値や関数もエクスポートできる

・デフォルトエクスポート
→export default 値; →importするときは、値の名前が違っても問題ない
→デフォルトエクスポートでは、必ずdefault 値の値が読み込まれるから
→デフォルトエクスポートは1つのファイルで1回まで使える

・名前つきエクスポート

export (値, 値};

→インポートするときも{}で囲む

・パッケージをインポートする

import 定数名 form "パッケージ名";

→世にあるパッケージを使えば、色んなことができる

・pushメソッド
→配列の最後に新しい要素を追加する

const numbers = [1, 2, 3];
numbers.push(4);

・forEachメソッド
→配列の要素を1つ1つ取り出して、同じ処理を行う

const numbers = [1, 2, 3];
numbers.forEach((number) => {
 console.log(number)
});

→() => {} はアロー関数
→引数に入っている関数のことをコールバック関数と呼ぶ

・findメソッド →コールバックメソッドの処理部分に記述した条件に合う、一つ目の要素を取り出す

const numbers = [1, 3, 5, 7, 9];

const foundNumber = numbers.find((number) => {
  return number % 3 === 0;
});

const characters = [
  {id: 1, name: "にんじゃわんこ", age: 6},
  {id: 2, name: "ベイビーわんこ", age: 2},
  {id: 3, name: "ひつじ仙人", age: 100},
  {id: 4, name: "とりずきん", age: 21}
];

const foundCharacter = characters.find((character) => {
  return character.id === 3;
});

・filterメソッド
→条件に合った全ての要素を取り出す →使い方はfindと同じ

・mapメソッド
→配列の全ての要素に同じ処理を行い、新しい配列を作り直す

・コールバック関数
→ある関数の引数に渡される関数のこと
→とある関数に処理を加えて、新しい関数を作ることができる

const printWanko = () => {
  console.log("にんじゃわんこ");
};

const call = (callback) => {
  console.log("コールバック関数を呼び出します。");
  callback();
};

call(printWanko);

→さらには、callback引数に関数を書くこともできる

const printWanko = () => {
  console.log("にんじゃわんこ");
};

const call = (callback) => {
  console.log("コールバック関数を呼び出します。");
  callback();
};

call(printWanko);

call(() => {
  console.log("ひつじ仙人");
});

・コールバック関数に引数を持たせる

const call = (callback) => {
  callback("にんじゃわんこ", 14);
};

call((name, age) => {
  console.log(`${name}は${age}歳です。`);
});

Railsの備忘録(Rubyではなく)

・RaisはRubyで書かれているがRubyとは別物。
 Webアプリケーションを作りたいなら、最初にRailsを学び、Rubyを学んで、再びRailsに戻ってくるべき。

Railsではインスタンス変数を作るだけでビューで自動的に使えるようになる。