人生シーケンスブレイク

シーケンスブレイク(Sequence breaking、シークエンスブレイクとも)とは、テレビゲームにおいて開発が想定している攻略ルートを逸脱し、ショートカットする行為のことである。

Django 2.x で Sass / SCSS を使う

Django記事シリーズ

の3つ目。

で Sass / SCSS を使えるようにする。

以降のコードでは、 Django 2.x で Haml ライクな Bootstrap 4 を使う - 人生シーケンスブレイク まで実施したので Hamlpy や Bootstrap 導入済みだが別に無くてもOK。

必要なライブラリをインストールする

まず、 GitHub - jrief/django-sass-processor: SASS processor to compile SCSS files into *.css, while rendering, or offline. を参考にインストールを行う。

$ pip install libsass django-compressor django-sass-processor

# requirements.txt も更新しとく
$ pip freeze > ./requirements.txt

各ライブラリは、

となっている。

alpineでこれらをインストールするには以下を入れておけばよい。

FROM python:alpine

ENV RUNTIME_PACKAGES="gcc g++ musl-dev nodejs libxml2-dev libxslt-dev"
RUN apk --update add $RUNTIME_PACKAGES

hamlpy入れる為に記述したパッケージも含まれているので、Sass / SCSSだけなら musl-dev, nodejsは不要かも。

settings.py 編集

INSTALLED_APPSsass_processor を追加する。

INSTALLED_APPS = [
    ...
    'sass_processor',
    ...
]

下記も追加する。

# Sass(SCSS)
SASS_PROCESSOR_ROOT = os.path.join(BASE_DIR, 'static')
SASS_PROCESSOR_INCLUDE_FILE_PATTERN = r'^.+\.(sass|scss)$'
SASS_PRECISION = 8
SASS_OUTPUT_STYLE = 'compressed'
SASS_TEMPLATE_EXTS = ['.html', '.haml']

Bootstrapは SASS_PRECISION = 8 にしておく必要がある。

細かい設定は GitHub - jrief/django-sass-processor: SASS processor to compile SCSS files into *.css, while rendering, or offline. を参照。

Sass / SCSS 配置

先程のsettings.pyでは、 ./static をSASSのルートディレクトリにしたので、 ./static/stylesheets/style.sass にテストファイルを配置してみる。

body
  background-color: black

最近はSCSSよりSassの方が書いてて楽。

templates 編集

以下のコードはHaml

- load sass_tags

%link{ rel: 'stylesheet', type: 'text/css', href: "{% sass_src 'stylesheets/style.sass' %}" }

できた

以下のようになっていればOK. f:id:ShineSpark:20180323201450p:plain

参考として、↓のリポジトリソースコードを公開しています。 github.com

みんなのPython 第4版

みんなのPython 第4版

Django 2.x で Haml ライクな Bootstrap 4 を使う

Django記事シリーズ

の2つ目。

Django 2.x で Haml ライクなテンプレートを使う - 人生シーケンスブレイクdjango-hamlpyまで導入したものとする。

npm でパッケージ管理をする

JavaScript周りのパッケージは今後も入れる予定なので、npmでパッケージ管理を行う。

# packege.json ファイル生成
$ npm init

# パッケージインストールコマンド
$ npm install --save bootstrap

# bootstrapに必要な追加ライブラリもインストールする
$ npm install --save popper.js
$ npm install --save jquery

お好みで Font Awesome も入れてもいいと思う。

$ npm install --save font-awesome

インストールすると、/node_modules 以下にパッケージが入る。インストールしたパッケージはpackage.json, package-lock.json内にバージョンと共に保持される為、別環境では$ npm installコマンドを叩くだけで同バージョンがインストールされるようになる。

