20201015のRubyに関する記事は23件です。

rails 新規アプリケーション立ち上げコマンド

Ruby on Railsでの新規アプリケーション立ち上げ方法

自分に向けて記憶の範囲内だけでアウトプットします!

ターミナル
rails _6.0.0_ new test -d mysql

ターミナル
rails db:create

ターミナル
rails g model test

db/migrate/2020・・・・・
t.string :name, null: false (ここの行の記述は適当)

ターミナル
rails db:migrate

config/routes.rb
root to tests#index (ここの行も適当)

ターミナル
rails g controller tests

app/controller/tests.controller.rb
def index
  @tests = Test.all
end

database.yml
utf8○○・・・の箇所をutf8のみにする

app/views/index.html.erb
ここにHTMLを記述する

以上!

ここまで全て記憶内で書いてみました。足りないところや間違っているところもあると思いますが、私自身は間違っているところがあればエラー見ればわかるのでこれを参考にする方は100%信じきらないでください!

現場からは以上です!

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

PCの開発環境で作ったWEBアプリをスマホでも確認する方法

最近個人開発アプリのレスポンシブ化を行いました。
デベロッパツールでも見れますが、実機でもちゃんと表示されるか確認したいですよね。そんな時に手軽にスマホアプリでも確認する方法を共有させて頂きます。

【環境】

  • windows10 Pro
  • Rails: 6.0.3.2
  • ruby: 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
  • Docker for windows
  • MySQL 5.7
  • nginx:1.15.8

手順

まず、PCとスマホを同じWiFiに繋ぎます。

その後、Windowsキー+Rを押し、cmdと入力します。
コマンドプロンプトを開くので、ipconfigと入力しエンターを押します。

イーサネット アダプター VirtualBox Host-Only Network:
(省略)
イーサネット アダプター VirtualBox Host-Only Network #2:
(省略)
イーサネット アダプター vEthernet (Extarnal Virtual Switch):

接続固有の DNS サフィックス . . . . .: flets-west.jp
IPv6 アドレス . . . . . . . . . . . .: 240xxxxxxxxxx
一時 IPv6 アドレス. . . . . . . . . .: 240xxxxxxxxxxxxxxxx
リンクローカル IPv6 アドレス. . . . .: xxxxxxxxxxxxxxxx
IPv4 アドレス . . . . . . . . . . . .: 192.168.1.193//この部分を覚えておく
サブネット マスク . . . . . . . . . .: xxxxxxxxxxxxxxx
デフォルト ゲートウェイ . . . . . . .: xxxxxxxxxxxxxxxxxxx

