seedデータの変更は削除する必要がある!

ハマったエラーについて書いていきます

 

  • エラー時の状況

CRUD処理実装と'devise' gemでログイン処理を実装後に、localhost:3000で入ると

undefined method 'id' for nil:Nil Class

というエラーが出る

 

この時の主なコードはこちら

  • ルート

Rails.application.routes.draw do

  root to: 'posts#index'

  devise_for :users

   resources :posts

   resources :users, only: :show

end

  • コントローラ

Postsコントローラ

class PostsController < Application Controller

  before_action :move_to_index, except: :index

  

  def index

    @posts = Post.all

  end

 

  def new

    @post = Post.new

  end

 

  def create

    Post.create(content: post_params[:content], user_id: current_user.id)

  end

 

  def move_to_index

    redirect_to action: :index unless user_signed_in?

  end

 

  private

  def post_params

     params.require(:post).permit(:content)

  end

end

Usersコントローラ

class UsersController < ApplicationController

  def show

    @user =  User.find(current_user.id)

  end

end

  • モデル

post.rb

class Post < ApplicationRecord

  belongs_to :user

end

user.rb

 class User < ApplicationRecord

    devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :posts

end

  • ビュー

views/posts/index.html.erb

<h1>投稿一覧</h1>
<% if user_signed_in? %>
  <% @posts.each do |post| %>
    <p><%= post.content %>:会員No.<%= post.user.id%></p>
  <% end %>
<% else %>
  <p>ログインしてください</p>
<% end %>

  • データベース(sqlite3)

postsテーブル

class CreatePosts < ActiveRecord::Migration[5.2]
  def change
    create_table :posts do |t|
      t.text :content
      t.integer :user_id


      t.timestamps
    end
  end
end

  • seed

Post.create(content: "熱rjrhje狂のWebマrhjerjhjーケティンsprnhグ", user_id: 1)
Post.create(content: "g熱rjrhjhグ", user_id: 2)
Post.create(content: "ehrehンsprnhグ", user_id: 3)
Post.create(content: "gnrnbn熱rjrhje狂のW", user_id: 4)

以上です

 

結果から言うと、問題があったのはseedの部分とデータベースです(コントローラやビュー等には問題無し)

 

エラーの原因はデータベーステーブルに登録されているカラムは:contentと:user_idなんですが、postモデルを作成した時に:user_idカラムを入れ忘れて後からadd_column で追加したんですけど、その間にseeds.rbで上記のデータを入れた為に:contentのみで:user_idが無いデータを作成した事になっていて、追加後にもう一度

bundle exec rake db:seed

で入れ直した時に前のデータは消えて新しいデータのみになると思ったところ、古いデータに新しいデータが追加され存在しカラム無しの古いデータが読み込めないからNo Method Error NilClassが出たようです。

 

今回の解決方法は既存のseedデータを修正した場合、前のデータがエラーの原因になっていて消す必要があるためRails Controllerで

Post.delete_all

でデータを削除後に

bundle exec rake db:seed

でデータを入れ直すことで正しいデータのみが残りエラーが解決しました!

 

追記

seedデータによく変更を加える場合は

rails db:migrate:reset db:seed

でデータベースの削除&作成を一度で出来るそうです!

 

 

Git アップロード 仕方

Githubでアップロードの仕方を覚えたので、忘れないように書いていきます

 

リポジトリやブランチの概念を理解するのにかなり時間がかかりました…

 

前提条件としてGithubのアカウントを持っている事と、(これは後ででもいいけど)repositoryをアカウントから作成しておくことです

 

以下の操作は全てターミナルで行います

 

まずにgitにアップロードしたい好きなフォルダに

cd フォルダ名

で移動して

git init

でgitにアップするフォルダorファイルを指定します

そして

git add . 

or

git ファイル名

でアップロードする準備みたいなものをします

git commit -m "変更についてのメッセージ"

で変更の保存と何を変更したか分かりやすいようにメッセージを書きます

次に

git branch ブランチ名

でブランチを作ります

ブランチというのは保存先みたいなものです

さらにブランチが作れたら

git branch

git checkout ブランチ名

で移動出来ます

 

追記(9/17)

git checkout -b ブランチ名

の作成と移動が同時に出来ます!

 

そして

git remote add リポジトリ名  gitのリポジトリのurl

でリモートリポジトリを作成します

