20191230のRailsに関する記事は21件です。

Railsのデータベースをポスグレでプロジェクトを立ち上げる

①ポスグレのインストール

$ brew update
$ brew install postgresql

②ポスグレを起動するとエラーがでる

$ postgresql
postgres does not know where to find the server configuration file.
You must specify the --config-file or -D invocation option or set the PGDATA environment variable.

③エラーの解消
コンフィグファイルの設定をして下さいと書いている。
ホームディレクトリに戻る

$ cd

ホームディレクトリに設定用のファイル".bash_profile"、".bashrc"があるか下記コマンドで確認

$ ls -a

ない場合は、下記コマンド作る

$ touch ~/.bash_profile
$ touch ~/.bashrc

再度確認すると、ある。

$ ls -a
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsのデータベースをポスグレに指定して、プロジェクトを立ち上げる方法

①ポスグレのインストール

$ brew update
$ brew install postgresql

②ポスグレを起動するとエラーがでる

$ postgresql
postgres does not know where to find the server configuration file.
You must specify the --config-file or -D invocation option or set the PGDATA environment variable.

③エラーの解消
コンフィグファイルの設定をして下さいと書いている。
ホームディレクトリに戻る

$ cd ~

ホームディレクトリに設定用のファイル".bash_profile"、".bashrc"があるか下記コマンドで確認

$ ls -a

ない場合は、下記コマンドで作る

$ touch ~/.bash_profile
$ touch ~/.bashrc

再度確認すると、ある。

$ ls -a

.bash_profileと、.bashrcの説明は下記URLを参照
https://qiita.com/takutoki/items/021b804b9957fe65e093

先ほど作った、~/.bash_profileに環境変数を設定してパスを通す

④下記コマンドで、ターミナルをコマンドモードに切り替る

$ vi .bash_profile

⑤コマンドモードに入ったらiを押してインサートに切り替える

i

⑥下記、環境変数を追記する

export PGDATA='/usr/local/var/postgres'

⑦保存してコマンドモードを終了する

キーボード【ESC】

下記コマンドを入力

:wq

⑧下記コマンドを入力して変更を反映させる

$ source .bash_profile

⑨下記コマンドにて、postgresqlが立ち上げれば設定完了

$ postgres

⑩データベースをポスグレに指定し、好きなバージョンも指定し、Railsプロジェクトを作成して終了

$ rails _5.1.7_ new アプリ名 -d postgresql
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RubyとRailsのバージョンの変更方法

Rubyのバージョン変更方法

①利用中のRubyバージョン確認

$ ruby -v

②インストール可能なRubyバージョン確認

$ rbenv install --list

③目的のバージョンをインストール(1-2時間かかります)

$ rbenv install 2.6.3

④利用するバージョンを変更

$ rbenv global 2.6.3

⑤現在コンソール上で利用しているRubyバージョン確認

$ rbenv versions

⑥rehashしてあげる ※ファイルの場所を変更して使えるようにする

$ rbenv rehash

指定したRailsのバージョンでプロジェクトを立ち上げる方法

①現在インストールされていて、使用できるRailsの確認

$ gem list rails

②Railsの使用したいバージョンをインストール(使用したいバージョンが無かった場合)

$ gem install -v 5.1.7

もう一度、使用できるRailsの確認をすると追加されている

$ gem list rails

③バージョンを指定してプロジェクトを立ち上げる

$ rails _5.1.6_ new sample_app
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】スクレイピングを使ってブログの記事一覧に記事内の写真を添える

はじめに

今回はRubyでスクレイピングに挑戦していきます。

前回の記事でブログを作成しました。
【Rails】summernoteを使って画像も投稿できるブログを作る

ブログといえばはてなブログですが、
スクリーンショット 2019-12-30 20.59.20.png
知り合いのお店のブログです)

このようにその記事内で使われている写真が横に乗るようになっています。

これを実現してみたい。。

前回記事で使ったsummernoteですが、画像を投稿するとbase64でimgタグで直保存されます。

例えばこんな感じです

<p>ホゲホゲ</p>
<p><img src="data:image/jpeg;base64,(長いので省略)" data-filename="4.jpg" style="width: 100px;"><br></p>

ブログ内で写真が使われていればどこかにimgタグがあるはずなのでこれをブログの保存時に検知すれば良いのでは?
と僕は考えました。

ということで、もっと簡単な方法もありそうなものですが、丁度スクレイピングにも興味があったのでやってみます。

実装!

こちらの記事を参考にしました。
https://morizyun.github.io/blog/ruby-nokogiri-scraping-tutorial/index.html
https://blog.takuros.net/entry/2014/04/15/070434

僕はnokogiriがすでにインストールされていたのでされていない人は上記の記事を参考にインストールしてみてください。(Gemいじるだけなので簡単だと思います)