{
  "name": "django-test",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "bootstrap": {
      "version": "4.0.0",
      ...
    },
    "popper.js": {
      "version": "1.14.1",
      ...
    },
    "jquery": {
      "version": "3.3.1",
      ...
    },
    "npm": {
      "version": "5.7.1",
      ...

ライブラリをstaticアクセス可能にする

settings.py を編集し、/node_modules 以下のライブラリファイルに対して、/static/* でアクセス可能にする。

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
    os.path.join(BASE_DIR, 'node_modules'),
]

今回は /node_modules 以下はクライアント向けのライブラリしか利用していない & 簡略化の為にまるごと公開しているが、個別に公開してよりセキュアにしてもよいかも知れない。

ちなみに、Docker上で、ローカルの node_modulesとDockerコンテナ上のnode_modulesを共有したい場合には以下のように、 node_modules をマウントすればOK.

以下の例は docker-compose.yml + Dockerfileの構成。

  web:
    build: .
    command: python3 /code/manage.py runserver 0.0.0.0:8000
    ports:
      - '8080:8000'
    volumes:
      - ./mysite:/code
      - /code/node_modules
FROM python:alpine

ENV RUNTIME_PACKAGES="gcc musl-dev nodejs"

RUN apk --update add $RUNTIME_PACKAGES

RUN mkdir /code
WORKDIR /code

COPY mysite /code/

# for Django
RUN pip3 install -r /code/requirements.txt

# for Bootstrap
RUN npm install --verbose

Hamlファイルを編集する。

まずベースとなる base.html.haml を作り、ヘッダーやフッターはincludeして共通部分を作る。

layouts/base.html.haml

- load static

!!! 5
%html{ lang: 'ja' }
  %head
    %meta{ charset: 'utf-8' }
    %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, shrink-to-fit=no' }
    %title
      - block title
        ああああ
    %link{ rel: 'stylesheet', type: 'text/css', href: "{% static 'font-awesome/css/font-awesome.min.css' %}" }
    %link{ rel: 'stylesheet', type: 'text/css', href: "{% static 'bootstrap/dist/css/bootstrap.min.css' %}" }
    - block stylesheets

  %body
    - include 'layouts/_header.html.haml'

    .main.container-fluid
      - block main

    %script{ src: "{% static 'jquery/dist/jquery.min.js' %}" }
    %script{ src: "{% static 'bootstrap/dist/js/bootstrap.min.js' %}" }
    - block javascripts

_header.html.haml

ヘッダー部分。 ちなみにhamlpyでハイフンを含むプロパティを宣言する場合には、'data-toggle': 'collapse' のようにクォートで括ればOK.

%header.header.navbar.navbar-expand-md.navbar-light.bg-light
  %a.navbar-brand{ href: "#" }
    Navbar
  %button.navbar-toggler.hidden-md-up{ type: 'button', 'data-toggle': 'collapse', 'data-target': '#navbar-text', 'aria-controls': 'navbar-text', 'aria-expanded': 'false', 'aria-label': 'Toggle navigation' }
    %span.navbar-toggler-icon

  .collapse.navbar-collapse#navbar-text
    %ul.navbar-nav.mr-auto
      %li.nav-item
        %a.nav-link{ href: "{% url 'polls:index' %}" } Poll


    %form.form-inline
      %input.form-control.mr-sm-2{ type:'search', placeholder: 'Search', 'aria-label': "Search" }
        %button.btn.btn-outline-success.my-2.my-sm-0{ type: "submit" }
          Search

index.html.haml

メイン部分。base.html.hamlをextendsすることで呼び出す。

- extends 'layouts/base.html.haml'

- block main
  - if latest_question_list
    %ul
      - for question in latest_question_list
        %li
          %a{ href: "{% url 'polls:detail' question.id %}" }
            = question.question_text
  - else
    %p
      No polls are available.

ブラウザから確認

以下のようになっていればOK. f:id:ShineSpark:20180322203912p:plain

上手くいかない場合には、Chromeの開発者ツールでJSやCSSが正しく読み込まれてれているかチェックすると良い。

f:id:ShineSpark:20180322204451p:plain

参考として、↓のリポジトリソースコードを公開しています。 github.com

みんなのPython 第4版

みんなのPython 第4版

Django 2.x で Haml ライクなテンプレートを使う

Django記事シリーズ

の1つ目。

nyaruka/django-hamlpy を入れてHamlライクなシンタックスを実現する。

django-hamlpy は特にアナウンスされてないがDjango 2.0.3 でも動作が確認できた。また、Django 1.11.7でも以前に動作確認済み。
ちなみに上記のフォーク元の jessemiller/HamlPy はメンテされていないので現在は動かない。

導入手順

django-halmpyインストール

$ pip install django-hamlpy

補足: alpine環境でdjango-hamlpyインストールの際はgccmusl-devが事前に必要。

ENV RUNTIME_PACKAGES="gcc musl-dev"
RUN apk --update add $RUNTIME_PACKAGES

settings.py変更

テンプレートローダーへ追加

*.haml*.hamlpy ファイルをテンプレートとして読み込み可能にする為に、settings.pyのTEMPLATES内のloadersを以下のように書き換える。

TEMPLATES=[
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['./templates'],
        'OPTIONS': {
            'context_processors': [...] # 略
            'loaders': (
                'hamlpy.template.loaders.HamlPyFilesystemLoader',
                'hamlpy.template.loaders.HamlPyAppDirectoriesLoader',
            ), 
        }
    }
]

APP_DIRS オプションは loaders オプションと競合するので注意。

補足: テンプレートキャッシュを使う場合

本番環境などでテンプレートキャッシュを利用したい場合には、以下のようにする。

TEMPLATES=[
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['./templates'],
        'OPTIONS': {
            'context_processors': [...] # 略
            'loaders': (
                ('django.template.loaders.cached.Loader', (
                    'hamlpy.template.loaders.HamlPyFilesystemLoader',
                    'hamlpy.template.loaders.HamlPyAppDirectoriesLoader',
                    ...
                )),
            )
        }
    }
]

既存テンプレート書き換え

今回は Writing your first Django app, part 1 | Django documentation | Django の polls/index.html を例に書き換えしてみる。

Before: polls/index.html

{% load static %}

<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

After: polls/index.html.haml

- load static

  %link{ rel: 'stylesheet', type: 'text/css', href: "{% static 'polls/style.css' %}" }

- if latest_question_list
  %ul
    - for question in latest_question_list
      %li
        %a{ href: "{% url 'polls:detail' question.id %}" }
          = question.question_text
- else
  %p
    No polls are available.

views.py書き換え

template_nameを.haml付きに書き換える。

class IndexView(generic.ListView):
    template_name = 'polls/index.html.haml'

これでエラー無く表示できたらOK。

f:id:ShineSpark:20180312183805p:plain

参考として、↓のリポジトリソースコードを公開しています。 github.com

Railsで、後からcounter_cacheを追加した時にcounter_cacheの初期値を入れたい

サービスリリース後に counter_cache を追加したので、既存レコードのcounter_cacheをリセットしたくなった。

やり方

reset_counters メソッドを利用するとカウンターリセットできる。

Room.reset_counters(id, :column)

子要素の要素数に合わせて修正してくれるので、数値ズレが出てしまった際にも利用可能。

reset_counters (ActiveRecord::Base) - APIdock

適用

Railsコンソール上で、以下のように叩くと全レコードのカウンターをリセットできる。

Room.all.each {|i| Room.reset_counters(i.id, :messages_count)}

レコード数がそれなりにある場合には、 find_each を使う方が良い。

Room.find_each {|i| Room.reset_counters(i.id, :messages_count)}

# バッチサイズを変更したい場合
Room.find_each(batch_size: 100) {|i| Room.reset_counters(i.id, :messages_count)}

migration file にそのまま書いてしまう場合はこう

class AddMessagesCountToRoom < ActiveRecord::Migration
  def up
    add_column :rooms, :messages_count, :integer, default: 0
    Room.find_each {|i| Room.reset_counters(i.id, :messages_count)}
  end
 
  def down
    remove_column :rooms, :messages_count, :integer
  end
end

メタプログラミングRuby

メタプログラミングRuby

Rails5で、Railsコンソールでupdated_atを更新せずにカラムを更新する

環境

状況

  • インターネットで調べた User.record_timestamps = false などを行っても、updated_atが更新されてしまった。
  • mysqlのテーブル情報を確認したら、ON UPDATE CURRENT_TIMESTAMP が付いていた。
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

対応

updated_at カラムに直接元のupdated_atを指定するSQLを実行したらupdated_atを更新せずに更新できた。

User.connection.execute("UPDATE users SET published_at = created_at, updated_at = updated_at WHERE published_at IS NULL")

メタプログラミングRuby

メタプログラミングRuby

使わないiOS Simulatorを削除する

Xcode上で古いiOS Simulatorが残ったままになっている為、手動で削除する。

f:id:ShineSpark:20180309150323p:plain

ここに古いSimulatorが残っている状態なのを解消する。

Runtimeを削除する

/Library/Developer/CoreSimulator/Profiles/Runtimes から、不要なシミュレータのバージョンのディレクトリを削除する。 rmtrash を使っている人はrmをシングルクォートで括って実行しよう。

/Library/Developer/CoreSimulator/Profiles/Runtimes $ sudo 'rm' -rf iOS\ 10.1.simruntime/
/Library/Developer/CoreSimulator/Profiles/Runtimes $ sudo 'rm' -rf iOS\ 10.3.simruntime/

シミュレータ環境の削除

~/Library/Developer/Xcode/iOS DeviceSupport にもバージョンごとにディレクトリが作成されているので、ここも削除する。

~/Library/Developer/Xcode/iOS DeviceSupport $ ll
total 0
drwxr-xr-x   6 user  staff   192B  1 25 14:41 ./
drwxr-xr-x  32 user  staff   1.0K  1 24 15:48 ../
drwxr-xr-x   5 user  staff   160B  1 25 12:00 11.2 (15C114)/
drwxr-xr-x   5 user  staff   160B  1  5 15:42 11.2.1 (15C153)/
drwxr-xr-x   5 user  staff   160B  1 16 12:55 11.2.2 (15C202)/
drwxr-xr-x   5 user  staff   160B  1 25 12:49 11.2.5 (15D60)/

自分は一度まっさらな状態にしたかったので全て消した。

~/Library/Developer/Xcode/iOS DeviceSupport $ rm 11.2*

確認

Xcodeを再起動して、Simulator一覧を確認したら、古いバージョンのものが削除されていることを確認。

f:id:ShineSpark:20180309150323p:plain

ビルド対象の一覧からも、不要なものが削除されていることを確認した。
(シミュレータ起動時に自動で再作成される)

f:id:ShineSpark:20180309154740p:plain

参考

特定ディレクトリ配下のgitリポジトリのみ別のconfig設定を適用する

デフォルトはGitHub用の設定を利用しているが、会社で利用しているGitLabだけhttp.proxyを適用したい際に以下の方法で実現した。

前提

以下のようなディレクトリ構成を想定

~/git/
├── GitHubのリポジトリ1
├── GitHubのリポジトリ2
├── ...
└── office/ # このディレクトリ配下のみ別の git config を適用したい
    ├── 会社用のリポジトリ1
    ├── 会社用のリポジトリ2
    └── ...

手順

~/.gitconfig に以下の設定を追記する

[includeIf "gitdir:~/git/office/"]
  path = ~/git/office/.gitconfig

会社用の設定を .gitconfig ファイルに記述する

このケースでは、 ~/git/office/.gitconfig に記述する。 以下の記述内容は例。

[user]
    name = <name>
    email = name@example.com
[http]
    proxy = proxy.example.com:8080

使う

~/git/office/ 以下では、~/git/office/.gitconfig の設定もインクルードされる。

リポジトリ単位で個別に設定する必要がなくなるので非常に便利。

参考: Git - git-config Documentation

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

  • 作者:湊川 あい
  • 発売日: 2017/04/21
  • メディア: 単行本(ソフトカバー)