リモートリポジトリは保存先の保存先みたいな感じ

gitのrepositoryのurlはrepositoryの中の緑色の"clone or download"をクリックするとリンクが出てくるのでそれをコピー

そしてついに

git push リポジトリ名 ブランチ名

でアップロード完了です!

正直これだけでも理解するのに1時間半くらいかかりました笑

しかも"こうなるとこういう風になるんだなぁ"と言うような漠然とした概念を掴んだだけでまだ理解は出来てない…

これから使う内に理解出来るようにします

今日は以上でーす💤

f:id:takayanagi-prg:20180916075903j:image

Rails ログイン/ログアウト/アクセス制限機能について

今回の記事では

  • ログイン機能
  • ログアウト機能
  • ユーザー名の表示
  • アクセス制限機能

について書いていきます

 

 

  • ログイン機能

ログイン機能は長くなるので工程を書いておきます

  • get "login"とpost "login"ルーティングの作成

       ↓

  • users/login_form.html.erbビューを作成

       ↓

  • パスワードカラムを追加

       ↓

  • フォームの送信に関して書く

       ↓

  • usersコントローラに中身を書いていく

       

 

まずルーティングから

get "login" => "users#login_form

post "login" => "users#login"

先頭に付いているgetとpostが違うのあれば名前が一緒でもいいそうです。

 

次にusersフォルダにlogin_form.html.erbファイルを作成します

そこにユーザー情報を送信出来るようにinputなどを書いていくのですがその前にpasswordを追加したいので前回やったようにusersテーブルにpasswordカラムを追加します

ターミナルで↓を書き

rails g migration add_password_to_users

db/migrateフォルダ内の"更新データの日付_add_password_to_users.rb"ファイル内に↓と書きます

def change

add_column :users, :password, :string

end

これでパスワードカラムがDBに追加されました

rails db:migrate

を忘れずに!

 

次はフォームの送信が出来るようにlogin_form.html.erbファイルにメールアドレスや名前等(ここでは省略)に加えてパスワードを追加します

<%= form_tag("/login") do %>

〜各種送信するフォームの中身(email,name等)〜

<p> パスワード</p>

<input type="password" name="password" value="<%= @password %>">

<% end %>

type="password"は入力した文字が黒塗りで見られないようにするもので、value="<%= @password %>"は初期値を表示するためです

@passwordは後でコントローラ内で定義します

 

次はusersコントローラに"login_form"と"login"を定義して、"login"の中身を書いていきます

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

まずフォームから送信された情報をfind_by("〜")で取得します

次に情報が取得出来た後、@userが存在する場合、

session[:キー名]というのはこれに代入した情報を送信し続ける変数です(ここではユーザーの情報を送信することでページを移動しても情報が保持されログイン状態が続くという仕組み)

else以降は@error_messageでエラーメッセージを表示し、@email = params[:…]と@password = params[:…]はビュー内のvalue="〜"で初期値を表示するためのものです

 

  • ログアウト機能

まずはルーティング

post "logout" => "users#logout"

sessionの値を変更する場合もDBの変更の時と同じようにpostを使います

 

ではコントローラを書いていきます

def logout

session[:user_id] = nil

flash[:notice] = "〜"

redirect_to("/login")

end
 session[] = nilにすることで送信する情報を空にすることが出来ます(ターミナルでのrails server起動時にctrl+Cを押して接続をキャンセルするみたいな感じ?)

後はログアウトリンクに忘れずに{method: "post"}を指定してくださいね

 

  • ユーザー名の表示

applicationコントローラ内で定義したアクションをbefore_actionで他のコントローラやビューでも使えるというものなのですが、

このbefore_actionを使ってユーザー名の表示をしていきます

まずapplicationコントローラ内に

before_action :set_current_user

〜省略〜

def set_current_user

@current_user = User.find_by(id:  session[:user_id])

end

を定義します

これは@current_userでログイン中のユーザーidを取得しているという意味です

そしてbefore_action :〜で他のアクションでも使えるようにします

そしてlayout/application.html.erbファイル内のヘッダーリンク部分に

<il>

  <%= link_to(@current_user.name, "/users/#{@current_user.id}") %>

</li>

と書けばログイン中のユーザー名が表示されます

 

  • アクセス制限

これも基本的には

applicationコントローラ内で定義したアクションを各コントローラ内でbefore_actionを使うものになります。

 

