Laravel・PHP入門

未経験エンジニアがRuby on Railsを学習していましたがPHPerになったメモ

【Laravel】多対多のリレーションまとめ

参考:
Eloquent:リレーション 5.5 Laravel


今回は、例えばブログのカテゴリーのような、お互いが複数関わる
Laravelの多対多の関係について言及します。
個人的にはかなりハマりましたが言及された記事が少なかった。

Laravelの多対多関係について

ブログのカテゴリー、学校の学生と科目など、ブログが多くのカテゴリーを持ち、
カテゴリーも多くのブログを持つ(この記事もLaravelや多対多、Eloquentなど多くのカテゴリを持ちます)
ような関係の事を示しています。
今回はあるエントリーとカテゴリーを例にして言及することとします。

公式ドキュメントにも記載がありますが、1対1や、1対多より少し複雑です。
2つをつなぐ中間テーブルが必要になるからです。(モデルは必要ありません)
早速実装してみます!

中間テーブルやModelを作ってみる

今回の場合、categories、entries、そしてcategory_entryテーブルを使用します。
命名規則により、多対多関係になるテーブルの単数系をアルファベット順に並べます。
(無視してもできるそうですが、かなり面倒らしいので避けることをお薦めします。)

DBの構成

  1. entriesテーブル
  • id
  • title
  • body
  • created_at
  • updated_at
  1. categoriesテーブル
  • id
  • name
  • created_at
  • updated_at
  1. category_entryテーブル(中間テーブル)
  • id
  • category_id
  • entry_id

中間テーブルについては、1つの関係につき1つのデータになりますので
このブログの記事で例をあげると、
f:id:fresh_engineer:20171209184159p:plain
この記事のidが9の場合、下記のようになります。(多いので4つに省略しています)
f:id:fresh_engineer:20171209185737p:plain:h100

つまり、1つの記事に対して4つのカテゴリが対応している場合、
4つのデータが必要になります。

DBにテーブルが登録できれば、次はmodelを作成していきます。

Modelの生成

中間テーブルについてはModelを必要としませんので、
Entryモデル、Categoryモデルを生成します。
まずはリレーション生成の部分のみ。

App\Models\Category.php

<?php

class Category extends Model
{
  public function entries()
  {
    return $this->belongsToMany('App\Models\Entry::class');
  }
}

App\Models\Entry.php

<?php
class Entry extends Model
{
  protected $fillable =
  [
    'title',
    'body',
  ];

  public function categories()
  {
    return $this->belongsToMany('App\Models\Category::class');
  }
}

今回は、多対多のため、belongsToManyメソッドを呼び出します。
準備はこれでOKです。

実践で、MVCモデルを利用した上で、データを入力する部分まで実装します。
カテゴリーは既にDBへ登録済みの前提で、
記事を投稿する時にカテゴリーの選択ができるような形で実装します。
(Viewはtwigを使用してますのでよしなに変更ください)

Controller/Model/View実装

View実装
<div class="container">
<form action="/entry/complete" method="post">

<div class="form-group">
    <label for="f-title">Title</label>
    <textarea name="title" class="form-control" id="f-other"></textarea>
</div>

<div class="form-group">
    <label for="f-category_ids">Category</label>
    <select name = "language_ids[]" class = "form-control" id = "f-language_ids" multiple>
    {% for id, name in all_categories_list %}
    <option value = "{{ id }}" >{{ name }}</option>
    {% endfor %}
    </select>
</div>

<div class="form-group">
    <label for="f-body">body</label>
    <textarea name="body" class="form-control" id="f-body"></textarea>
</div>

<div class="form-group">
    <input type="submit" value="send" class="btn" id="btn">
</div>

</form>
</div>
Controller実装

EntryControllerで入力フォームを表示する際、
既に登録済みのカテゴリーも表示します。
そして、Entryデータを保存する際に、
Entryデータと対応したカテゴリーのデータを保存するメソッドを呼び出します。

App/Controllers/EntryContoroller

<?php
public function input(Request $request) //入力のViewを表示(その時にカテゴリーの配列も渡す)
{
         return view('entry/input',
         [
                 'all_categories_list' => $this->getAllCategoriesList()
         ]);
         }
}