今回はDBに保存する前のデータを使用するので他のページから取ってくるという工程は不要になります。

スクリーンショット 2019-12-30 21.50.52.png

imageというカラムに挿入することにします。

スクレイピングしてimgタグを:imageに保存

blog_posts_controller.rb
  @charset="UTF-8"

  def create
    @blog_post = BlogPost.new(blog_post_params)
    @blog_post[:created_by] = current_user.id
    @blog_post[:updated_by] = current_user.id

    doc = Nokogiri::HTML.parse(@blog_post[:content], nil, @charset)
    images = doc.at('//img')
    if images.instance_of?(Array) then
      @blog_post[:image] = images[0]
    else
      @blog_post[:image] = images
    end

    respond_to do |format|
      if @blog_post.save
        format.html { redirect_to @blog_post, notice: 'Blog post was successfully created.' }
        format.json { render :show, status: :created, location: @blog_post }
      else
        format.html { render :new }
        format.json { render json: @blog_post.errors, status: :unprocessable_entity }
      end
    end
  end

doc = Nokogiri::HTML.parse(@blog_post[:content], nil, @charset)
blog_post[:content]の内容全てをNokogiri::HTML::Documentに変換しています。

その後のimages = doc.at('//img')でimgタグの一番初めにヒットしたものを持ってきています。

これで

blog_post[content]
<p>ホゲホゲ</p>
<p><img src="data:image/jpeg;base64,(長いので省略A)" data-filename="4.jpg" style="width: 100px;"><br>
<img src="data:image/jpeg;base64,(長いので省略B)" data-filename="4.jpg" style="width: 100px;">
</p>

このような:contentの中身が

blog_post[image]
<p><img src="data:image/jpeg;base64,(長いので省略A)" data-filename="4.jpg" style="width: 100px;"><br></p>

このように:content内の初めのimgタグの内容が:imageに保存されます。

ブログの記事一覧の横に表示

blog_post/index.html.haml
    - @blog_posts.each do |blog_post|
      %table
        %thead
          %tr
            %th
            %th

        %tbody
          %tr
            %td{style: "max-width: 100px; height: auto;"}
              -if !blog_post.image.nil?
                = link_to blog_post.image.html_safe, blog_post
              -else
                =image_tag("hoge.jpg", :size => '100x100', style:"max-height: 100px")
            %td= link_to blog_post.title, blog_post
          %hr

style: "max-width: 100px; height: auto;"を指定しているのは、そのまま表示すると:image内の画像がでかすぎた時対策です。

また、blog_post.content内にimgタグが存在しなかった時、blog_post.imageがnilになってエラーが出てしまうため、仮の画像を入れるようにしています。

終わりに