例えばログインしていないユーザーがログインしているページに入ろうとした場合に

def authenticate_user

if @current_user == nil

redirect_to("/login")

end

end

と定義しておけば、これをログインして欲しく無いページのアクションに指定しておけば、このアクションが発動されてアクセスが制限されるというわけです

例:usersコントローラ内のedit,updateアクションでこのアクション(authenticate_user)を行いたい場合、usersコントローラ内で

before_action :authenticate_user, {only: [:edit, :update]}

と適用したい任意のアクションをonlyで指定します

 

後はログイン中のユーザーが別のユーザーの編集を出来ないように、(ここではusersコントローラ内でのみ適用させるので)usersコントローラ内で

before_action :ensure_correct_user,

{only: [:edit, :update]}

〜省略〜

def ensure_correct_user

  if @current_user.id !=  params[:id].to_i

   redirect_to("/posts/index")

  end

end

を定義します

ポイントは@current_userが params[:id]で受け取った値と比較する場合に params[:~]は文字列でしか受け取れないので.to_iを使って数値に変換する必要があるところです

 

今日はこれで以上です。

初めて3000文字以上書きましたが時間がかかり疲れました…

いつも1000文字当たり1時間くらいかかるので(今回は2.5時間くらい)なかなか更新するのは大変ですが、良いアウトプットだと思い頑張って続けます💪

 

いつも読んでくださりありがとうございます🙏

 

f:id:takayanagi-prg:20180914194137j:image

Rails 画像のアップロード機能

f:id:takayanagi-prg:20180913182210j:image

 

今回の記事では

  • 画像のアップロード機能

について書きます

 

画像のアップロードにはまず画像のデータをデータベースに保存するためのカラム(ここではuser_image)を追加します

*ターミナルへの記述は青で書きます

rails g migration add_image_name_to_users

注意するのはmigrateでは無くmigrationと記述することです

これでdb/migrate/にファイルが作成されるのでそこで

〜省略

def change

add_column :users(テーブル名), :image_name(カラム名):string(データ型)

end

省略〜

これらはターミナルからではなく、ファイルからdbの変更を加える操作です

しかし変更の方はターミナルで操作しなければなりません

rails db:migrate

 

次はユーザー登録画面で登録時点でのデフォルトの画像をusersコントローラのcreateアクションに追加します

def create

@user = User.new(

name: params[:name]

email: params[:email]

image_name: "指定の画像のURL"

)

省略〜

end

 

次はビューに画像を表示させます画像を表示させたい.html.erbファイル内に

<img src="<%= "/画像の入っているフォルダ名/#{@user.image_name}" %>">

 

次は画像を送信出来るようにusers/edit.html.erbファイル内に

<%=form_tag("...", {multipart: true}) do %>

<input name="image" type="file">

を追加します

 

最後にusersコントローラ内のupdateアクションに

def update

〜省略

@user.image_name = params[:image_name]

 

if params[:image]

    @user.image_name  =

"#{@user.id}.jpg"

    image = params[:image]

    File.binwrite("public/フォルダ名/#{@user.image_name}", image.read)

end

省略〜

end

と書きます

@user.image_name = params[:image_name]

は画像のファイル名をimage_nameカラムに保存する為のものです

 

if params[:image]

    @user.image_name  =

"#{@user.id}.jpg"

    image = params[:image]

は画像データが送信されたらimage_nameカラムに画像のファイル名を代入し、

imageで送信されたものを受信し、

 

File.binwrite("〜")

は画像データをファイル内に作成するもので、()内の.readメソッドはその画像データを読み込むためのものです

 

今回は以上です。

最後の方に新しい知識がたくさん入ってきたので少し難しいですね。

 

 

Rails 投稿の編集&削除機能の追加

 

今回の記事では

  • 編集機能の追加
  • 削除機能の追加

を説明します。

 

まず編集機能ですが、これは仕組み自体は新規投稿と一緒で、違うのは新しく作り出して保存する事と値を取得して保存する事です。

削除も編集機能の値の処理が少し違うだけなのでここでは一緒に記述していきます

まずルーティング

〜省略

get "posts/index" => "posts#index"

get "posts/new" => "posts#new"

get "posts/:id" => "posts#show"

post "posts/create" => "posts#create"

get "posts/:id/edit" => "posts#edit"

post "posts/:id/update" => "posts#update"

