うめぼしジョイスティック - ivoice

CakePHP、JavaScript、jQuery等のプログラミングについて書いていきます 思考は、うめぼしのように硬く、そして柔らかく。

CloudflareでHerokuからRender.comにサイトを移動する方法

Herokuで独自ドメインを実現させるためにCloudflareを使用している場合は

example.comドメインの場合)

TYPE: CNAME

Name: example.com

Content example.herokuapp.com

というレコードと

TYPE: CNAME

Name: www

Content example.herokuapp.com

というレコードをDNSのRecordsに設定していると思いますが、それを

TYPE: CNAME

Name: example.com

Content example.onrender.com

TYPE: CNAME

Name: www

Content example.onrender.com

の2つに変更すればOKです。

Cloudflareでルートドメインからのアクセスをwww付きドメインに飛ばす方法

Herokuの無料プランではルートドメイン(wwwなし)が許可されていません。

なので、ルートドメインでのアクセスをwwwドメインにリダイレクトしておくと良いです。

その方法を簡単にメモしておきます。

今回参考にしたのは

『Heroku + Cloudflare』でルートドメインかつSSLでサイトを運用する | vdeep

こちらのブログです。

Cloudflare管理画面より、 「Page Rules」→「Create Page Rule」 でページのルールを設定します。

例えば自分のドメイン

sample.comだとすると、

設定画面のURLでは

最初のボックスに