nokogiri便利でした。
これと似たような流れでその記事のはじめの方をダイジェストでだすということもできそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】NoMethodError (undefined method `current_sign_in_at' for #<User:XXXXXXXXXXXXXX>):

はじめに

Railsでgem devise_token_authを導入時に発生した内容です。

Eメール認証の確認をしようと、
http://localhost:3000/api/v1/auth/sign_in
にPOSTリクエストを出すと以下エラーが発生しました。

Started POST "/api/v1/auth/sign_in" for ... Processing by ... DeviseTokenAuth::SessionsController#create as JSON
...

Completed 500 Internal Server Error in 311ms (ActiveRecord: 17.4ms | Allocations: 7912)

NoMethodError (undefined method `current_sign_in_ip' for #<User:...>):

※rails serverより抜粋。

このエラーに対して、自分がうまくいった解決法を残します。

環境

OS: macOS Catalina 10.15.1
Ruby: 2.6.5
Rails: 6.0.2.1

結論:user.rbを修正

Before

app/models/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  include DeviseTokenAuth::Concerns::User
end

After

app/models/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  include DeviseTokenAuth::Concerns::User
end

:trackableを削除すると無事に通るようになりました。

おわりに

最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:

参考にさせて頂いたサイト(いつもありがとうございます)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】summernoteを使って画像も投稿できるブログを作る

はじめに

summernoteを使って画像の投稿などにも対応したブログを作っていきたいと思います。

何か間違っている点があればコメントをください…!

レシピ

1. ER図を書く

データ構造をまとめます。ER図の作成はpgmodelerを僕は使用しています。
スクリーンショット 2019-12-28 19.01.28.png

こんな感じになりました。

2. generator使って丸っと全体像を作成

Rails初心者の僕はgeneratorに頼りきっています。

$ rails generate scaffold Blog_post title:string content:text created_by:string updated_by:string

3. migrationファイルの編集

not nullを指定したいのでmigrationファイルに直接書き込みます。

変更前

db/migrate/20191228075319_create_blog_posts.rb
class CreateBlogPosts < ActiveRecord::Migration[5.1]
  def change
    create_table :blog_posts do |t|
      t.string :title
      t.text :content
      t.string :created_by
      t.string :updated_by

      t.timestamps
    end
  end
end

変更後

db/migrate/20191228075319_create_blog_posts.rb
class CreateBlogPosts < ActiveRecord::Migration[5.1]
  def change
    create_table :blog_posts do |t|
      t.string :title, null: false
      t.text :content, null: false
      t.string :created_by, null: false
      t.string :updated_by, null: false

      t.timestamps null: false
    end
  end
end

4. migrationする

migrateファイルの編集も終わったのでmigrationをかけます。

$ bundle exec rake db:migrate

これでblog_postsテーブルがDB上に作成されます。

5. form.htmlを編集

created_by、updated_byがフォームで作成する感じになっているので内部での処理に置き換えます。

_form.html.haml
= form_for @blog_post do |f|
  - if @blog_post.errors.any?
    #error_explanation
      %h2= "#{pluralize(@blog_post.errors.count, "error")} prohibited this blog_post from being saved:"
      %ul
        - @blog_post.errors.full_messages.each do |message|
          %li= message

  .field
    = f.label :title
    = f.text_field :title
  .field
    = f.label :content
    = f.text_area :content
--  .field
--    = f.label :created_by
--    = f.text_field :created_by
--  .field
--    = f.label :updated_by
--    = f.text_field :updated_by
  .actions
    = f.submit 'Save'

(-部分を削除です)

6. created_by、updated_byを内部で入れる

  # POST /blog_posts
  # POST /blog_posts.json
  def create
    @blog_post = BlogPost.new(blog_post_params)
+    blog_post[:created_by] = current_user.id
+    blog_post[:updated_by] = current_user.id

    respond_to do |format|
      if @blog_post.save
        format.html { redirect_to @blog_post, notice: 'Blog post was successfully created.' }
        format.json { render :show, status: :created, location: @blog_post }
      else
        format.html { render :new }
        format.json { render json: @blog_post.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /blog_posts/1
  # PATCH/PUT /blog_posts/1.json
  def update
+    blog_post[:updated_by] = current_user.id
    respond_to do |format|
      if @blog_post.update(blog_post_params)
        format.html { redirect_to @blog_post, notice: 'Blog post was successfully updated.' }
        format.json { render :show, status: :ok, location: @blog_post }
      else
        format.html { render :edit }
        format.json { render json: @blog_post.errors, status: :unprocessable_entity }
      end
    end
  end

(+を追加です)

7. summernoteの導入

summernoteを使用します。
スクリーンショット 2019-12-28 19.35.03.png
このようなテキストエディタが導入できます。

これで画像の投稿まで対応できます。

https://blog.seiyamaeda.com/12552
https://qiita.com/Kohei_Kishimoto0214/items/a7c75d105d530d81a678

これらの記事を参考に導入します。(導入過程は省略)

_form.html.haml
= form_for @blog_post do |f|
  - if @blog_post.errors.any?
    #error_explanation
      %h2= "#{pluralize(@blog_post.errors.count, "error")} prohibited this blog_post from being saved:"
      %ul
        - @blog_post.errors.full_messages.each do |message|
          %li= message

  .field
    = f.label :title
    = f.text_field :title
  .field
    = f.label :content
    = f.text_area :content, 'data-provider': :summernote
  .actions
    = f.submit 'Save'

%div#summernote
:javascript
  $(function () {
    $('[data-provider="summernote"]').each(function(){
      $(this).summernote({
        lang: 'ja-JP',
        height: 250,
        fontNames: ['Helvetica', 'sans-serif', 'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New'],
        fontNamesIgnoreCheck: ['Helvetica', 'sans-serif', 'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New'],
      });
    })
  })

最終的にこのような形でformに実装します。

8. html_safeでhtml形式のcontentsがちゃんと表示されるようにする

summernoteによりDBに保存すると
<p>test</p>
のようにhtml形式で保存されます。

generatorで作成されたshow, indexのままだとそのまま

なども表示してしまうのでこれを修正します。

contentに対してhtml_safeというメソッドをかけることで修正できます。

show.html.haml
%p#notice= notice

%p
  %b Title:
  = @blog_post.title
%p
  %b Content:
  = @blog_post.content.html_safe

= link_to 'Edit', edit_blog_post_path(@blog_post)
\|
= link_to 'Back', blog_posts_path
index.html.haml
%h1 Listing blog_posts

%table
  %thead
    %tr
      %th Title
      %th Content
      %th
      %th
      %th

  %tbody
    - @blog_posts.each do |blog_post|
      %tr
        %td= blog_post.title
        %td= blog_post.content.html_safe
        %td= link_to 'Show', blog_post
        %td= link_to 'Edit', edit_blog_post_path(blog_post)
        %td= link_to 'Destroy', blog_post, method: :delete, data: { confirm: 'Are you sure?' }

%br

= link_to 'New Blog post', new_blog_post_path

ついでにcreated_byなどの余計な情報は表示しないように変更しました。

終わりに

これで完成です。

summernoteを取り上げている記事少ないですけどめちゃ便利ですねこれ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアルメモ - 第1章

目次はこちら

Railsチュートリアル(ローカル版)の第1章をやってみて気づいたことのメモを記載していきます

1.1 はじめに

割愛

1.2 さっそく動かす

ローカル(mac)で普通にチュートリアル通り実行していくと、最初の

printf "install: --no-document \nupdate:  --no-document\n" >> ~/.gemrc
gem install rails -v 5.1.6

Fetching: concurrent-ruby-1.1.5.gem (100%)
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /Library/Ruby/Gems/2.3.0 directory.

となる。
ググると、system標準のrubyを使おうとしているため、権限エラーになっているようなので、rbenvをインストールして、別のrubyを使用(バージョンは2.5系で最新だった2.5.7を指定)

brew install rbenv

echo 'export PATH="~/.rbenv/shims:/usr/local/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
source ~/.bash_profile

rbenv install 2.5.7
rbenv global 2.5.7
rbenv versions
gem install rails -v 5.1.6

今度は無事railsをインストールできた

1.3 最初のアプリケーション

1.3.1 Bundler

Gemfileとbundlerの使い方についての章

gemはrubyにおけるライブラリのこと。bundlerを使うとgemのバージョンを管理できる。
(pythonでいうところの、requirements.txtがGemfile、pipがbundler)
なお、bundler自身もgemとのこと。
Gemfile.lockというファイルがセットで存在し、.lockの方は実際にインストールしたgemが反映される。

使い方は、
1. Gemfileに使用するgemを記載
2. bundle installでGemfileに記載されたgemをインストールしてくれる

なお、GemfileとGemfile.lockに同じライブラリが記載されているがバージョンに差異がある場合(Gemfileのバージョンを変えたときなどに発生)には、bundle updateが必要。
bundle installはあくまで、未インストールのgemのインストールしかやってくれず、gemのバージョン更新はしないらしい。

1.3.2 rails server

割愛

1.3.3 Model-View-Controller (MVC)

割愛(大事なところなので、MVCについてよく知らない人はちゃんと読んでください)

1.3.4 Hello, world!

コントローラーに変更を加え、ルーティング(URLと呼び出される処理のマッピング)を変える。
ルーティングはconfig/routes.rbに定義する。

config/routes.rb
Rails.application.routes.draw do
  root 'application#hello'
end

↑に対して、application_controller.rbのhelloメソッドが呼び出される

1.4 Gitによるバージョン管理

割愛

1.5 デプロイする

herokuにデプロイしていく。
herokuのCLIが必要になるので、homebrewでインストールする(公式にcatalinaだとwarningが出ると書いてあったが、mojaveだと特に何も起きなかったので気にせず進める)

brew tap heroku/brew && brew install heroku

コマンドラインからログインし、sshキーをherokuに登録し、heroku createで新規アプリケーションを作成する

herokuにgit pushしようとすると以下のエラーが発生。

git push heroku master
fatal: 'heroku' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

調べてみると、ローカルのフォルダ構成が以下になってしまっていた。どうもheroku createすると、カレントディレクトリでgit initが実行され、.git/configのremoteにherokuが追加されるらしい。

tree
.
├──.git/config
└── environment
    └── hello_app
        └──.git/config

hello_app配下の.gitディレクトリを削除し、プロジェクトルートで再度heroku create実行からやり直すと解消。

無事、herokuにデプロイできた。

1.6 最後に

割愛

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアルメモ 目次

はじめに

  • ここ1年半くらいpythonをメインに触っていたが、転職サイトを眺めていたらまだまだRailsの需要が高い(特にスタートアップ界隈)なことに気づき、ちょうど年末で暇なので久々にRails チュートリアルを復習してみようと思った
  • 以前学習したときはcloud9がawsに吸収される前だったのでcloud9を使うことに抵抗がなかったが、rails tutorialをやるためにわざわざawsにログインしてcloud9使うのは手間だなと思ったので、ローカルでやってみることにした(aws経由じゃなくても使える?みたいだが、まぁ普通にローカルの方がサクサク開発できるし)
  • エディタはVSCodeを使用しています
  • 章ごとに気づいたことをまとめていきます(途中で力尽きたらごめんなさい)

目次

第1章メモ
第2章メモ※後日記載予定
第3章メモ※後日記載予定
第4章メモ※後日記載予定
第5章メモ※後日記載予定
第6章メモ※後日記載予定
第7章メモ※後日記載予定
第8章メモ※後日記載予定
第9章メモ※後日記載予定
第10章メモ※後日記載予定
第11章メモ※後日記載予定
第12章メモ※後日記載予定
第13章メモ※後日記載予定
第14章メモ※後日記載予定

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails: Arrayでもwill_paginateを使えるようする方法

前提

  1. gem pagenateは事前に使える状態にしておく。
  2. bundle installから使える状態までにする方法に関してはREADMEを参考にしてください。
    FYI: will_paginate

結論から言うと、デフォルトではwill_paginateはarray型の時は使えない。
そのため、config/initializersの配下にちょっとした記述をする必要がある。
ファイル名はなんでもいいのでとりあえずファイルを作る。(ex: will_paginate_array.rb)
ファイル作成後は以下の一文を追記する。

# will_paginate_array.rb
require 'will_paginate/array'

記述後、一旦railsを再起動する。
で使えるようになるはず。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails] link_toをボタン化する

ポートフォリオ作成中にlink_toをボタン化したいと思い調べて実装したので、忘れないように記録に残します。

<%= link_to "任意のリンク名", hoge_path, class: 'btn btn-warning' %>

※class名はbootstrapから引用しています!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsのDEPRECATION WARNINGを消す

事象

Railsのバージョンを5から6にアップグレードしたら、尋常ではない量のDEPRECATION WARNINGが出てしまった。

DEPRECATION WARNING: Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1. To continue case sensitive comparison on the `:カラム名` attribute in `モデル名` model, pass `case_sensitive: true` option explicitly to the uniqueness validator. (called from block (3 levels) in <main> at /***/spec/factories/***.rb:6)

Rails6からUniqueness validatorの仕様が変更されたことによる警告だった。

参考
Rails 6.0でDeprecatedになるActive Recordの振る舞い3つ

しかし、Uniqueness validatorを使っている箇所すべてで警告が表示されるので、RSpecを流すと実行結果がとんでもないことになる。
他にもいくつか警告が表示されていたが、自分のアプリではいずれも問題ないことが確認できた。
その時点で警告は無意味となり、あまりにも見づらいので非表示にしたい。

対応

不要な警告がログに出力されないよう、config/application.rbに以下コードを追加した。

ActiveSupport::Deprecation.silenced = true if Rails.version == '6.0.2'

これで、当該アプリのバージョンが6.0.2なら、DEPRECATION WARNINGが出力されなくなる。

今後Railsをアップグレードする際も、当該バージョンでdeprecatedになったものの確認がすべて完了してから非表示にしたいので、6.0.2と直に書いている。
6.0.2 -> 6.0.3に上げて新たな警告が出ていれば、内容を確認(対応)後にこちらも6.0.3に書き換えていく。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails db:migrate でエラーが起きる時の対処法

今回は、マイグレーションをした時の対処法についてみていきます。

$ rails db:migrate
-- create_table(:movies)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::DuplicateTable: ERROR:  relation "movies" already exists

このようなエラーはすでに、同じ「movies」というテーブルが存在していますよ。っていう意味なので、moviesテーブルを削除してあげてれば問題ないです。

すべきこと

1.ターミナルで以下のように入力してあげる。

$ rails db

2.#が出てくるので、その横に\dと入力してあげる

# \d

3.テーブルがたくさん出てくるので該当のテーブルを削除してあげる。(今回は、moviesテーブルを削除する)

# drop table movies;

4.再び,マイグレコマンドを入力する

$ rails db:migrate 

これで、マイグレーションがうまくいきます。

もし、間違えているところがあればコメントしていただけると幸いです。
また、いいねを頂くと励みになりますのでよろしくお願い致します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ログイン機能に関わるsessionについて(ステートレスとステートフル含む)

sessionとは

セッションとは、一連の処理の始まりから終わりまでを表す概念のこと。
セッションという定義は広く、さまざまなところでセッションという用語が使われる。

「なるほど。わからん。」

・セッションを理解するにはまずステートフルとステートレスを知る必要がある。

ステートフルとは、あるリクエストをしたら、レスポンス(対応や反応、応答内容等)が変わるもの。特に、それ以前のやり取りの状況(ステート)によって回答が変わるもののこと。

ステートレスとは、あるリクエストをしたら、必ず同じ結果になるもの。それまでのリクエスト・レスポンスのことは一切考えず、今来たリクエストを額面通りに受け取って回答するもののこと。

具体的な例で考えてみる。

のび太とドラえもんのやりとりがステートフルだった場合

の「ドラえもん来週テストだから暗記パンだして」

ど「今在庫切れで入荷待ちなんだよ。テストまでには間に合うはず」

の「明日テストだよ。例の物は?」

ど「はい。でも自分で勉強しないと成長しないよ」

このやりとりのように「WEBブラウザ(のび太)」と「WEBアプリケーション(どら)」間ではリクエストとレスポンスのやりとりをして処理している。

次のステートレスの場合と比べるとわかりやすい。

のび太とドラえもんのやりとりがステートレスだった場合

 の「ドラえもん来週テストだから暗記パンだして」

 ど「今在庫切れで入荷待ちなんだよ。テストまでには間に合うはず」

 の「明日テストだよ。例の物は?」

 ど「例の物ってなあに」

 の「…」

このようにステートレスでは前回のやりとりを保存していないため例の物というデータがなければレスポンスすることはできない。

上の二つの例を比べてわかるように、前のやりとりを記憶しているステートフルの方がWEBアプリケーションを利用する上で都合がいい。
しかし、WEBは基本的にステートレスである。ステートフルにするために使用するのがsessionだということ。

※ステートレスであることにもメリットがありますがここではセッションについての説明なので省かせていただきます

sessionを使用することによって生じるデメリットもある。

・sessionはサーバー側にメモリの空間を作るため、アクセスするユーザーの増加に比例してサーバー側のメモリを圧迫してしまう
・ハッカーにsessionによって作られたサーバー側にある重要なデータ(住所。クレカ番号など)が奪われる危険性がある

以上の理由からsessionの使用はあまり好まれない傾向にあるらしい

また、セッションと一緒に考える必要があるクッキーについても書いていきたい。

今日もいい勉強したな!

認識に間違いがあれば教えていただけるとありがたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ログイン機能について 編集

理解するには前提知識として
HTTP(リクエスト、レスポンス、ヘッダ、ボディ)

sessionメソッドは、Railsにもともと定義されているメソッドで、暗号化して保存するためのメソッド

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Validates 編集してく

presence
空でないかどうか
uniqueness
重複していないかどうか
length
長さを指定する(例:文字の長さ)
numericality
数値のみ受け付ける

英単語も覚えられるし一石二鳥ですな

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nuxt.js graphQL の勉強素材

誰向けなの???

  • Nuxt.js使ってなんかしてみたい
  • GraphQLってなに?
  • RESTなAPIを卒業したい

って人たち向けの記事です。勉強するときはググれば色々な記事が出てくるのですが、良さげな資料がまとまってる記事があると便利かなと思って作成しました。筆者本人がど初心者なので表記のミス等は許してください...!

背景

筆者が
- フロントエンド: Nuxt.js
- バックエンド: Rails
- API: apollo(GraphQL), Axios

で開発するプロジェクトに参加するために勉強する必要がありました。

今の世の中、色々なところに素晴らしい勉強素材があるので本当に助かります...

Nuxt.js

概念

REFFECT
さんの記事を色々と読みました。軽い演習もできます。この記事以外にもそもそものvue.jsの勉強素材もたくさんあり、非常に分かりやすくおすすめです。

演習

FusicTechBlog
さんの記事内に書かれているtodoアプリの制作を行いました。これにはgraphQLの知識なども必要なので最後にやるといいかもしれません。

GraphQL

一番理解するのが難しく感じました。そして今もそこまで理解できていない気がします。

概念

公式ドキュメント
がわかりやすく書かれています。英語もそんなに難しいものではないので気合いで読みました。

blog.kymmt.com
クエリの書き方やTypeの書き方等、飛ばされそうな細かい説明も書いてありとても助かりました。

こちらの記事
Rails側でどのようにgraphQLを使うのかについて書かれています。

演習

FusicTechBlog
先ほどNuxt.jsのところでも紹介した記事の前編です。RailsサイドでGraphQLを実装します。

Axios

概念

こちらの記事
が図付きで説明されており、Axiosがどういうことをするために存在しているのかなどを理解しやすいです。

終わりに

まだまだ勉強途中ですが、上記の記事を読んだり演習することで最低限の知識くらいは得ることができた気がします。同じような境遇の方がいましたら参考にしていただけると嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#Rails で bundle exec rspec って毎回入力するのが面倒だから bin/rspec をインストールするにはたった2コマンドで良いなんて `bundle binstubs rspec-core`

bin/rspec の実体はrubyスクリプトである

bundle binstubs rspec-core
bundle binstubs bundler --force

bin/rspec

#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file was generated by Bundler.
#
# The application 'rspec' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
  Pathname.new(__FILE__).realpath)

bundle_binstub = File.expand_path("../bundle", __FILE__)

if File.file?(bundle_binstub)
  if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
    load(bundle_binstub)
  else
    abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
  end
end

require "rubygems"
require "bundler/setup"

load Gem.bin_path("rspec-core", "rspec")

bin/bundle

#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file was generated by Bundler.
#
# The application 'bundle' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require "rubygems"

m = Module.new do
    module_function

  def invoked_as_script?
    File.expand_path($0) == File.expand_path(__FILE__)
  end

  def env_var_version
    ENV["BUNDLER_VERSION"]
  end

  def cli_arg_version
    return unless invoked_as_script? # don't want to hijack other binstubs
    return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
    bundler_version = nil
    update_index = nil
    ARGV.each_with_index do |a, i|
      if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
        bundler_version = a
      end
      next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
      bundler_version = $1 || ">= 0.a"
      update_index = i
    end
    bundler_version
  end

  def gemfile
    gemfile = ENV["BUNDLE_GEMFILE"]
    return gemfile if gemfile && !gemfile.empty?

    File.expand_path("../../Gemfile", __FILE__)
  end

  def lockfile
    lockfile =
      case File.basename(gemfile)
      when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
      else "#{gemfile}.lock"
      end
    File.expand_path(lockfile)
  end

  def lockfile_version
    return unless File.file?(lockfile)
    lockfile_contents = File.read(lockfile)
    return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
    Regexp.last_match(1)
  end

  def bundler_version
    @bundler_version ||= begin
      env_var_version || cli_arg_version ||
        lockfile_version || "#{Gem::Requirement.default}.a"
    end
  end

  def load_bundler!
    ENV["BUNDLE_GEMFILE"] ||= gemfile

    # must dup string for RG < 1.8 compatibility
    activate_bundler(bundler_version.dup)
  end

  def activate_bundler(bundler_version)
    if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
      bundler_version = "< 2"
    end
    gem_error = activation_error_handling do
      gem "bundler", bundler_version
    end
    return if gem_error.nil?
    require_error = activation_error_handling do
      require "bundler/version"
    end
    return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
    warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
    exit 42
  end

  def activation_error_handling
    yield
    nil
  rescue StandardError, LoadError => e
    e
  end
end

m.load_bundler!

if m.invoked_as_script?
  load Gem.bin_path("bundler", "bundle")
end

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2895

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#Rails - rails console で全てのパス・URLを確認する ( e.g `app.methods.grep /_path\Z/` )

example

bundle exec rails console
[1] pry(main)> app.methods.grep /_path\Z/
[2] pry(main)> app.methods.grep /_url\Z/

app って何よ?

main空間に生えているインスタンスっぽい?

[15] pry(main)> self
=> main
[16] pry(main)> self.app
=> #<ActionDispatch::Integration::Session:0x000055e5817d8540

Rails.application.app とはまた違うようだ。

Ref

rails console の tips - Qiita
https://qiita.com/snaka/items/eeb5dee96e44fca54a2e

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2893

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorial3 [TweetApp]

TweetApp

< 本格的なRailsアプリケーション >

これから本格的なアプリケーションの開発を進めていきます。本格的なアプリケーションの開発とはいえ、学習が⽬的のため本来必要とする部分をあえてやらない箇所も出てきます。例えばテストコードです。本来「⾃動化テスト」はマストととなっていますが、本チュートリアルではとにかくRailsになれる、理解することを⽬的としているので省略しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsの新規プロジェクトを指定のRubyバージョンで作成する。

はじめに

久しぶりにRailsの新しいプロジェクトを作成するに当たり、Rubyバージョンを最新のものを利用しようとしてつまずいたので、今後の自分のためにも記事として残しておく。

環境

・rbenvはすでにインストールされているものとする。
https://qiita.com/Alex_mht_code/items/d2db2eba17830e36a5f1
・macOS
Catalina

1. プロジェクトを運用するディレクトリを作成する。

$ mkdir app_name
$ cd app_name

2. Rubyのバージョンを最新にする。

現在使用しているバージョンを確認する

$ rbenv versions

  system
  2.5.1
* 2.6.5

以下のコマンドでインストール可能なバージョンリストが表示される。

$ rbenv -l

インストールしたいバージョンがない場合は以下のコマンドでアップデート
(2019/12/29時点では安定の最新バージョンは2.7.0)

$ brew update
$ rbenv install 2.7.0

インストールが完了すると以下のように表示が増える

$ rbenv versions

  system
  2.5.1
* 2.6.5
  2.7.0

現在はバージョン2.6.5が指定されているので、2.7.0を指定する。
このときコマンドが以下の2パターンあるので使い分けてください。

$ rbenv local 2.7.0 これは現在のディレクトリのプロジェクトのみに適用。
$ rbenv global 2.7.0 その他のプロジェクトのバージョンも全てに適用。

僕は別のアプリを2.6.5で作っているのでlocalで実行。

3. Railsのプロジェクトを作成する。

$ bundle init

Gemfileが生成される。
開いて以下のように編集

# gem rails  → gem rails (コメントアウトを外して保存)
$ bundle install

ここでオプションを付けるかどうかも議論はありますが、プロジェクトが多くなってきてスキルが上がってきたときに考えたほうが理解できると思います。
ざっくりとした説明としてはオプションを付けたほうが容量を節約した運用ができるよということ。

以下のコマンドでプロジェクトを作成。DBの選択などオプションはありますが、シンプルに作っていきます。

rails new .

Gemfileを上書きするか聞かれるのでyを入力し、return。

今回は以下のメッセージが出たので対応。

Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/

こちらを参考に。
https://qiita.com/libertyu/items/1eb74adc817ab8971100
以下のコマンドを実行。

$ brew install yarn

続いて

$ rails webpacker:install

これで準備OK! 以下で起動!

$ rails s

以下にアクセスして起動を確認。
http://localhost:3000/

スクリーンショット 2019-12-30 0.02.58.png

まとめ

一つ一つのコマンドの意味を理解してくことは、とても大切です。
一方で、完璧に理解して進むことは時間がいくらあっても足りません。
今回はコマンド入力しただけで進んだ、次回はそのうちの一つのコマンドについて調べて理解が進んだ状態で進んだというように
毎回毎回少しずつ学習していくことがいいのではないかと考えています。

もし、上記のコマンドでうまく行かなかった際はつまずいた箇所を指摘していただけると幸いです。
共に頑張っていきましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ajaxのフォローボタンが反応しないエラー(500 Internal Server Error)

フォローできない 500 Internal Server Error

ajaxのフォローボタンが反応しない。データベースも変更がない。

consolelogのエラー内容

 app/models/user.rb:44
Completed 500 Internal Server Error in 32ms (ActiveRecord: 5.2ms)



ActiveRecord::RecordNotUnique (SQLite3::ConstraintException: UNIQUE constraint failed: relationships.follower_id, relationships.followed_id: INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)):

app/models/user.rb:44:in `follow'
app/controllers/relationships_controller.rb:6:in `create'

対象のコード

class RelationshipsController < ApplicationController
  before_action :user_signed_in?

  def create
    @user = User.find_by(params[:followed_id]) # 対象ユーザーを受け取る
    current_user.follow(@user) # 対象ユーザーをフォローする
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

  def destroy
    @user = Relationship.find(params[:id]).followed # Relationshipからidを取得
    current_user.unfollow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end
end

class  User < ApplicationRecord

has_many :posts, dependent:  :destroy

has_many :likes

has_many :comments

has_many :active_relationships, class_name:  "Relationship",

foreign_key:  "follower_id", \# デフォルトではuser_idに紐づけられるので指定

dependent:  :destroy

has_many :passive_relationships, class_name:  "Relationship",

foreign_key:  "followed_id", \# デフォルトではuser_idに紐づけられるので指定

dependent:  :destroy

has_many :following,

through:  :active_relationships, \# active_relationshipsメソッドを呼び出し

source:  :followed  \# 各要素に対してfollowedメソッドを実行

has_many :followers,

through:  :passive_relationships, \# active_relationshipsメソッドを呼び出し

source:  :follower  \# 各要素に対してfollowedメソッドを実行



\# Include default devise modules. Others available are:

\# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable

devise :database_authenticatable, :registerable,

:recoverable, :rememberable, :validatable



validates :name, presence:  true, length: { maximum:  50 }

validates :email, length: { maximum:  255 }

validates :password, length: { minimum:  6 }



def  update\_without\_current_password(params, *options)

params.delete(:current_password)



if params\[:password\].blank? && params\[:password_confirmation\].blank?

params.delete(:password)

params.delete(:password_confirmation)

end



result  =  update_attributes(params, *options)

clean\_up\_passwords

result

end



\# フォロー機能のメソッド



\# ユーザーをフォローする

def  follow(other_user)

following  << other_user

end



\# アンフォロー

def  unfollow(other_user)

active_relationships.find_by(followed_id:  other_user.id).destroy

end



\# 既にフォロー済みのユーザーに含まれていないか確認

def  following?(other_user)

following.include?(other_user)

end

end

原因

どうもこのファイルの中に問題がありそう。
500はコントローラー側に問題があるエラーの様

解決方法

    @user = User.find_by(params[:followed_id]) # 対象ユーザーを受け取る

find_byでなくfindが正解だった。

修正後問題なく動作しフォロー機能挙動。

備考

ちなみにfindメソッドとfind_byメソッドの違いは、、、

findメソッド
  • 検索したいレコードを全て抽出する。
  • マッチするレコードが無い場合はエラーとなる。
find_byメソッド
  • 検索したいレコードの最初に一致した1件だけを抽出
  • マッチするレコードが見当たらない場合nilが返ってくる。
使い分け

find→IDがわかっている場合。
find_byIDが不明且つ別の条件でレコードを検索したい場合。

【参考】
find_byとfindの違い - Qiita

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む