post "posts/:id/destroy => "posts#destroy"

〜省略

新しく記述したものは太字です

:idは複数の物からそれぞれの固有のデータを取得する必要があるものルーティングの中に入っています

 

次にコントローラ内に空でいいのでそれぞれのアクションを追加します

 

そしてまずshow.html.erbファイル内に

編集・削除のリンク項目を追加します

<%= link_to("編集", "/posts/#{@post.id}/edit") %>

<%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %>

この{method: "post"}というのは直接link_toでルーティングにpostを持つアクションに飛ばしたい時に指定します(postはgetと違って.html.erbのファイルを作らないから)

 

次にedit.html.erbファイルを作成します

ファイル内には

〜省略

<%= form_tag("/posts/#{@post.id}/update") do %>

  <div>

    < textarea name="content">

<%= @post.content %>

</textarea>

<input type="submit" value="保存">

  </div>

  <% end %>

form_tagは新規投稿と同じでupdateアクションへ送信するためで、そのために textarea内のnameにcontentを指定しています

<%= @post.content %>は初期値として入力される内容です

 

最後にコントローラ

〜省略

def edit

 @post = Post.find_by(id: params[:id])

end

普通に値を取得しているだけです

投稿に失敗した際の初期表示のための定義ですね

def update

  @post = Post.find_by(id: params[:id])

  @post.content = params[:content]

  @post.save

  redirect_to("/posts/index")

end

まず値を取得し、textareaのnameで指定されているcontentを取得した後に保存して投稿一覧に遷移しているという意味です

def destroy

  @post = Post.find_by(id: params[:id])

  @post.destroy

  redirect_to("/posts/index")

end

値を取得し、削除、一覧へ遷移、簡単ですね、削除機能で気をつけるのはlink_toでのメソッドを"post"に指定するのを忘れない事です

 

今回はかなり雑になりましたがこれで終わります。

かなり頭で整理出来てきました。

f:id:takayanagi-prg:20180912033548j:image

高校中退からフリーランスを目指すようになるまで

f:id:takayanagi-prg:20180911050835j:image

今回もブログのタイトルである高校中退からフリーランスエンジニアを目指すようになったきっかけと経歴の全2回の後編を書いていきます。

 

 

僕は高卒認定を取得し丁度2年生の終わりで高校を中退しました。

そして1年間は予備校の自習室に通い、勉強をし続ける実質浪人生のような生活になりました。

 

しかし…最初の1ヶ月は毎日8~10時間くらい勉強し、成績も良く伸びたのですが

次の月には一気に勉強時間が減り、夏が始まるころには1日3時間程度しかしなくなりました…

そして秋を迎えるころには勉強しない日すらあるようになり、学力は伸びないどころか落ち始めていました。

12月の願書を出す頃には"これは落ちるな"と確信をしていた(諦めきっていた)程です。

1月とかは1ヶ月まるごと勉強しなかった気がします

2月、3月くらいに少しくらい落ちた学力を取り戻そうとして最後の足掻きで少し勉強を再開しましたが、沼に頭のてっぺんまで浸かっていたので何の意味も無いまま受けて落ちました

 

"落ちたら死んでやる"というくらいの覚悟をもって高1の時に受験を始め、現役合格を目指していたので受験前に落ちるのがわかっていても、とてもショックでしばらくは何もする気が起きませんでした…

 

その後一度は再受験をしようと浪人生として勉強を再開しましたが、実質1年間宅浪をしていて成績が伸びなかったどころか後半には成績が落ちたのを思い出し、踏ん張れる程の情熱や忍耐力も既に無く、結局2週間くらいで浪人生活は終了し、心が完全に折れました。

 

そこから1年くらいは何をやっていたのかあまり覚えてませんが、1日中ボーッとしていたと思います。

僕はこの時、死ぬ運命が来るまでは自分はもう一生惨めな思いをしながら生きていくしか無いのだなと思い、日々を無為に過ごしていました…

学習性無気力感ってやつですね

 

そんな中でも実家の恵まれた環境の中では1日が過ぎるのは暇で、なんとか暇を潰せないかと色んな趣味を見つけてはすぐに飽きて、取っ替え引っ替え新しいのを見つけやっていました。

お絵かき、音楽鑑賞、チェス、将棋、ゲーム、読書、映画などです(ここにあげた趣味はほとんどお金のかからないものばかり)