sample.com/*

と書きます。(ルートドメインでのアクセスを想定)

その次の選択タブでは「Forwarding URL」(リダイレクト機能)を選択し、 右の選択タブで「301 - Permanent Redirect」を選びます。

最後のボックスに

https://www.sample.com/$1

のように記述します。

これで完了。

Cloudflareでは無料プランではページルールを3つまで作ることが出来ます。

書き方は

https://support.cloudflare.com/hc/en-us/articles/218411427

本家のこのページが参考になります。

最初に * (アスタリスク)で記述した部分を 反映させたい所では $1、$2、というように順番に記述する訳です。

お試し下さい。

AbstractController::Helpers::MissingHelperErrorっていうエラーが出た。

Railsをいじってたら「AbstractController::Helpers::MissingHelperError」というエラーが出ました。

環境:Windows10

stackoverflow.com

ここに書いてあったのですが、

e.g. when your Rails app is in a folder named RailsApp: PS C:>cd RailsApp PS C:\RailsApp>rails c production works just fine.

While PS C:>cd railsapp PS C:\railsapp>rails c production will fail.

Windows PowerShellコマンドライン)で、ディレクトリにたどり着くまでに ディレクトリ名の大文字の所を小文字にしたり(cd railsappのように)してたどり着いてしまって、 その状態でrails sをしようとするとエラーになるようです。

一旦Windows PowerShellを落としてから、もう一度正しいパス(文字)でディレクトリに行き、rails sをしたら動きました。

Railsのバージョンを上げた

Railsのバージョンを上げました。

Windows10環境で、Rails 5.1.6から Rails 5.2.1に。

【やったこと】

GemfileのRailsのバージョンを5.2.1に変更する

gem 'rails', '~> 5.2.1'

こういう感じ。

あと

gem 'bootsnap', require: false

Gemfileにこちらも追加する必要があるようです。

あとは、ターミナルで

rails s

をしようとすると、bundle installをしろ、等々言われるので、言われるがままに指示に従う。(bundle updateもしたかな??)

あ、参考にしたサイトは、

qiita.com

こちらです。ほぼこのまま。

私のは自分メモなので、こちらを参考にして下さい。

そのあと、上記のサイトにも書かれているように、ターミナルで

rails app:update

を実行。

そうするとどのファイルを上書きするか、しないか等々聞かれるので、config/application.rbやconfig/routes.rbあたりは上書きしないでおく。

(ここは慎重に1つ1つ確認。)

そして、終わったら

rails s

をして確認。

すると、エラーが出ました。

postgresqlのパスワードをdatabase.ymlのdevelopmentの部分に書かないとローカルで動かなくなりました。(パスワードが必要だよー!と出る)

以前はパスワードなしでもいけてたのですが。

そこで、デベロッパー環境のみにローカルのpostgresqlのパスワードを適用します。

database.ymlのバージョン管理についてはここ。

qiita.com

まずはターミナルで

git rm --cached database.yml

をして、Gitの管理の対象外にする。

そしてあと、

.gitignore ファイルに

/config/database.yml

とします。これで完全にdatabase.ymlはgitでリポジトリに上がらなくなります。

あとは、database.ymlをコピペして、dataase.yml.sampleというひな型のファイルを残してあげます。

そうしたらdatabase.ymlにdevelopment環境の部分のみにユーザー名とパスワードを記述。

development:
  <<: *default
  database: アプリ名_development
  #追記
  username: ユーザーネーム
  password: パスワード

ここの部分ですね。

ちなみに、PostgreSQLにターミナル経由で入って、「アプリ名_development」というデータベースを作っておかないといけません。

PostgreSQLの場合、デフォルトのユーザーネームはpostgresのようです。

他の参考にしたサイト

kawabatas.hatenablog.com


ちなみに、 コマンドプロンプトからPostgreSQLに接続するには

psql -U postgres

と打ち、パスワードを求められるので、設定したパスワードを打てばOKです。

参考:

www.dbonline.jp

Railsのあれこれ その5

既存のモデル(テーブル)にカラムを追加する

既存のテーブルに追加でカラムを追加します。 結構複雑です。

まず、ターミナルで

rails g migration add_image_name

このように、カラムを追加するためのマイグレーションファイルを追加します。 「add_image_name」というのがマイグレーションファイルの名前になります。 ここは任意でOK。

アプリ名>db>migrate の中に、

日付け_add_image_name

というファイルが追加されているはずなので、そこを編集します。

class Change < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :image_name, :string
  end
end

この場合は usersテーブルにimage_nameという文字列のカラムを追加します。

マイグレーションファイルのchangeメソッドの中に

def change
  add_column :テーブル名, :カラム名, :データ型
end

このように記述します。テーブル名はモデル名の複数形になるので注意しましょう。(例:Userモデルの場合、users)

そうしたら、 ターミナルで

rails db:migrate

と打ちます。 これで、さきほどマイグレーションファイルに書いた変更がデータベースに反映されます。 確認してみましょう。

image_name

という文字列のカラムが追加されているはずです。


画像を参照するときの書き方

これが結構地味に頭がこんがらがります。

<img src="<%= "/user_images/#{画像名}" %>">

このようにします。

画像名の変数が image_name だとすると

<img src="<%= "/user_images/#{image_name}" %>">

こうなる訳ですね。 外側の""ダブルクオーテーション2つは、ただのマークアップのための表示、 そして内側のダブルクオーテーション2つはrubyの変数を式として評価するためのものです。

<%= "#{image_name}" %>

このようになっていた場合、rubyでは image_nameを変数として出力する訳です。 今回は

<img src="<%= "/user_images/#{image_name}" %>">

となっているので、

<%= "/user_images/#{image_name}" %>

までがrubyの式として表示させたい部分ですね。 いちばん外側にあるダブルクオーテーションは「マークアップのためのダブルクオーテーションマーク」ということです。 いや~ややこしい。

この「rubyの式の展開」についてはよく覚えて、慣れておきましょう。

画像を登録する

画像です。画像の登録。

コントローラーのcreateでは、

  def create
    @user = User.new(name: params[:name], 
                    email: params[:email],
                    image_name: "default_user.jpg")
    
    if @user.save
      flash[:notice] = "ユーザー登録が完了しました"
      redirect_to("/users/#{@user.id}")
    else
      render("users/new")
    end
  end

のようにして、まずUser.newをするときに、画像にデフォルトの画像ファイルを設定します。

その次に、画像を編集する場合です。

edit.html.erbに

<p>画像</p>
          <input name="image" type="file">

を追加します。

input属性のnameはimageという名前にしましょう。 そして、ポイントはファイルタイプを「file」とすることです。 これで画像ファイルが取得できます。

ただし、送信フォームに

<%= form_tag("/users/#{@user.id}/update", {multipart: true}) do %>

のようにして、フォームに

{multipart: true}

をつけます。これをすることにより、ファイルが送信出来るようになります。

そして、コントローラーのupdateアクションでは「画像がある場合に登録する」 という処理を記載します。

ファイルがあるときのみ実行するif文を書きます。

  def update
    @user = User.find_by(id: params[:id])
    @user.name = params[:name]
    @user.email = params[:email]

    if params[:image]
      @user.image_name = "#{@user.id}.jpg"
      image = params[:image]
      File.binwrite("public/user_images/#{@user.image_name}", image.read)
    end

    if @user.save
      flash[:notice] = "ユーザー情報を編集しました"
      redirect_to("/users/#{@user.id}")
    else
      render("users/edit")
    end
  end

このようになります。

if params[:image]

の部分で、「画像がもしある場合」 として処理を実行しています。

ファイルを保存するには

File.binwrite("public/user_images/#{画像名}", 画像データ.read)

というようにして画像ファイルを入れる場所と、画像データを指定します。

上記では

 @user.image_name = "#{@user.id}.jpg"
 image = params[:image]
 File.binwrite("public/user_images/#{@user.image_name}", image.read)

の部分です。 public/user_images/ というフォルダに、画像を書き込んでいることが分かります。 この場合のファイル名はユーザーIDを使っています。

かなりややこしいですね。 binwriteメソッドとreadメソッドについても調べておきましょう。


Railsのあれこれ その4

ログイン・ログアウト処理はややこしい

ルーティングは

  get "login" => "users#login_form"
  post "login" => "users#login"
  post "logout" => "users#logout"

このように、ログアウトはpostになる。

new.html.erbのビューに

<% @user.errors.full_messages.each do |message| %>
    <%= message %> #エラーの表示
<% end %>

<%= form_tag("/users/create") do %>
  <p>ユーザー名</p>
  <input name="name" value="<%= @user.name %>">
  <p>メールアドレス</p>
  <input name="email" value="<%= @user.email %>">
  <p>パスワード</p>
  <input name="password" type="password" value="<%= @user.password %>">
  <input type="submit" value="登録">
<% end %>

このように書く。これはサインアップ(登録)画面。

ログイン画面は

login_form.html.erb というログイン用のビューに

<% if @error_message %>
    <%= @error_message %> #エラーメッセージを表示
<% end %>
<%= form_tag("/login") do %>
  <p>メールアドレス</p>
  <input name="email" value="<%= @email %>">
  <p>パスワード</p>
  <input type="password" name="password" value="<%= @password %>">
  <input type="submit" value="Log In">
<% end %>

このように書く。フォームはログインに飛ばしている。

コントローラーは

def new
  @user = User.new
end

def create
  @user = User.new(
    name: params[:name],
    email: params[:email],
    image_name: "user_image.jpg",
    password: params[:password]
  )
  if @user.save
    session[:user_id] = @user.id
    flash[:notice] = "ユーザー登録が完了しました"
    redirect_to("/users/#{@user.id}")
  else
    render("users/new")
  end
end


def login_form
end


def login
  @user = User.find_by(email: params[:email], password: params[:password])
  if @user
    session[:user_id] = @user.id
    flash[:notice] = "ログインしたよ"
    redirect_to("/posts/index")
  else
    @error_message = "メールアドレスかパスワードが間違っています"
    @email = params[:email]
    @password = params[:password]
    render("users/login_form")
  end
end

def logout
  session[:user_id] = nil
  flash[:notice] = "ログアウトしたよ"
  redirect_to("/login")
end

このようになる。

「session」という変数の session[:user_id]に @user.id を入れて、ログイン認証をするところがポイントである。

また、全体に変数を適用する場合は before_actionを用いる。

class ApplicationController < ActionController::Base
  before_action :set_current_user  
  def set_current_user
    @current_user = User.find_by(id: session[:user_id])
  end
end

このように、ApplicationControllerでbefore_actionを定義し、 @current_userという変数にユーザー情報を入れる。

全コントローラーのアクションが実行される前にログインユーザーの情報を変数を入れているので、すべてのビューで@current_userという変数が使える。

Railsのあれこれ その3

editとupdateはややこしい

editアクションとupdateアクションは結構頭がこんがらがります。

まずルーティングは

  post "users/:id/update" => "users#update"
  get "users/:id/edit" => "users#edit"

こういう感じ。 この場合はusersコントローラのupdateとeditのアクションです。

コントローラーでは

  def edit
    @user = User.find_by(id: params[:id])
  end
  
  def update
    @user = User.find_by(id: params[:id])
    @user.name = params[:name]
    @user.email = params[:email]
    if @user.save
      flash[:notice] = "ユーザー情報の編集完了"
      redirect_to("/users/#{@user.id}")
    else
      render("users/edit")
    end
  end

このように記述します。

ビューですが、

updateアクションにビューは必要ありません。 データを更新するだけのアクションです。

editアクションのビューは

<% @user.errors.full_messages.each do |message| %>
          <div class="form-error">
            <%= message %>
          </div>
        <% end %>
        
        <%= form_tag("/users/#{@user.id}/update") do %>
          <p>ユーザー名</p>
          <input name="name" value="<%= @user.name %>">
          <p>メールアドレス</p>
          <input name="email" value="<%= @user.email %>">
          <input type="submit" value="保存">
        <% end %>

このようになります。

最初に

@user.errors.full_messages

でeach文を回して投稿エラーメッセージを表示させているのがポイント。

そのあとに、投稿用のフォームを書きます。 name属性にデータベースのカラムと同じ名前をつけて投稿。

params[:name], params[:email] で受け取れるデータを、

    @user.name = params[:name]
    @user.email = params[:email]

としてからセーブしているのがポイントです。

また、editアクションで投稿が失敗した際に

render("フォルダ名/ファイル名")

つまりは

render("users/edit")

となり、editについて、投稿失敗時のrenderではidは記述する必要がないのが大事なところです。


ルーティングの決まり(ログイン機能のsessionについて)

getは

■データベースを変更しない場合

に用いる。

postは

■データベースを変更する場合

■sessionの値を変更する時

に用いる。