入力すると↑のように色々でてきますので、おそらくですが、仮想環境にDockerを使っている場合、イーサネット アダプター vEthernet (Extarnal Virtual Switch)と書いてある欄のIPv4のIPアドレスをスマホのブラウザから入力するとアクセスできると思います。
(例:3000番ポートを開放している場合、http://192.168.1.193:3000/ とすると、PCの開発環境にアクセスできます。)

開発環境が違う場合、他のIPアドレスを入力する必要があると思いますので、適時つながるアドレスを見つけてください!

最後まで読んでいただきありがとうございます!

このように日々学んだことをアウトプットしてます!少しでも皆様のお役に立てれば幸いです!ご指摘などあればコメントいただけますと嬉しいです!

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

if文で論理演算子をたくさん使いたいの巻

はじめに

 本日学んだ、if文で条件を重ねたいときに、論理演算子をどう使うかについてまとめる。

論理演算子

&&→かつ

if a && b
#処理
end

aとbの両方がtrueのとき、処理が実行される。

||→または

if a || b
#処理
end

aかbのどちらかがtrueであれば処理が実行される。

!a
trueとfalseが反対になる。

if !a
#処理
end

aが本当はfalseだと、処理が実行される。(falseがtrueに変わるため)

複数の論理演算子をif文で使う

簡単に言ってしまえば、( )を使って、まとまりを括る。

if ( a && b ) || ( !a && !b )
#処理
end

||があるため、左辺か右辺がtrueであれば、処理が実行される。
左辺は「aかつbがtrue」であれば、左辺全体としてtrueになる。
右辺は「aかつbが本当はfalse」であれば、右辺全体としてtrueになる。
要は、aとbがtrueかfalseで一致してれば、処理が実行されるというコード。

さいごに

高校の数Aでやったような内容だなぁ…

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

rails db:migrateでエラー(StandardError: An error has occurred, this and all later migrations canceled:が出た時の対処

はじめに

これは学習用のメモになります。

今回は$rails db:migrate、または、$rails db:migrateを行った後のエラーが出た時の対処をしていきます。

== 20200107095832 CreateMicroposts: migrating =================================
-- create_table(:microposts)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

SQLite3::SQLException: table "microposts" already exists: CREATE TABLE "microposts" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "content" text, "user_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL)

以下つづく

原因

この前に行ったコマンドのmigrationで何らかの手違いがあると思います。おそらく、migration処理の途中からエラーが起きていて、テーブルは生成されているが、テーブルを生成したmigrationは未実行のまま。といった状態なのかな?と思います

解決策

$ rails db:migrate:reset

データベースのリセットを行った後

$ rails db:migrate

もう一度マイグレーション

データベースを削除し、新しくmigrationファイルを修正して、もう一度migrationを行いたい場合に使うコマンドです。

$ rails db:migrate:reset

データベースのリセットを行った後エラーが発生!

ActiveRecord::NoEnvironmentInSchemaError: 

Environment data not found in the schema. To resolve this issue, run: 

        bin/rails db:environment:set RAILS_ENV=development


Tasks: TOP => db:migrate:reset => db:drop => db:check_protected_environments
(See full trace by running task with --trace)

 対処

rake db:migrate:status

上記のコマンドでdbのステータスを確認します。
⬇︎実行内容

 up     20201013130002  Devise create users
 down    20201015132219  Add devise to users

どうやら、一番下のマイグレーションファイルが怪しい。。。
エディタを確認したところ
同じマイグレーションファイルを二回作成していました。。
なので、一番下のマイグレーションファイルを削除してみます。
※downの状態だったら、手動でファイルを削除しても問題ない

$ rm -rf db/migrate/20201015132219_add_devise_to_users.rb

これでもう一度マイグレーションを行う。
⬇︎実行結果

== 20201013130002 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0061s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0014s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0011s
== 20201013130002 DeviseCreateUsers: migrated (0.0087s) =======================

問題なくできました!

最後に

今回はマイグレーションした際のエラーについて学習しました。
DBリセットしても解決しませんでした。
原因はマイグレーションファイルが重複していたためでした。

間違っているところがあればご指摘いただけると幸いです。

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

Railsチュートリアル備忘録2

環境

macOS Catalina 10.15.5
Rails 6.0.3

Railsチュートリアルとそれに付随するいろいろを書いていきます。
Githubに慣れたいので、チュートリアルは第6版に準拠しています。

1.5.1 Herokuのセットアップとデプロイ

リスト 1.21

$ heroku create

 ›   Warning: heroku update available from 7.42.13 to 7.43.0.
Creating app... done, ⬢ *****
https://*****.herokuapp.com/ | https://git.heroku.com/*****.git

$ git push heroku master

remote:        LoadError: cannot load such file -- uglifier
error: failed to push some refs to 'https://git.heroku.com/*****.git'

下記を参考に、
https://algorithm.joho.info/heroku/error-failed-to-push-some-refs-to/
$ git fetch
$ git rebase heroku/master
を実行したが、下記のようになり解決せず。

fatal: invalid upstream 'heroku/master'

また、下記を参考に、
https://ja.stackoverflow.com/questions/67934/git-push-heroku-master%E3%81%A7%E7%99%BA%E7%94%9F%E3%81%99%E3%82%8B%E3%82%A8%E3%83%A9%E3%83%BC-precompiling-assets-failed-error-failed-to-pu
Gemfile にuglifier のgem追加をしてみる。

Gemfile
gem 'bootsnap',   '1.4.5', require: false
gem 'uglifier'

再度、下記実行
$ git commit -a -m "Update Gemfile for Heroku"
$ git push heroku master

remote: LoadError: cannot load such file -- uglifierは消えたが
error: failed to push some refs to~は変わらず。

$ git push heroku master実行時のエラーに下記があった。

remote: ###### WARNING:
remote: 
remote:        This buildpack was created as a stop-gap measure to allow running applications with Bundler 2 on Heroku.
remote:        Heroku now supports Bundler 2 directly: https://devcenter.heroku.com/changelog-items/1563
remote:        
remote:        Please discontinue use of this buildpack and instead directly use the `heroku/ruby` buildpack.
remote:        
remote:        To remove this buildpack use the `heroku buildpacks` command to list your existing buildpacks.
remote:        
remote:        If you only have one buildpack listed you can run:
remote:        
remote:        ```
remote:        heroku buildpacks:set heroku/ruby
remote:        ```
remote:        
remote:        If you have multiple buildpacks, you'll need to add the buildpack to the correct location using
remote:        `heroku buildpacks:add heroku/ruby -i <correct index>` and then remove this buildpack via:
remote:        
remote:        ```
remote:        heroku buildpacks:remove https://github.com/bundler/heroku-buildpack-bundler2
remote:        ```

$ heroku buildpacksでは下記のBuildpackのみ。

https://github.com/bundler/heroku-buildpack-bundler2

そのため$ heroku buildpacks:set heroku/rubyを実行。

Buildpack set. Next release on pacific-atoll-18588 will use heroku/ruby.
Run git push heroku main to create a new release using this buildpack.

再度$ git push heroku masterすると今度は下記の警告。

remote:        webpack binstubs not found.
remote:        Have you run rails webpacker:install ?
remote:        Make sure the bin directory or binstubs are not included in .gitignore
remote:        Exiting!

https://archive.blog.inomar.me/2018/08/19/rails5-1%E3%81%A7webpack%E3%81%8C%E4%BD%BF%E7%94%A8%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%AE%E3%81%A7vuejs%E3%81%A7%E9%81%8A%E3%82%93%E3%81%A7%E3%81%BF%E3%81%9F/
上記を参考にして$ bundle exec rails webpacker:installを実行。
再度$ git push heroku masterしても上記の警告が消えず。

remote:        webpack binstubs not found.
remote:        Have you run rails webpacker:install ?
remote:        Make sure the bin directory or binstubs are not included in .gitignore
remote:        Exiting!

$ git push heroku mainを実行。

error: src refspec main does not match any
error: failed to push some refs to 'https://git.heroku.com/*****.git'

$ git push heroku main -fで強制プッシュしようとしても同じ結果だったので
gitのリポジトリを削除・再作成し、herokuのアプリも再作成してadd、commit、pushを行ったが、
以下のエラーは消えず…

 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/*****.git'

ダメ元で再度$ git push heroku main -fを実行したところ、ようやく完了。
無意味なダウンロード等を結構してしまったと思うのでこの後無事に動作するのかが不安…

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

トランザクションシミュレータ

トランザクションの検証が面倒すぎる。モデルとしては単純そうだから、作ってしまおう、と思った。

Ruby

ruby.trans.rb
class Command end
class Begin < Command
end
class Rollback < Command
end
class Commit < Command
end
class Read < Command
    attr_reader :var
    def initialize(var)
        @var = var
    end
end
class Write < Command
    attr_reader :var,:val
    def initialize(var,val)
        @var = var
        @val = val
    end
end
class Lock
    attr_reader :tr,:var,:type
    def initialize(tr,var,type)
        @tr=tr
        @var=var
        @type=type
    end
end

class Unlock
    attr_reader :tr,:var
    def initialize(tr,var)
        @tr= tr
        @var=var
    end
end
class Insert
    attr_reader :var,:val
    def initialize(var,val)
        @var=var
        @val=val
    end
end

class Delete
    attr_reader :var
    def initialize(var)
        @var=var
    end
end

class Event
    attr_reader :tr,:cmd
    # tr :String
    # cmd : Command
    def initialize(tr, cmd)
        @tr = tr
        @cmd = cmd
    end
end


class Database 
    attr_reader :vars
    # vars : Map<var_name,value>
    def initialize(vars)
        @vars = vars
    end
end

class Transaction
    attr_accessor :name,:vars
    def initialize(name)
        @name=name
        @vars= {}
    end
end

class State
    attr_reader :db,:events,:pointer,:trs
    def initialize(db,events,trs)
        @db = db
        @locks = []
        @events = events
        @pointer = 0
        @trs = trs
    end

    def next()
        e = @events[@pointer]
        if e then
            if e.cmd.is_a?(Begin) then
                puts "Begin #{e.tr}"
            elsif e.cmd.is_a?(Rollback) then
                puts "Rollback #{e.tr}"
            elsif e.cmd.is_a?(Commit) then
                puts "Commit #{e.tr}"
            elsif e.cmd.is_a?(Read) then
                if @locks.filter {|l| l.tr != e.tr && l.var == e.cmd.var && l.type == :Exclusive}.empty? then
                    puts "Read #{e.tr} var=#{e.cmd.var} => val=#{@db.vars[e.cmd.var]}"
                else
                    puts "Read #{e.tr} var=#{e.cmd.var} => Read failed. This variable is locked by another transaction."
                    raise("Reading failure")
                end
            elsif e.cmd.is_a?(Write) then
                if @locks.filter {|l| l.tr != e.tr && l.var == e.cmd.var}.empty? then
                    pre = @db.vars[e.cmd.var]
                    @db.vars[e.cmd.var]=e.cmd.val
                    puts "Write #{e.tr} var=#{e.cmd.var} val=#{e.cmd.val} => db[#{e.cmd.var}]: #{pre} => #{@db.vars[e.cmd.var]}"
                else
                    puts "Write #{e.tr} var=#{e.cmd.var} val=#{e.cmd.val} => This variable is locked by another transaction."
                    raise("Writing failure")
                end
            elsif e.cmd.is_a?(Lock) then
                if @locks.filter {|l| l.tr != e.cmd.tr && l.var == e.cmd.var && l.type == :Exclusive}.empty? then
                    @locks << e.cmd
                    puts "Lock #{e.tr} var=#{e.cmd.var} type=#{e.cmd.type} => Success."
                else
                    puts "Lock #{e.tr} var=#{e.cmd.var} type=#{e.cmd.type} => This variable is locked by another transaction. Getting lock was failed."
                    raise("Locking failure")
                end
            elsif e.cmd.is_a?(Unlock) then
                @locks.filter!{|l| !(l.tr == e.tr && l.var == e.cmd.var)}
                puts "Unlock #{e.tr}"
            elsif e.cmd.is_a?(Insert) then
                if @db.vars[e.cmd.var].nil? then
                    @db.vars[e.cmd.var] = e.cmd.val
                    puts "Insert #{e.tr} var=#{e.cmd.var} val=#{e.cmd.val} => Success."
                else
                    puts "Insert #{e.tr} var=#{e.cmd.var} val=#{e.cmd.val} => This variable is already exists. Insertion was failed."
                    raise("Insertion failure")
                end
            elsif e.cmd.is_a?(Delete) then
                if !@locks.filter{|l| l.tr != e.tr && l.var == e.cmd.var}.empty? then
                    puts "Delete #{e.tr} var=#{e.cmd.var} => This variable is locked by another transaction. Deletion was failed."
                    raise("Deletion failure")
                end
                if @db.vars[e.cmd.var].nil? then
                    puts "Delete #{e.tr} var=#{e.cmd.var} => No such variable. Deletion was failed."
                    raise("Deletion failure")
                end
                @db.vars.delete(e.cmd.var)
                @locks.filter! {|l| !(l.tr == e.tr && l.var == e.cmd.var)}
                puts "Delete #{e.tr} var=#{e.cmd.var} => Success"
            else
                puts "Other"
            end
        else
            # the last of events
        end
        @pointer += 1
    end
end


@events = [
    Event.new("tr_a",Begin.new()),
    Event.new("tr_b",Begin.new()),
    Event.new("tr_a",Lock.new("tr_a","X",:Shared)),
    Event.new("tr_a",Read.new("X")),
    Event.new("tr_b",Read.new("X")),
    Event.new("tr_a",Lock.new("tr_a","X",:Exclusive)),
    Event.new("tr_a",Write.new("X",20)),
    Event.new("tr_a",Unlock.new("tr_a","X")),
    Event.new("tr_b",Read.new("X")),
    Event.new("tr_b",Insert.new("Y",12)),
    Event.new("tr_b",Delete.new("Y")),
    Event.new("tr_a",Commit.new()),
    Event.new("tr_b",Commit.new())
]

@vars = {"X" => 10}
@db = Database.new(@vars)

@trs = {
    "tr_a" => Transaction.new("tr_a"),
    "tr_b" => Transaction.new("tr_b"),
}

@state = State.new(@db,@events,@trs)

@events.each_index {|i|
    printf("%3d ",i)
    @state.next()
}

実行結果

  0 Begin tr_a
  1 Begin tr_b
  2 Lock tr_a var=X type=Shared => Success.
  3 Read tr_a var=X => val=10
  4 Read tr_b var=X => val=10
  5 Lock tr_a var=X type=Exclusive => Success.
  6 Write tr_a var=X val=20 => db[X]: 10 => 20
  7 Unlock tr_a
  8 Read tr_b var=X => val=20
  9 Insert tr_b var=Y val=12 => Success.
 10 Delete tr_b var=Y => Success
 11 Commit tr_a
 12 Commit tr_b

こんな感じ。

別のトランザクションイベント。Xの排他ロックがかかっていた場合。

    Event.new("tr_a",Begin.new()),
    Event.new("tr_b",Begin.new()),
    Event.new("tr_a",Lock.new("tr_a","X",:Exclusive)),
    Event.new("tr_a",Read.new("X")),
    Event.new("tr_b",Read.new("X")),
  0 Begin tr_a
  1 Begin tr_b
  2 Lock tr_a var=X type=Exclusive => Success.
  3 Read tr_a var=X => val=10
  4 Read tr_b var=X => Read failed. This variable is locked by another transaction.
Traceback (most recent call last):
        3: from tran.rb:182:in `<main>'
        2: from tran.rb:182:in `each_index'
        1: from tran.rb:184:in `block in <main>'
tran.rb:103:in `next': Reading failure (RuntimeError)

tr_bの読み込みがロックされて、このイベント列は失敗する。

振り返り

  1. 次はロック待ちの状況をモデリングしていこう。片方のトランザクションが終われば、もう片方のロック待ちも解消される、というパターン。

  2. まともにテスト書いて、モデルを検証する必要がある。

  3. MVCCではなくて、単純なロック機構でのシミュレーションなので、MVCCのつもりでイベント列を見ていると混乱する。

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

画像を複数件保存・表示する

実装したい事

画像実装機能は実装済みで、複数件の写真を保存・表示させる。

1.モデルのアソシエーション変更

変更前

class Scene < ApplicationRecord
  belongs_to :user
  has_one_attached :image

 省略

end

変更後

class Scene < ApplicationRecord
  belongs_to :user
  has_many_attached :images

 省略

end

2.コントローラーの変更

変更前

class ScenesController < ApplicationController

  def new
    @scene = Scene.new
  end

  def create
    @scene = Scene.new(scene_params)
    if @scene.save
      redirect_to root_path
    else
      render :new
    end
  end
  def show
    @scene = Scene.find(params[:id])
  end

  private
  def scene_params
    params.require(:scene).permit(:name, :user_name, :comment, :image).merge(user_id: current_user.id)
  end
end

変更後

class ScenesController < ApplicationController

  def new
    @scene = Scene.new
  end

  def create
    @scene = Scene.new(scene_params)
    if @scene.save
      redirect_to root_path
    else
      render :new
    end
  end
  def show
    @scene = Scene.find(params[:id])
  end

  private
  def scene_params
    params.require(:scene).permit(:name, :user_name, :comment, image: []).merge(user_id: current_user.id)
  end
end

3.ビューの変更

投稿ページ

変更前

  <%= form_with model: @scene, local: true do |f| %>
   <div class="img-upload">
      <div class="weight-bold-text">
        現場画像
        <span class="indispensable">必須</span>
      </div>
      <div class="click-upload">
        <p>
          クリックしてファイルをアップロード
        </p>
          <%= f.file_field :image, id:"item-image"%>
      </div>
    </div>
省略
<% end %>

変更後

 <%= form_with model: @scene, local: true do |f| %>
   <div class="img-upload">
      <div class="weight-bold-text">
        現場画像
        <span class="indispensable">必須</span>
      </div>
      <div class="click-upload">
        <p>
          クリックしてファイルをアップロード
        </p>
          <%= f.file_field :image, multiple: true , id:"item-image"%>
      </div>
    </div>
省略
<% end %>

閲覧ページ

変更前

省略
<%= image_tag image %>
省略

変更後

<% @scene.image.each do |image| %>
  <%= image_tag image %>
<% end %>

写真.png

上記の変更点で、複数件の写真の投稿・表示が可能となりました。

今後について

写真の表示方法が横並びにしているだけなので、間隔を空けながらビューファイルを整理する。

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

プログラミングコードを販売できるサービス「Code-sell」をリリースした!

初めに

今回、約2か月ぶりにwebアプリを公開しました。
プログラミングコードを販売できるサービス Code-sellです。

https://www.code-sell.net/

なるべく気軽に販売・購入できるように工夫しました。
100円から価格設定できます。
ちなみに僕が今まで作ってきた4つのwebアプリのコードをすべて無料で公開しています!
ほしい人いるかわからないけど何かの参考にでも...。

code-sell.png

↑topページ

なぜ作ったか

今まで作ったwebアプリを販売(譲渡)しようと思ったのですが権利の問題や面会などめんどくさそうなものがたくさん出てきました。そんな時に思いつきました。Code-sellは譲渡はせずコードをダウンロードするだけなので権利の問題も考えなくていいですし、面会ももちろんありません。

できること

google認証
stripeを使った、購入、送金
いいね
通知
言語タグ・説明タグ

とかです。基本的な機能しかいまはありません...。

使った技術

rails6
ruby2.7
stripe
postgresql
slim
ridgepole

くらいですかね。
このなかでもstripeには本当に苦労しました。
情報はあるんですがどれもこれもコードの説明?で実践的な情報が本当に少ないです。
なので組み立てるのにかなり時間をかけました。
絶対にstripeに関する記事を出すと約束します。

終わりに

読んでくれてありがとうございました。code-sell使ってみてください!
https://www.code-sell.net/

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

プログラミングコードを販売できるサービス「Code-sell」をリリースした(個人開発)

初めに

今回、約2か月ぶりにwebアプリを公開しました。
プログラミングコードを販売できるサービス Code-sellです。

https://www.code-sell.net/

なるべく気軽に販売・購入できるように工夫しました。
100円から価格設定できます。
ちなみに僕が今まで作ってきた4つのwebアプリのコードをすべて無料で公開しています!
ほしい人いるかわからないけど何かの参考にでも...。

code-sell.png

↑topページ

なぜ作ったか

今まで作ったwebアプリを販売(譲渡)しようと思ったのですが権利の問題や面会などめんどくさそうなものがたくさん出てきました。そんな時に思いつきました。Code-sellは譲渡はせずコードをダウンロードするだけなので権利の問題も考えなくていいですし、面会ももちろんありません。

できること

google認証
stripeを使った、購入、送金
いいね
通知
言語タグ・説明タグ

とかです。基本的な機能しかいまはありません...。

使った技術

rails6
ruby2.7
stripe
postgresql
slim
ridgepole
JavaScript

くらいですかね。
このなかでもstripeには本当に苦労しました。
情報はあるんですがどれもこれもコードの説明?で実践的な情報が本当に少ないです。
なので組み立てるのにかなり時間をかけました。
絶対にstripeに関する記事を出すと約束します。

終わりに

読んでくれてありがとうございました。ぜひcode-sell使ってみてください!
https://www.code-sell.net/

※まだ公開したばかりなので不具合を見つけたらお問い合わせフォームやらQiitaのコメントなどで教えてください。お願いします。

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

コードを販売できるサービス「Code-sell」をリリースした(個人開発)

初めに

今回、約2か月ぶりにwebアプリを公開しました。
プログラミングコードを販売できるサービス Code-sellです。

https://www.code-sell.net/

なるべく気軽に販売・購入できるように工夫しました。
100円から価格設定できます。
ちなみに僕が今まで作ってきた4つのwebアプリのコードをすべて無料で公開しています!
ほしい人いるかわからないけど何かの参考にでも...。

code-sell.png

↑topページ

なぜ作ったか

今まで作ったwebアプリを販売(譲渡)しようと思ったのですが権利の問題や面会などめんどくさそうなものがたくさん出てきました。そんな時に思いつきました。Code-sellは譲渡はせずコードをダウンロードするだけなので権利の問題も考えなくていいですし、面会ももちろんありません。

できること

google認証
stripeを使った、購入、送金
いいね
通知
言語タグ・説明タグ

とかです。基本的な機能しかいまはありません...。

使った技術

rails6
ruby2.7
stripe
postgresql
slim
ridgepole
JavaScript

くらいですかね。
このなかでもstripeには本当に苦労しました。
情報はあるんですがどれもこれもコードの説明?で実践的な情報が本当に少ないです。
なので組み立てるのにかなり時間をかけました。
絶対にstripeに関する記事を出すと約束します。

終わりに

読んでくれてありがとうございました。ぜひcode-sell使ってみてください!
https://www.code-sell.net/

※まだ公開したばかりなので不具合を見つけたらお問い合わせフォームやらQiitaのコメントなどで教えてください。お願いします。

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

コードを販売できるサービス「Code-sell」をリリースした!(個人開発)

追記
メール認証のエラーを修正しました。
いままで気づけなくてすみませんでした。

初めに

今回、約2か月ぶりにwebアプリを公開しました。
プログラミングコードを販売できるサービス Code-sellです。

https://www.code-sell.net/

なるべく気軽に販売・購入できるように工夫しました。
100円から価格設定できます。
ちなみに僕が今まで作ってきた4つのwebアプリのコードをすべて無料で公開しています!
(今非公開にしています。すみません。)
ほしい人いるかわからないけど何かの参考にでも...。

code-sell.png

↑topページ

なぜ作ったか

今まで作ったwebアプリを販売(譲渡)しようと思ったのですが権利の問題や面会などめんどくさそうなものがたくさん出てきました。そんな時に思いつきました。Code-sellは譲渡はせずコードをダウンロードするだけなので権利の問題も考えなくていいですし、面会ももちろんありません。

できること

google認証
stripeを使った、購入、送金
いいね
通知
言語タグ・説明タグ

とかです。基本的な機能しかいまはありません...。

使った技術

rails6
ruby2.7
stripe
postgresql
slim
ridgepole
JavaScript

くらいですかね。
このなかでもstripeには本当に苦労しました。
情報はあるんですがどれもこれもコードの説明?で実践的な情報が本当に少ないです。
なので組み立てるのにかなり時間をかけました。
絶対にstripeに関する記事を出すと約束します。

終わりに

読んでくれてありがとうございました。ぜひcode-sell使ってみてください!
https://www.code-sell.net/

※まだ公開したばかりなので不具合を見つけたらお問い合わせフォームやらQiitaのコメントなどで教えてください。お願いします。

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

SSHでポートフォワード接続して、ファイルの送受信をする

環境

Ubuntu 16.04.7 LTS (Xenial Xerus)
ruby 2.5.0p0

やりたい事

Rubyプログラムをポートフォワードで指定したサーバーに転送した後、転送先のサーバーでRubyプログラムを実行させて、csvファイルを標準出力させます。そして、標準出力したcsvファイルを、自分のローカル環境に持ってくるという事をやります。

コード

def ssh_connect

    begin
     # ファイルを転送
        _cmd = system('scp -P 54322 -i /home/.ssh/id_rsa /home/syori.rb server@153.153.xx.xx:/home')

        # ポートフォワードの設定
        Net::SSH.start(
            '153.153.xx.xx',
            'username',
            :keys => '/home/.ssh/id_rsa',
            :port => 54322
            ) do |_a|
                _a.forward.local(2222,'192.168.xx.xx', 54323)
                _a.exec!('ruby syori.rb')
              end

        # ファイルを取得する
        _cmd = system('scp -P 54322 -i /home/.ssh/id_rsa server@153.153.xx.xx:/home/users.csv /home')

    rescue => ex
        print "***** " + self.class.name.to_s + "." + __method__.to_s + " *****\n"
        print(ex.class," -> ",ex.message)
    end
end

解説

system

RubyでLinuxコマンドを発行するメソッドです。戻り値は、ture/falseが返ってきます。

scp

ファイル転送するコマンド(プロトコル)です。ファイル転送というと、ひと昔はftpがよく使われていたと思いますが、ftpはログインする時のアカウント情報を暗号化できないため、セキュリティを高めるために、SSH機能が標準装備されているscpを使う事が基本になります。

scpのオプション

-P

ポート番号を指定します。SSHのポート番号は22が、ウェルノウンポート番号として指定されていますが、外向けに公開しているサーバーであれば、変な攻撃を受けないために、カスタマイズしている場合があると思います。接続するサーバーのSSHのポート番号を指定します。

-i

SSH通信で利用する公開鍵を保存しているパスを絶対パスで設定します。大抵、ホームの.sshに置かれます。

転送するファイル名を絶対パスで設定します。転送先の指定は、転送先のサーバー名:転送先のディレクトリを絶対パスで指定します。

ポートフォワードの解説

Net::SSH.start(
     フォワード元IPアドレス, 
     フォワード元のユーザー名,
     :keys => 接続元の秘密鍵の絶対パス,
     :port => 接続元のポート番号
     ) do |_a|
         _a.forward.local(フォワード元のポート番号(何でもいい),
                  'ポートフォワード先のIPアドレス', 
                  フォワード先のポート番号)
         _a.exec!('接続先で実行したいコマンド')
     end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]Active Hashの導入

はじめに

Active_Hashとは、都道府県名やカテゴリー選択などの変更されないデータをモデルファイル内に直接記述することで、データベースへ保存せずにデータを取り扱うことができるgemです。
Active_Hashを用いることで、モデルファイルに直接記述した変更されないデータに対して、ActiveRecordのメソッドを用いることができます。

目次

1.Active Hashのインストール
2.モデルの作成
3.マイグレーションファイルの編集
4.アソシエーションの設定
5.ビューファイルの編集

1. Active Hashのインストール

gemfileに以下を記述します。
その後、コマンドでbundle installを実行します。

gemfile
gem 'active_hash'

2. モデルの作成

今回はPostモデルとCategoryモデルを作成します。
Postモデルはいつも通りに作成します。

ターミナル
rails g model post

Categoryモデルを作成する際は、「--skip-migration」オプションを使用します。
「--skip-migration」を使用することで、マイグレーションファイルの生成を行わないようにします。
今回、カテゴリーを情報をデータベースには保存をしないのでマイグレーションファイルを作成しません。

ターミナル
rails g model category --skip-migration

category.rbでCategoryクラスを定義し、ActiveHash::Baseクラスを継承します。
ActiveHash::Baseを継承することで、Categoryモデルに定義したオブジェクトに対してActiveRecordのメソッドが使用できるようになります。

app/models/genre.rb
class Category < ActiveHash::Base
  self.data = [
    { id: 1, name: '---' },
    { id: 2, name: '化粧水' },
    { id: 3, name: '乳液' },
    { id: 4, name: 'オールインワン' },
    { id: 5, name: 'クレンジング' },
    { id: 6, name: '洗顔料' },
    { id: 7, name: '日焼け止め' },
    { id: 8, name: 'リップ' },
    { id: 9, name: '香水' },
    { id: 10, name: 'ヘアカラー' },
    { id: 11, name: 'ヘアスタイリング' },
    { id: 12, name: 'シャンプー・コンディショナー' },
    { id: 13, name: 'コンタクトレンズ' }
  ]
end

データは配列にハッシュの形で格納しています。

3. マイグレーションファイルの編集

postsテーブルにはcategory_idカラムを作成します。
_idになっているのはidに紐づいているカテゴリーを取得し、カテゴリーのidをpostsテーブルに保存するからです。
カラム型はinteger型にします。

db/migrate/20XXXXXXXXXXXX_create_articles.rb
~~
t.integer :category_id, null: false
~~

4. アソシエーションの設定

ActiveHashにはbelongs_to_active_hashメソッドが用意されています。
ActiveHashを使って作成したモデルに対してアソシエーションを設定する場合は、belongs_to_active_hashメソッドを使います。
ActiveHash::Associations::ActiveRecordExtensionsを記述することで、belongs_to_active_hashメソッドを使用できます。

app/models/post.rb
class Post < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :category
end

5. ビューファイルの編集

今回はデータをプルダウン形式で表示しました。
ですので、collection_selectメソッド使って表示します。

<%= form.collection_select(保存されるカラム名, オブジェクトの配列, カラムに保存される項目(表示する際に参照するDBのカラム名), 選択肢に表示されるカラム名, オプション, htmlオプション(classなど)) %>
app/views/posts/new.html.erb
<%= f.collection_select(:category_id, Category.all, :id, :name, {}, {class:”category-select"}) %>

参考リンク

https://github.com/zilkey/active_hash

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

Herokuへのデプロイ【Ruby on Rails】初心者

開発環境:macOS Catalina/GitHub/MySQL

※Herokuへのユーザー登録完了後の手順です。
備忘録として残したいと思い、記事にしました。
初心者なので、至らない点があるかと思いますがその際はコメントいただけたらと思います。

1. Heroku CLIをインストールする

コマンド

% brew tap heroku/brew && brew install heroku

バージョンの確認

% heroku --version

バージョンが出力されたらインストール完了

公式サイト:https://devcenter.heroku.com/articles/heroku-cli

2. ログインする

% heroku login --interactive
  Email: それぞれ入力
  password: それぞれ入力

:information_desk_person:登録したメールアドレスがLogged in asの後に表示されていればログイン成功

3. Gemの導入

Gemfile ※一番下に入力

Gemfile
group :production do
   gem 'rails_12factor'
end

:information_desk_person:bundle installと再起動をお忘れなく

:information_desk_person:Gitで管理している場合はコミットしておきます

4. Heroku上にアプリケーションを作成する

% heroku create [アプリケーション名]
% git config --list | grep heroku

:information_desk_person:この時、"fatal: not in a git directory"以外が出力されていれば作成完了です!

5. MySQLを使えるようにするコマンド

% heroku addons:add cleardb
% heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`
% heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}

:information_desk_person:URLの"mysql2"はGemの使用状況によって変更する
以降は非公開の値を管理する為の環境変数の設定などを行います。

6. 公開を確認するコマンド

% heroku apps:info

参考:https://devcenter.heroku.com/articles/getting-started-with-rails6

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

Railsで生SQLをリードレプリカに投げる

switch_pointというgemを使用するのだが、
readmeにちらっとだけ書いてあって、例が示されてないのでわかりにくいがswitch_point_proxy.model_for_connectionってのを使えばいいみたい

https://github.com/eagletmt/switch_point

例えばUserモデルだったら、

use_switch_point :slave

みたいに追加して、

rows = []

User.with_readonly do
  con = User.switch_point_proxy.model_for_connection.connection
  sql = "select * from users limit 1"
  rows = con.select_all(sql)
end

みたいな感じで行けるみたい

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

Rails Active_storage -画像の保存を簡易化する-

Active storageとは

Active Storageは、ファイルアップロードを行うための機能です。これを使えば、フォームで画像の投稿機能などが簡単に作れます。クラウドストレージサービス(Amazon S3, Google Cloud Storage, Microsoft Azure Storageなど)に対するファイルのアップロードを簡単に行うことができます。

導入方法

  • Active_storageに沿ったテーブルを作る
% rails active_storage:install

Active_storageをインストールし、関連ファイル(マイグレーションなど)を生成

%rails db:migrate

Seaquel Proを確認すると以下のようなテーブルが生成されていたらここまでは成功です。
image.png
これで画像を保存するための「入れ物」は完成しました。

モデルの記述: 画像1枚を添付する

「メッセージに画像を添付する」、「商品情報に画像を添付する」など画像情報は他モデルと関わることが多くあります。ここでよくあるのが、「imagesテーブルがあるからimageモデルを作ってアソシエーションを組む」という考え方です。実はactive_storageで作成したテーブルに関しては別途モデルを作る必要はなありません。関わらせたいモデルに「has_one_attached :ファイル名」を追記すればアソシエーションは完成します。
今回はメッセージとアソシエーションを組むことを想定していきます。
models/message.rb

class Message < ApplicationRecord
  ~ associationなどの記述は省略~

  has_one_attached :image

end

アソシエーションというよりも、「擬似的な画像カラムを作った」と言った方がイメージしやすいかもしれません。

コントローラの記述: ストロングパラメータ

seaquel_proのmessageテーブルを見てみると、imageカラムは存在していません
image.png

しかしながらモデルで記述したhas_one_attachedによって、messagesテーブルには「擬似的なimageカラム」が存在していることになっています。
※画像情報はrails active_storage:installで生成したテーブル内に保存されます。

このことからmessages_controller.rb内のparamsで画像の情報が飛ばせるようになりました。

controllers/messages_controller.rb

class MessagesController < ApplicationController

  def new
    @message = Message.new
  end

  def create
   @mesage = Message.create(message_params)
  end

  private

  def message_params
      params.require(:message).permit(:content, :image).merge(user_id: current_user.id)
  end
end

ビューの記述: 画像の送信

ここに関してはいつも通りform要素のfile_fieldを使います。

<%= form_with model: @message, local: true  do |form| %>
  <%= form.text_area :content %><br>
  <%= form.file_field :image %><br>
  <%= form.submit %>
<% end %>

ビューの記述: 画像の表示

imgタグでも可能ですが、railsのヘルパーメソッドであるimage_tagを使って記述を簡略化します。

<% if @message.image.attached? %>
  <%= image_tag @message.image %>
<% end %>

以上です!!

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

【Rails】deviseで現在ログインしているユーザー情報の取得方法

はじめに

deviseでは「現在ログインしているユーザーの情報を取得」する事ができます。
例えば、「名前」「生年月日」「住所」「電話番号」など、対象のユーザーが既に登録した情報を表示する方法を紹介します。

目次

1.current_userメソッド
2.遷移先のview

開発環境

ruby 2.6.5
rails 6.0.0
devise 4.7.3

前提

devise導入済み
model生成済み
ユーザー登録済みでデータを既に持ってる
view作成済み

実装

それでは実装して行きます。

1.current_userメソッド

deviseを導入しているため使用できるメソッドで、current_user(現在ログインしているユーザー)の情報が取得できます。

index.html.erb
<%= link_to current_user.nickname, edit_user_registration_path(current_user), class: "user-name" %>
          #↑ここ#                           #↑ここ#

例えば、マイページでユーザー情報を編集したい時を想定します。link_toメソッドでcurrent_user.nameと記述すると、今ログインしてるユーザーのnameカラムに保存されてる名前が表示れます。
また、url指定したpathの後ろにcurrent_userをつける事で、遷移先にもそのユーザー情報を表示させる事ができます。

※注意:urlはreils routesでコントローラー#アクションを探しください。

2.遷移先のview

遷移先のviewページでは、既に登録されてるユーザーの情報を表示させます。

edit.html.erb
<%= form_with model: @user, url: edit_addresses_path,  class: 'registration-main', local: true, method: :get do |f| %>

<%= f.text_area :name, class:"input-default", id:"name", placeholder:"例) 太郎", maxlength:"40" %>

<% end %>

今回ユーザー情報を編集するページを作りたいのでapp> views> devise >registrationsにあるedit.html.erbのファイルを編集します。
form_withメソッドを使います。
devise内部で@userが定義されていて、既にデータが代入されてるので「model: @user」とします。
「do |f|」とする事で「end」までの「f.text_area :カラム名(今回はname)」に現在のユーザー情報が表示されます。

※注意:deviseのviewをよび出してる場合は既に生成さてるファイルを使うと便利です。
参考記事
https://qiita.com/AKI3/items/bf0d5b57029abfc8154c

まとめ

以上、現在ログインしているユーザー情報の取得方法でした。
current_userメソッドを使う事がポイントです。

最後に

私はプログラミング初学者ですが、同じ様に悩んでる方々の助けになればと思い、記事を投稿しております。
それでは、また次回お会いしましょう〜

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

【Ruby on Rails】Skipprを使用した画像スライドショー

目標

スライドショー.gif

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

前提

※ ▶◯◯ を選択すると、説明等が出てきますので、
  よくわからない場合の参考にしていただければと思います。

流れ

1 gemの導入
2 Skipprサイトからファイルをダウンロード
3 実際のコード

gemの導入

Railsでjqueryを使えるようにします。

Gemfile
gem 'jquery-rails'
ターミナル
$ bundle insatll
app/assets/javascripts/application.js
//= require jquery ←追加
//= require jquery_ujs ←追加
//= require activestorage
//= require turbolinks
//= require_tree .

Skipprサイトからファイルをダウンロード

公式サイト
http://austenpayan.github.io/skippr/

こちらのGithubをクリックし、ZIPファイルをダウンロードしてください。
スクリーンショット 2020-10-15 13.20.39.png
スクリーンショット 2020-10-15 13.22.35.png

解凍後、下記の通りに保存してください。

  • skippr.min.jsファイルは、app/assets/javascriptsフォルダに
  • skippr.cssファイルは、app/assets/stylesheetsフォルダに スクリーンショット 2020-10-15 13.25.43.png

実際のコード

app/assets/imagesにimage1.jpg〜image4.jpgを保存してください。

app/views/application.html.erb
<div id="box">
  <div id="images">
    <div class="image1"></div>
    <div class="image2"></div>
    <div class="image3"></div>
    <div class="image4"></div>
  </div>
</div>
app/assets/stylesheets/application.css
/* 高さを指定することにより画像が表示される */
#box{
  height: 600px;
}
.image1 {
  background-image: url(image1.jpg);
}
.image2 {
  background-image: url(image2.jpg);
}
.image3 {
  background-image: url(image3.jpg);
}
.image4 {
  background-image: url(image4.jpg);
}
app/assets/javascripts/application.js
$(document).ready(function () {
  $("#images").skippr({
    // スライドショーの変化 ("fade" or "slide")
    transition : 'slide',
    // 変化に係る時間(ミリ秒)
    speed : 1000,
    // easingの種類
    easing : 'easeOutQuart',
    // ナビゲーションの形("block" or "bubble")
    navType : 'block',
    // 子要素の種類("div" or "img")
    childrenElementType : 'div',
    // ナビゲーション矢印の表示(trueで表示)
    arrows : true,
    // スライドショーの自動再生(falseで自動再生なし)
    autoPlay : true,
    // 自動再生時のスライド切替間隔(ミリ秒)
    autoPlayDuration : 3000,
    // キーボードの矢印キーによるスライド送りの設定(trueで有効)
    keyboardOnAlways : true,
    // 一枚目のスライド表示時に戻る矢印を表示するかどうか(falseで非表示)
    hidePrevious : false
  });
});

まとめ

比較的簡単に導入できるものの、
bootstrapと組み合わせるとうまくいかないこともあるので、
その場合はこちらを参考にしてください。
【Ruby on Rails】bootstrap4のcarouselをeachメソッドを使いスライドショーを実装

またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら https://twitter.com/japwork

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

RubyでのTSVファイルとCSVファイルの取り扱い方

はじめに

この記事では、Rubyにおいて、TSVファイルやCSVファイルを扱う上での基礎知識を、myメモ的な感じでまとめました。TSV,CSV以前に、Fileクラスについても一緒に確認できればと思います。

TSVファイルとは

タブ区切りでデータが格納されたファイル

CSVファイルとは

コンマ( , )区切りでデータが格納されたファイル

本記事では以下のTSVファイルを例にあつかいます

# meibo.txt
john    m   18
paul    m   20
alice   f   15
dabid   m   17
jasmin  f   17

Fileクラスについて

ファイルを開く

#書き方1
File.open("meibo.txt") do |file|
  処理
end

#書き方2
file = File.open("meibo.txt")
  処理
file.close

書き方1はファイルを開いても勝手に閉じてくれますが、書き方2ではcloseメソッドをしないとファイル開きっぱなしです。なので、書き方1の方が個人的には好きです。

File.open("meibo.txt") do |file|
  puts.file
end

例えば、上記のようにすると、以下のようなFileオブジェクトの標準出力を得ます。

#<File:0x00007fba4497ea68>

ファイルを読み込む

開いたファイルは、読み込んだりします。

File.open("meibo.txt") do |file|
  p file.read
end

すると、以下のような標準出力になります。

"john\tm\t18\npaul\tm\t20\nalice\tf\t15\ndabid\tm\t17\njasmin\tf\t17\n"

いきなり読み込んでも大丈夫です。

file = File.read("meibo.txt")
p file

#=>
"john\tm\t18\npaul\tm\t20\nalice\tf\t15\ndabid\tm\t17\njasmin\tf\t17\n"

一行ずつ読みたい場合、以下のように、一度ファイルを開いて、その処理の部分で、一行ずつ読ませて、好きな処理を入れます。

File.open("meibo.txt") do |file|
  file.each do |line|
    処理
  end
end

#例えば

File.open("meibo.txt") do |file|
  file.each do |line|
    p "#{line.chomp}\tfoo"
  end
end

#=>
"john\tm\t18\tfoo"
"paul\tm\t20\tfoo"
"alice\tf\t15\tfoo"
"dabid\tm\t17\tfoo"
"jasmin\tf\t17\tfoo"

以上がFileクラスでの扱い方ですが、出力が数珠つなぎの文字列になっているので、少々扱いづらいかと思います。そこで、CSVクラスを使用することで、データを扱いやすくすることができます。

CSVクラスについて

本来CSVファイルを扱うためのクラスだと思いますが、col_sepオプション(指定した文字列で区切ってくれる)を使うとTSVファイルもCVSクラスで扱えます。CSVクラスを使用するときは行頭にrequire "csv"を付けます。

require "csv"

#openメソッドを使うなら
CSV.open("meibo.txt", col_sep: "\t") do |tsv|
  p tsv.read
end

#openメソッドを使わないなら
tsv = CSV.read("meibo.txt", col_sep: "\t")
p tsv

#=>
[["john", "m", "18"], ["paul", "m", "20"], ["alice", "f", "15"], ["dabid", "m", "17"], ["jasmin", "f", "17"]]

CSVメソッドを用いて読み込むと、出力結果は配列に入れて返されます。
こうすることで、データとして扱いやすくなります。
一行ずつ読ませたいなら以下のforeachメソッドを使います。

require "csv"

CSV.foreach("meibo.txt", col_sep: "\t") do |line|
  処理
end

#例えば
CSV.foreach("meibo.txt", col_sep: "\t") do |line|
  p line
end

#=>
["john", "m", "18"]
["paul", "m", "20"]
["alice", "f", "15"]
["dabid", "m", "17"]
["jasmin", "f", "17"]

こうすることで、各行ごとに配列に対して処理を行うことができます。

ちなみに、もちろんですが、新たにCSVファイルを開いて、そこに書き込むこともできます。

require "csv"

CSV.open("meibo.csv","w") do |line| #"w"は書き込みモード
 line << ["michel","m",16]
end

# meibo.csv
michel,m,16

TSVをCSVに変換

最後に、これまでにご紹介した構文を使って、TSVファイルをCSVファイルに変換できます。
いきなり結論ですが、以下です。

require "csv"

CSV.open('meibo.csv', 'w') do |csv|
  CSV.foreach("meibo.txt", col_sep: "\t") do |line|
   csv << line
 end
end

まず、書き込みモードでCSVファイルを用意します。そのCSVファイルに、foreachでTSVファイルの各行を一行ずつCSVに格納して行くという、流れです。
CSVからTSVについてもこの逆を行えばOKです。

さいごに

Fileクラスは最初はちょっとよくわからなかったんですが、この記事書きながら頭の中整理できたので、これからもどんどん使っていこうと思います。

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

【Ruby】クラスとインスタンス

はじめに

Rubyでは予め定義されている値とは別に、自分で新しい種類の値を作成することができます。

その際「どんな特性を持つのか?」、「どんな動作をするのか?」などの設計図を用意して、作成できます。

新しい種類の値を作成するために必要な概念が、「クラス」「インスタンス」です。

クラスとは

値の元となるもの。値の共通のルールを定義することができます。
ここで定義するルールとは、共通の「属性」と「処理(メソッド)」です。

クラスを使用する利点は、共通の情報をまとめ、個別の情報は各データごとに分けることで、開発・管理・保守が容易になるといったことが挙げられます。

クラスは例えるならば、車の製造における設計図であり、そこから生み出される値が車といえます。
クラスはあくまで設計図ですので、実体がなくそれ単体ではデータとして扱うことができません。

クラスの定義は以下のように行います。

class クラス名
  # 変数やメソッドの定義
end

クラス名は半角英大文字から始めるのがルールです。
(例)User,Groupなど

インスタンスとは

クラスを元にして作られるデータのことです。
インスタンスはクラスとは異なり、実体を持つのでデータとして使用することができます。
クラスが車の設計図であるならば、インスタンスはそこから生成される車といえます。

インスタンスは、クラスが使用できるnewメソッドを実行することにより生成します。

newメソッドとは

クラスが予め持っているメソッドです。
使用したクラスのインスタンスを生成して返します。

使い方は以下のような形です。

#ここではインスタンスを生成し、変数に代入している
変数名 = クラス名.new

基本的には上記のように、生成したインスタンスは変数へ代入し、再利用します。
これは、インスタンスを生成したあとからデータを追加したり、メソッドを実行できるようにするためです。

以下で実際にクラス名を指定して、インスタンスを生成します

class Car

end

fire_truck = Car.new

これで「Car」というクラスからインスタンスを生成し、「fire_truck」という変数に代入することができました。

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

link_toって奥が深いねって話(原因不明)

アプリ開発中投稿ボタンを押したら投稿ページに遷移するようにlink_toで記述をしていた時

  <%= link_to "投稿", 'new_photo_path'%>

最初はこのように記述しました。
するといつものスクリーンショット 2020-10-15 3.30.59.png
この赤いエラー分が出ました。。

仮定

routes.rbがうまく記述できていない
綴りが間違えてる

routes.rbを確認しにきました

routes.rb
resources :photos, except: :index
  root to: 'photos#index'

resourcesでindexを除外していること以外に不思議な点はなく

rails routes

で確認しても問題はなし…

スクリーンショット 2020-10-15 3.35.14.png

綴りも間違えていない…

行ったこと

PrefixではなくController#Actionの方を記述した
new_photo GET /photos/new(.:format)

index.html.erb
<%= link_to "投稿", '/photos/new'%>

で解決しました…

追加

@scivola さんからのコメントで原因がわかりました
@scivola さんありがとうございました。
Prefixは''で囲むと文字列になってしまうようです…
なので自分の場合は文字列として認識されているようです

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

マイグレーション基礎知識のまとめ rails db:rollbackとカラムの追加/削除

はじめに

【この記事から得られる知識】
・マイグレーションについて
・rails db:rollbackの実行手順
・カラムの追加と削除の実行手順
・カラムがreferences型の場合の追加と削除の実行手順

【環境】
・macOS Catalina
・rails 6.0.0
・ruby 2.6.5

マイグレーションとは

・テーブルの設計図や仕様書のこと 
・データベースにテーブルを作成する際に重要な役割をもっている
 -マイグレーションファイルにカラムの型、カラム名、オプションの情報を記述する
 -情報を反映させるとテーブルの作成・変更ができる

マイグレーションの実行手順

①モデルを作成
②モデル作成時に生成されるマイグレーションファイル(db/migrate/2020~~~~.rb)に必要な情報を記述する

db/migrate/20201014123456_create_address.rb
class CreateAddresses < ActiveRecord::Migration[6.0]
  def change
    create_table :addresses do |t|
    # t.カラムの型 :カラム名,     オプション
      t.string :postal_code,    null: false
      t.string :city,           null: false
      t.string :address_line,   null: false
      t.string :phone_number,   null: false
      t.references :order,      null: false, foreing_key: true
      t.timestamps
    end
  end
end

③記述したテーブルのカラムを反映させるために作成中のアプリケーションのディレクトリにいることを確認した後ターミナルでrails db:migrateを実行

% rails  db:migrate

④ターミナルに以下のような記述があれば成功!

== 20XXXXXXXXXXXX CreateAddresses: migrating ======================================
-- create_table(:addresses)
   -> 0.0395s
== 20XXXXXXXXXXXX CreatePosts: migrated (0.0396s) =============================

念のためsequelproでも記述した情報が表示されていれるか確認する
※情報が反映されていない場合は更新ボタンをクリックする


せっかくrails db:migrateしたのにテーブルにミスがあった!

「どうしよう、、、」
「マイグレーションを編集したいっ!」ていうときありますよね。

しかし、一度実行すると再度実行できない仕組みになっています。
なぜかというと設計を履歴として残しあとでどのような変更をしたか確認できるようにするためです。

もしスペルミスでカラム名を変更したい場合であればわざわざ履歴に変更を残したくないですよね。

その場合はrails db:rollback コマンドを使いましょう。(反映済みの情報を差し戻すことができるため変更の履歴が残りません。)
それ以外の場合はカラムの追加/削除用のマイグレーションファイルを作成して変更を行いましょう。(新たにファイルを作成して変更をするため履歴が残ります。)

以下でこれらの説明をしたいと思います。


rails db:rollback 実行手順①~⑥

rails db:migrate:statusコマンドでマイグレーションファイルの状況を確認

% rails db:migrate:status

・実行するとマイグレーションの履歴が表示され、statusがupとdownで状況が表示される
・upは実行済み、downは修正可能の状態を意味する

# rails db:migrate:stauts 実行結果

database: アプリ名_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20201001015223  Create orders
   up     20201001092756  Create addresses
   up     20201014023427  Add id to addresses
   up     20201014030100  Add id to orders

rails db:rollbackを実行してup(実行済み)をdown(修正可能)にする

% rails db:rollback

③もう一度rails db:migrate:statusを実行しマイグレーションファイルの状況を確認する

database: アプリ名_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20201001015223  Create orders
   up     20201001092756  Create addresses
   up     20201014023427  Add id to addresses
  down    20201014030100  Add id to orders

④変更したいマイグレーションファイルのstatusがdownであることが確認できると今回の場合db/migrate/2020101430100_~~.rbのファイルを修正する
rails db:migrateを実行し修正内容を反映させる

% rails  db:migrate

⑥念のためsequelproでも記述した情報が表示されていれるか確認する
※情報が反映されていない場合は更新ボタンをクリックする

【補足情報】

任意のマイグレーションファイルをrollbackしdownの状態にしたい場合は
rails db:rollback STEP=数値(戻りたい箇所が下から数えて何番目か)というふうに記述し実行する
※一番下を1とする

# 下から2番目をrollbackしたい場合 
% rails db:rollback STEP=2

statusを確認すると下から2番目までdownになっていることが確認できる

database: アプリ名_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20201001015223  Create orders
   up     20201001092756  Create addresses
  down    20201014023427  Add id to addresses
  down    20201014030100  Add id to orders

後は同じようにマイグレーションファイルを修正しrails db:migrateを実行する

カラムの追加/削除 実行手順(パターン1, 2)

最初に前提の知識としてカラムの追加はadd_columnカラムの削除はremove_columnと記述する

    # カラムの追加
    add_column :users, :first_name, :string
    # カラムの削除
    remove_column :users, :last_name, :string

パターン1 : 順番に記述する方法

rail g migration ファイル名を実行
ファイル名はAddカラム名To追加先のテーブル名とする(ファイル名は任意のものでもいいが、Add~To~が後から見たときにわかりやすく定着したファイル名のつけ方になっている)

# nameカラムをUsersテーブルに追加する場合
% rails g migration AddNameToUsers

生成されるファイルの中身

db/migrate/20200000000000_add_names_to_users.rb
class AddNamesToUsers < ActiveRecord::Migration[6.0]
  def change 
  end
end

②新しく生成されたマイグレーションファイルに情報を記述する

db/migrate/20200000000000_add_names_to_users.rb
class AddNamesToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string
  end
end

rails db:migrateを実行する

% rails  db:migrate

パターン2 : ターミナルにまとめて記述する方法

rail g migration ファイル名 追加するカラム名:型を実行

# 追加するカラムの詳細情報までまとめ記述する
% rails g migration AddNameToUsers first_name:string last_name:string

生成されるファイルの中身(ファイルの中身が記述された状態でマイグレーションファイルが生成)

db/migrate/20200000000000_add_names_to_users.rb
class AddNamesToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string
  end
end

rails db:migrateを実行する

% rails  db:migrate

references型カラムの追加/削除 実行手順

状況:Ordersテーブルに外部キーとしてaddress_idを追加する

rails g migration ファイル名を実行する

# address_idカラムをOrdersテーブルに追加する場合
% rails g migration AddIdToOrders

②生成されたファイルに記述する

db/migrate/20201014000000_add_id_to_orders.rb
class AddIdToOrders < ActiveRecord::Migration[6.0]
  def change
    # 追加
    add_reference :orders, :address, foreign_key: true
    # 削除
    remove_reference :orders, :address, foreign_key: true
  end
end

追加のポイント
add_referenceであること
foreign_key: trueを記述すること(必要な場合のみ)
削除のポイント
remove_referenceであること

rails db:migrateを実行する

% rails  db:migrate

解説は以上です!!

想像より長くなってしまいましたがこの記事がお役に立てると幸いです。
慣れると簡単なのでぜひ習得してスムーズに開発が進められるようにしましょう!
それでは、最後までご覧いただきありがとうございました。

参考

https://qiita.com/kurawo___D/items/e3694f7a870a1cc4738e
https://freesworder.net/rails-column-add-remove/
https://gist.github.com/seak0503/84bfa6b37a0a6961c334

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

Git 簡単に変更前の状態に戻す方法(コミット前)

コミット前の変更点をターミナルを使わずに変更する

5a8e0bb5a8678f4f589fba16c996ee70.png

他のブランチに移動するだけ!

この方法が最も簡単に変更前に戻す方法なのですが、他の事例に当てはまる場合は下記の方の記事を参考にするといいですよ!

https://qiita.com/tani-shi/items/3419600447292abf6c79
@tani-shi

現場からは以上です!

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