この時自分はとても怠惰な人間で何一つ続かず、続かないということはこの世で最も価値が低いことと考えていました。

 

しかし月々変わる趣味の中でも唯一続いていたのが音楽鑑賞で、その内に自分も音楽を作りたいと思うようになり、アルバイトをして貯めた10万円を中古の自作PCと周辺機器+作曲ソフトに費やし作曲を始めました。

すると昔は音感が無いと何も出来ないと思っていたのですが、色々なことを調べる内に音楽理論による体系的な作曲方法を知ることになり、音感が無くても作品の質を問わなければ作曲が出来るようになりました。

そして作曲自体は毎日楽しんでやる事が出来、とても充実した日々でした。

 

この時中学校の時に美術で作品を作ることで味わった充実感を思い出し、続ける事を目的とせずに"純粋にそれ自体を楽しめる事は続くんだ"と感じ、同時に物を生み出すという事に至上の達成感・喜びを感じました

 

しかしそんな日々も長くは続かず、今度は将来の不安が頭の中で日々大きくなり、"何とかしてお金を稼がないと"という焦りの中純粋に楽しめなくなってしまいました。

しかし普通に就職するのではいくら好きな趣味があっても、ショボい人生を送るのは完全に目に見えていたので"それは絶対に嫌だ"と思い、探し当てたのがプログラミング業界です。

以前はプログラミングはすごく専門的な職業のイメージであまり興味が無かったのですが、プログラミングの世界では高収入、人材不足、学歴不問、先進的技術、そしてクリエイティブなどのキーワードが飛び交っていてとても興味が惹きつけられました。

そして調べた結果

  • リモートワークOK→空間的制約に囚われない
  • (営業等とは違って)必ず制作物がある→作品として結果を残す事が出来る

などの理由から"これは自分にピッタリだ"と思いフリーランスエンジニアを目指す事に決めました!

(以上を思ったのが2ヶ月前くらいです)

 

長くなりましたが、ここまで読んでいただきありがとうございました😊

 

なぜ高校を中退したのか

こんにちは😃

ブログのタイトルである高校中退からフリーランスエンジニアを目指すようになったきっかけと経歴を2回に分けて書いていきます。

 

 

 

それでは

今日は

なぜ高校を中退したのかについて…

 

まずこの話をするには高校入学時から話さなければなりません。

僕は高校受験で第1志望の公立高校に滑り、滑り止めの私立高校に入学しました。

しかし、高校の入学式の時に学校のレベルが低すぎてとてもビックリしたのをよく覚えています。(自分が入った選択コースは1番アホなコースだった)

入学式では校長を含む何人かの先生方達が話されてたのですが、その中でも学年主任の方が

高校はもう義務教育じゃないからね、学校の規則が守れないなら辞めてもらう

みたいな事を話していてとんでもないところに来てしまったなぁと思いました(学校自体は特進コースもある地方の自称進学校レベルです)

 

高校入学した最初の1週間は人生の目的もまるで無かったし、音楽でも適当にやろうかなーと思ってたけど、音感とかが全然身に付かない事にムカついてきてすぐに辞めました。

そして無期限の暫定感の中で

"ここから人生を変えるには大学受験しかない!"と一念発起して高校入学後1週間で大学受験を決意し、情報集めから始めました。

この時が人生で初めての独学になります

 

そしてすぐに中学校の復習から開始し、1ヶ月後には予備校に入り授業は殆ど取らずに参考書中心の学者プランを立て自習室で毎日勉強する日々が続きます。

 

しかしその中でも受験科目外の授業に時間を取られることや自分の参考書を進めてると教師に妨害されるなどの出来事が重なり、早く高校を辞めたいなぁと思いが募る反面、大学受験には高校卒業資格が必要というジレンマに悩まされます。

そう思って学校を早く辞める方法を調べている時に高卒認定試験の存在を知ります。

(高卒認定試験とは高校へ通ってない人、もしくは何らかの理由で高校を中退した人を対象とした大学受験資格を得ることが出来る試験です。)

高卒認定試験合格では大学受験資格を得るだけであって高校卒業とはみなされない

 

この存在を知った僕はすぐに高卒認定を取得するために動き始め、さらに高校の在籍年数によって試験科目が免除されるとの事だったので高校2年まで在籍することを決め3年になる前に中退しました

f:id:takayanagi-prg:20180910083545j:image

〜続く〜