public function complete(Request $request)
{
         $inputs = $request->all(); 
         $category_ids = $inputs['category_ids'];
         unset($inputs['category_ids']); //fillableしているのでEntryテーブルに入らないカラムは除く

         $id = $this->entry_model->saveAndGetId($inputs);
         $this->entry_model->saveCategoryIdsFromEntryId($id, $language_ids);
         return view('entry/complete');
}
Model実装

App/Models/Entry.php

<?php
namespace App\Models;

use App\Models\Language;
use Illuminate\Database\Eloquent\Model;

class Entry extends Model
{
  protected function $fillable
       [
            'title',
            'body',
  ];

  public function saveAndGetId($inputs)
  {
          return $this->create($inputs)->id;
               //entryデータを生成した上で、中間テーブルに必要なIDを取り出す
  }
       public function saveLanguageIdsFromEntryId(int $id, array $language_ids){
            $entry = $this->find($id); //idからEntryを取り出して、
            return $entry->languages()->attach($language_ids);
            //ここで中間テーブルに保存!
        }


App/Models/Category.php

<?php
namespace App\Models;

use App\Models;
use Illuminate\Support\Collection;

class Category extends Model
{
    public function getAllCategoriesList()
    {
        return $this->pluck('name', 'id'); //すべてのカテゴリーを配列にして取り出す
    }

※関係の定義の部分は既出なので省略。


route/web.php

<?php
    Route::post('/entry/conplete' => 'EntryController@complete');

以上

【Laravel】ViewにMeta情報を渡す共通処理を実装する

話は飛躍しますが復習メモ。

DRY(Dont Repeat Yourself)の法則に則り、
共通処理や共通の変数については、何度も呼び出すのではなく
1度処理できるようにすると良い。

例えば、今回は全てのViewにHTMLへ埋め込む
Meta情報(titleやページ情報)を、共通処理にしたいとします。
Viewを呼び出すにあたり、共通経路はいくつかありますが
(親クラスやRouteなど)

auth認証など、毎回呼び出すものはMiddlewareが確実であり簡潔なので
全てのViewにデータを渡したい今回は
MiddlewareとView::shareメソッドを採用します。

※今回はDBにMeta情報全て入力済み、
MetaModelとmeta table使用の前提で進めていきます。

Middlewareを実際に作って、通し、実装する

①Middlewareを作る

php artisan make:Middleware GetMetaData //キャメルケース

緑色でsuccessと出ると、app/Http/Middlewareの下にGetMetaData.php
作成されているはずです。

②Middlewareを通す

Middlewareを使用するために、Kernel.phpで定義します。

今回は全てのViewに渡すとき、
つまりほとんどのHTTPリクエストに対応したいため
限定しない$middlewareプロパティへ追加します。

Kernel.php

protected $middleware = [
  ...
   \App\Http\Middleware\GetMetaData::class //追加
];

これで、全てのHTTPリクエスト時にGetMetaDataという
Middlewareが実行されるようになりました。

③Middlewareを実装する

それでは早速GetMetaDataの内容を実装していきます。
App/Http/Middleware/GetMetaData.php

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\View; //今回はView::shareを使用するので
use App\Models\Meta as MetaModel;

class GetMetaData 
{

public function __construct()
{
  $this->meta_model = new MetaModel; //MetaModelをインスタンス化
}
public function handle(Request $request, Closure $next)
{
View::share(['meta' => $this->meta_model->getMetaData($request)])
//全てのViewに、metaという名前の配列を渡す
ValueはMetaModelのgetMetaDataメソッドを呼び出す
return $next($request);
}

Meta.php

public function getMetaData($request)
{
  $meta_id = $request[meta_id];
  return $this->where('meta_id', $meta_id); 
}

これで、Viewを表示するたびに
MetaテーブルからMeta情報を抽出する一連の流れが実装できました。


以上です。

参考:
ミドルウェア 5.5 Laravel

【PHP】twigまとめ(条件式、変数)

業務でtwig文を使っていたのですが
情報がバラバラだったのでまとめ。

目次

1.全体

継承

{% extends 'ファイルパス' %} 

・別ファイルから継承する(複数はNG)
・親ブロックを子ブロックが上書きする
・{% block ブロック名%}〜{% endblock %}

挿入

{% include 'ファイルパス'%}
{% include 'aa/aa' with[ 'aa' : 'aa'] %} //引数も取れます

コメント文

{# ここにコメントを書く#}

CSRF対策

{{ csrf_field() }}

HTML文のエスケープ

{{ html文 | raw }} 

その他

{{ 変数 | length }} //文字数
{{ dump() }} //PHPのdumpと一緒

2.変数

書き方

{{ 変数名 }}

※ただし条件式の中では{{}}は不要。(例:{% if post="hello" %})

定義方法

①同じTwig内で設定する

{% set 変数名='value' %}

・配列の場合は{% set array = [ A, B ] %}
連想配列は{% set array =  [ key : value ] %}

②Contorollerなどから渡す

変数:{{ 変数名 }}

配列:{{ 変数名.キー名 }} ※連想配列も可

▼例 (部分抜粋)

app/Controllers/PostController.php

$url = 'URLです';
$post = $this->post_model->getPostArray();
// 'id' => '1', 'title' => 'タイトル'
return view('post/show', [
'url' =>$url, //変数 
'posr' =>$post ]; //配列

 resouse/view/post/show.twig

<p>変数は「{{ url }}」です。</p>
<p>配列は idが{{ post.id }}で、
titleが{{ post.title }}です。</p>

出力結果

変数は「URLです」です。
配列は idが1で、titleがタイトルです。

その他

バリデーションエラーなど定型変数の時の書き方

・input_old('タグの名前') // セッションなどで確認フォーム利用時

・errors.first('タグの名前') //バリデーションエラー時

3.条件式

if文

{% if 条件式 %}
{% endif %}

・通常のif文が上記の書き方で使える
・条件式内で変数を定義した場合、条件文外では使用不能
・条件文内では、変数に{{}}はつけない
・else文、elseif文、複数条件の場合はandやorも使用可能

{% if 条件式A and 条件式B %}
{% elseif 条件式 %}
{% else %}
{% endif %}

for文

{% for i = 1 1..100 %}
{% endfor %}

・iは任意です
連想配列の場合は{% for key, value in 配列名 %}

foreach文( ループ, for in で代用 )

{% for hoge in array %}
{% endfor %}

 ・arrayに任意の配列、hogeも任意の名前です

三項演算子

{{ 条件文 ? 処理A : 処理B }}

・条件文が正の時にA、誤の時B

例文

①テンプレート・変数を使用したページ

{% extends 'layout/user_default'%}
{% block content %}
{% set title='hello' %}
<div class="sample">
  <h1>{{ title }}</h1>
</div>
{% endblock %}

 

②Emailのフォーム(一部抜粋)

<div class="form-group">
  <label for="f-email">Email address</label>
  <input type="email" name="email" class="form-control" id="f-mail"
  value="{{input_old('email')}}" placeholder="entry@leverages.jp">
  {% if errors.first('email')|length > 0 %}
   <span class="text-danger">{{errors.first('email')}}</span>
       {% endif %}
</div>

 

公式リンク

Documentation - Twig - The flexible, fast, and secure PHP template engine

 

以上

【PHP/Laravel】エンジニア歴1ヶ月の入門まとめ

Webエンジニアという職種について約1ヶ月がたちました。
本記事では1ヶ月たった自分が1週目の自分に教えられれば
より早い学習ができたのではないかと思う内容を復習がてら記載します。

この記事は正しいことが目的ではなく、
初心者が他の入門者により早く、考えてwebアプリを動かすための一助を
提供することを目的としています。
学術的、より正しく学びたい方は本や学校をご利用ください。

念のためおすすめの読者は下記です。

★ main: 独学でググってコピペして動かせる人
      ドットインストールや参考書などで何か作ったことがある人

▼ min:  PHPもしくはRubyの環境構築はググればできる人

 

目次 

 

MVCの使い方と基本的なwebアプリケーションの流れ

エンジニアになって最もご指導いただいたのがMVCの使い分け。Laravel5.5環境。

入門者:MVCそれぞれの役割を知っている。Contorollerにメソッド全部書く。太る。
初心者:MとCをDBに関連するか否かで書き分ける。←私は今ここ
それ以上:レベルの高いパターンなど考えるらしい(ごめんなさい知らない)
入門者についてはドットインストールや参考書が多くあるので初心者版を記載します。

▼ 簡易版はよくあるので、ちょっと詳しく図解。

f:id:fresh_engineer:20171129022519p:plain

大事なのは、find($id)をModelが実施していることです。
DBからそのidを持ったPostデータを取って来るというDBに関わる作業
Controllerから切り離しています。

リクエストはブラウザのURLの部分だと考えてください。
post/show/26というリクエストが送られます。
route/web.phpの同リクエスト部分にヒットします。

>> route/web.php

Route::get('/post/show/{id}', 'PostController@show');

ここで、Routeはapp/Http/Controllers/PostControllerのshowメソッドへ
アクセスします。そして、そのshowメソッドが
app/Model/PostModelのgetPostメソッドを呼び出します。


関係する部分のみ抜粋してソースを書きます。

>> app/Http/Controllers/PostController.php

use App\Models\Post as PostModel ;

class PostController extends BaseController{

  private $post_model;

  public function __construct(PostModel $post_model)
  {
    $this->post_model = $post_model;
  }

  public function show($id)
  {
    $post = $this->post_model->getPost($id);
     return view('post/show', ['post' => $post]);
  } 

}

 

 >> app/Models/Post.php

public function getPost($id){
  return $this->find($id);


はじめ、え、contorollerの中にpost_model??は???って思いました。

ですが、一度納得すると、こちらの方がMVCってこういうことか!と
わかりやすく感じるようになりました。

DBに関するものは、Modelを使用すると記載しましたが
具体化すると、

ー ー ー ー ー ー 前提と準備 ー ー ー ー ー ー ー

Postというtableに入っているものはPostModelで操作します
・Contorollerからリクエストに応じてPostのデータを取得するため、
 PostModelの然るべきアクションを呼び出します。
・Modelのアクションを呼び出すため、
 PostModelのクラスをPostController内でインスタンスします。※

ー ー ー ー ー ー 実践 ー ー ー ー ー ー ー 

・$this->post_model->getPost($id);
 このPostControllerクラス($this)から、post_modelというインスタンス
 getPostというメソッドを呼び出します。(引数としてidを渡します。)
・PostModelのgetPostメソッドが、
 $idに入った26というidを用いてDBのposts tableから id=26の
 postデータを丸ごと配列として取り出します。
 今回はその取り出した配列をそのままreturnしているので、
 呼び出した$postに代入されます。

(=は右辺の結果を左辺に代入する演算子)

・代入された$postを用いて、post/showというviewをresponseします。
・ユーザーはブラウザで、resouse/view/post/show.htmlが表示されます。

※ オブジェクト志向の話が入ると長くなるので下の2記事がおすすめです。

PHPオブジェクト指向入門(前半) - Qiita

プログラミング勉強中の人にオブジェクト指向とは何なのかを何となく伝えたい話 - かまずにまるのみ。

 

図解ではわかりやすくするために分けましたが、
一時的な変数に入れているだけなので、こんな風に省略もできます。 

public function show($id){
return view('post/show' ,
['post' => $this->post_model->getPost($id)]); 
 }

 これは後のリーダブルコードで詳しく書きます。

 

長々と書きましたが、とりあえずPost-tableからデータ入れたり出したり更新したり削除(いわゆるCRUD)したいときは、Controllerに直接書かずにModelに書こうね!!
ControllerからModelを呼び出せるようにした方がMVCフレームワークだよね!!

ということが言いたかったわけです。
演算子の意味がわからない人はこれを読みましょう。

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)

 

 

 

名前空間・クラス・メソッド・コントローラ・モデルの書き方

最低限のwebアプリケーションを作るのに必要ですが
情報がバラバラでわかりづらかったこの辺りをまとめます。

まずはソースコードと一緒にざっくり説明入れます。

<?php
namespace
App\Http\Controllers\Admin;
//名前空間。このファイルがどこにあるか示す。
書き方はディレクトリ\バックスラッシュ(macならoption+¥);

use App\Http\Controllers\BaseController;
use
Illuminate\Http\Request;
use App\Models\Post as PostModel ;
//別ファイルのメソッドなど何かを使用するとき必ず記載する。
ex.ModelやValidationなど。asは呼び方。


class PostController extends BaseController{
//PostControllerという名前のクラスです、
BaseControllerというControllerを継承してます
(継承:private以外のメソッドが使えますが、
継承を使わない間は決まり文句として記載してください)
★★早速先ほどuseに記載したBaseControllerが書いてますね!


private
$post_model;
//privateはこのPostControllerクラスからしか呼び出せません。

public function __construct(PostModel $post_model)

{

  $this->post_model = $post_model;
  //このPostControllerクラスのpost_modelインスタンス
  PostModelの$post_modelというオブジェクトを代入する。日本語怪しい。

}

//publicは他のクラスなどどこからでも参照できるメソッド。
__constructは本Controllerクラスが呼び出されるたびに必ず実施されます。
Controllerの、Routeから呼び出すメソッドは基本的にpublicですね。
同クラス内でしか呼び出さないメソッドはprivateにしましょう。


public function show($id)

//メソッドの作り方:
アクセス修飾子 + function + メソッド名 (引数)

{
  $post = $this->post_model->getPost($id);
   // $ 変数名
     = (代入演算子、右辺を左辺に代入する)
     -> 左辺から右辺を呼び出す
     ()メソッド書くときは引数なくても()書く
     ; この行終わりの印

   return view('post/show', ['post' => $post]);

   // return 返り値 呼び出した奴にそのまま返り値が届きます。
     この場合はviewというresponseが返ります。
    view('接続先のビューへのパス', [配列])
    postという名前で$postという配列が入った変数が返ります。

}

 

リーダブルコード(命名規則/コメント/リーダブルコード)

命名規則は命です

ControllerやModelを作ろうとして、どんな名前にしようか分からなかった経験はありませんか?
今回は設定より規約という概念に則り記載します。詳しくは下記

簡単にいうとpostsテーブルにひもづくのは
PostモデルだとLaravelは知っています。
Modelでこのテーブルからデータを取ってくる、
と定義しなくてもid=26のデータですよと勝手にpostsテーブルを覗いてくれます。

具体的に見ると下記。

Model:Post.php、MsCountry.php 単数形・キャメルケース。

Table:posts、ms_countries 複数形・小文字・スネークケース。

Controller:PostController.php (複数形が主流との噂ですが単数も可)キャメルケース。

Class:BaseController  キャメルケース。

Method:publlic function saveAndGetId(ココ) はじめが小文字のキャメルケース。

変数:$search_word 小文字のスネークケース。

 とにかくコードやコメントを読む必要のないような
ものすごくわかりやすい名前をつけましょう。必要ならば名前が冗長でも構いません。
PGがコードを書くのと、それを読むのとでは後者の方が回数が多いので
保守性のあるコードを書きましょう!!!(口すっぱくご指導いただきました)

 

(2)コメントをかこう:

初心者のうちは毎行書いても良いくらいだと言われました。
人が読むソースコードを書くため、必ずコメントを書きましょう。
特に、メソッドの前には必ず記載します。書き方の一例を記載します。

/**                       // はじまり
* 特定単語によりPostデータを検索し結果を返す //1行目:メソッドの説明文
*                       //2行目:空行
* @params varchar $search_word         //3行目:@params 種類 引数
* @return array $seach_result          //4行目:@return 種類 返り値
* @access public               //5行目:@access アクセス権限
*/                       // おわり
public function create

{ 〜

 参考:

phpDocumentorの書き方 - Qiita

【PhpDoc】コメントの書き方のまとめ – 小俣泰明(タイメイ)blog

 

⑶リーダブルコード

まずこれを読みましょう。

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

 

 そして書き方の規約を学び、合わせて書きましょう。

PSR-2 コーディングガイド(日本語)|北海道札幌市のシステム開発会社インフィニットループ

 

命名規則を守る
・コーディングガイドに則る
・(DRY)何度も書く定数・変数は定義する。
  − 保守の時に変更が生じた場合に極力書き直すコストが減るように!
・何度も書くメソッドは切り分けで親コントローラーに書いて継承
・メソッドは一機能が原則、複数になる場合はprivateで切り分ける
・インデントを揃える
・空白も揃える (私はよくif文の空白を間違えます)
・一時変数を消す

 

コードは自分で書くものではなく、人が読むもの

保守性の高いコードを書きましょう(数回目)

 

とりあえず、これで初心者から入門者に近づけるといいな

リーダブルコードとか書いてる割に記事が冗長になってしまったので
今度Qiitaで書き直すことにします。

【初心者用】MySQLの基本コマンド@Userやtable作成まとめ

MySQLの基礎コマンドよく見失うのでメモ。

 

【やりたいこと】
rootで初回ログイン/パスワード設定
ユーザー作成(+権限付与)
database作成
table作成など
※前提:MySQLはダウンロード済み

①rootで初回ログイン/パスワード設定

mysql -u root

はじめはパスワードがないので、rootでログインします。
コマンドがmysql>になれば成功です。

次にパスワードの設定をします。

set password for 'root'@'localhost' = password('任意のパスワード');

 こちらで、ログアウトしてから再度ログインができれば成功です。

exit

mysql -u root -p #パスワードを使用してログイン

 パスワードを聞かれますので、先ほど設定したrootのパスワードで
ログインができれば成功です。

 

②ユーザー作成・ログイン〜権限付与

まずはrootでログイン。

mysql -u root -p

ログインができれば早速ユーザを作りましょう。

create user dbuser identified by '任意のパスワード';
#dbuser/passwordは任意のユーザー名・パスワードへ変更してください。

mysqlのコマンドは必ず最後に「 ; 」が必要になります。
Query, OK と出てこれば作成完了です。
一度ログアウトして、早速ログイン。 

exit;

mysql -u dbuser -p #dbuserというユーザ名と、パスワードを利用します

mysql>になっていればログイン成功です。
ですが、このユーザが権限を持っていないので、権限を付与します。
詳しい権限の種類やレベルは記載しませんが、
今回色々設定したいので全ての権限を付与します。

grant all on *.* to dbuser;

グローバルレベルのall権限が付与されました!

 

③database作成 

create database database_name; #database_nameは任意のdatabase名

ログイン後、databaseを作ります。
できたか確認します。

show databases;

できたか見てみます。これでdatabase一覧が見れます。

use database_name; #database_nameというデータベースを使う

そして、database_nameというデータベースに移動します。

 

④table作成

tableを作ります。
安定のcreate。

create table table_names(id int, name varchar(20));

tabel_namesは任意のテーブル名を設定ください。
カラムなどにいくつか規則があるのでご注意ください。
ここで、カラムと挿入するデータ型を指定します。

id = カラムの名前(任意) / int = 整数

のため、このときはidというカラムに整数のデータ型を入れる。
ex. id = 1 など

ということになります。あとはデータ型や特徴さえ掴めば
テーブルが作成できますね。

初心者がよく使うのは
int:整数 / varchar:文字列(255字まで) 

text:長い文字列(6万字くらいまで) / timestamp:日時 

などですが、詳しくは下記サイトをご参照ください。

MySQLのデータ型 - MySQLの使い方

show tables; 

 今どんなテーブルがあるのか見られます。
そして、先ほどのテーブルへ移動します。

use tables(任意のテーブル名);

テーブル構造を見たいときは

desc tables(任意のテーブル名);

f:id:fresh_engineer:20171108014448p:plain

こちらで見られます。

 

また、insertデータを入れた後は、

select * from tables;

 でも見れますし、整形して見たい場合は

select * from tables \G;

最後\Gをつけてあげると下記のような形で格納データが確認できます。
Macではoption+¥マークでバックスラッシュが入力できます。

f:id:fresh_engineer:20171108014635p:plain

以上です。

Ruby で  CSVファイル を処理するメモ

RubyでGoogle Spreadsheetを読み書きするメモ - Ruby on Rails 入門

 

上記記事の時、google spreadsheetからcsvファイルをダウンロードして
そのあとデータをjsonに整形することがあったのでメモ。

忘れないうちに自分用にメモさせていただきます

 

CSVからデータを取り出すにはRailsのtableとかforeachというメソッドが良いらしい。
tableはテーブル向けのインスタンスを返してくれるそうですが、
今回データを分けてHash化したかったので
foreachで1つ1つ取ってくる。

 

まず標準添付ライブラリのcsvjsonは使います

require 'csv'
require 'json'

 データを入れる用の配列を用意します

all = Array.new

hogehoges =

 

そして待ち焦がれたforeachの登場。
同フォルダ内のcsvファイルを読むよ、ヘッダーあるよ、dateに毎回入れるよ

CSV.foreach('table.csv',headers: true) do |data|
hogehoges.push data[1]
hogehoges.push data[2]
hogehoges.push data[3]
end

という感じ。
重複して欲しくなかったり分けたかったりしたので
compactやuniqを使用して最終的には下記になりました。
hashに全部入れて、jsonで返して終わりです。

#cording = UTF-8
require 'csv'
require 'json'
all = Array.new
hogehoges =

CSV.foreach('table.csv',headers: true) do |data|
hogehoges.push data[1]
hogehoges.push data[2]
hogehoges.push data[3]
end

newhogehoges =hogehoges.compact.uniq
x = 1
y = 0

newhogehoges.each do |neweq|
h = Hash["id", x, "name", neweq]
all.push(h)
x += 1
y += 1
end

puts all.to_json

 だいぶメモみたいになってしまったので時間あるときにでも
もう少し綺麗に書きます・・・多分

Ruby on RailsでCarrierWaveを使って画像投稿機能を実装する

【やりたいこと】

既存のwebアプリ(タスク管理アプリ)で画像を投稿できるようにしたい
( 既存で一通りのモデルとかビューはすでに作成済みの想定 )

【イメージ】

あまり湧いていないのですがcarrierwaveのgemを使用すると良いらしい。
既存でtitleの投稿機能は実装していたのでそれらに追加する形で実装します。

・gemをinstallする
・dbで画像を受け取れるようにする
・dbへ渡せるようモデルに追記する
・モデルへ渡すためのコントローラとビューを追加する
・dbから受け取った画像をビューで表示する画面を作る

 

【やってみる】

いつも通りvi GemfileでGemfileに追記、bundle installします。

gem 'carrierwave' 

bundle install 

これでcarrierwaveをインストール。
公式Githubに色々記載があります

rails g migraation AddpictureTotasks picture:string
#rails g migration Addカラム名(任意)Toテーブル名 カラム名:型

 rails db:migrate

これでdbのtaskテーブルに画像が追加できるようになりました。 

mysqlで叩いてみてもちゃんとpictureカラムが増えてる 

# mysqlにログインした後 

select * from tasks \G;

f:id:fresh_engineer:20170829001855p:plain

 こんな感じ。(投稿前はNILLになってるはず)

 

dbが用意できたのでdbへ渡すモデルを編集する

class Task < ActiveRecord::Base
mount_uploader :picture, PictureUploader
end

公式のGithubにもあった通りmount_uploaderというメソッドを使う。

 

画像をinputするためのviewを作成する。

<div class="field">
<%= f.label :picture %>
<%= f.file_field :picture %>
</div>

そのviewで受け取った画像をモデルへ渡すためにコントローラのparamにも
pictureを追加する

def task_params
params[:task].permit(:title, :picture)
end

これでcontrollerがpictureも渡してくれるようになりました

最後に受け取った画像を表示できるようviewを編集して終わり

<%= image_tag(@task.picture_url) if @task.picture.present? %>

以上で
画像をアップロード(view)→コントローラが受け取る→モデルが受け取る→dbへ渡す
リクエスト→dbから画像データを取ってくる→viewで表示する 

の完了です。