pyenv にパスを通す

pythonがなんかおかしいと思ったらパスが通ってなかったので、パスを通しました

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile

コードをターミナルに叩いたら、無事に通りまりました!

$ which python
/Users/Hiyashikyuri/.pyenv/shims/python

参考にした記事
pyenvを使ってMacにPythonの環境を構築する

Flaskで多対多のJSON APIを作る

前回は1対多の関係でしたけど、今回は多対多のデータベースを設計しました〜

Flaskで1対多のJSON APIを作る

完成物

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask.json import jsonify

app = Flask(__name__)

# sqlalchemyの設定
app.config['SECRET_KEY'] = 'secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:@localhost/many-to-many'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# 中間テーブル
user_hobbies = db.Table(
    'user_hobbies',
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('hobby_id', db.Integer, db.ForeignKey('hobby.id'))
)

"""
python コンソールで以下のコードを実行して、UserとHobby、中間テーブルのデータを作成

user1 = User(name='Bob')
user2 = User(name='John')
user3 = User(name='Mike')
db.session.add(user1)
db.session.add(user2)
db.session.add(user3)

h1 = Hobby(name='スノボ')
h2 = Hobby(name='野球')
h3 = Hobby(name='サッカー')
db.session.add(h1)
db.session.add(h2)
db.session.add(h3)

user1.subscriptions.append(h1)
user1.subscriptions.append(h2)
user1.subscriptions.append(h3)
user2.subscriptions.append(h1)
user2.subscriptions.append(h3)
user3.subscriptions.append(h3)

db.session.commit()

"""


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    subscriptions = db.relationship('Hobby', secondary=user_hobbies, backref=db.backref('subscribers', lazy='dynamic'))

    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'hobbies': [Hobby.to_dict(c) for c in self.subscriptions]
        }


class Hobby(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))

    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
        }


@app.route('/')
def index():
    return jsonify({"data": [User.to_dict(u) for u in User.query.all()]})


@app.route('/hobbies')
def hobbies():
    return jsonify({"data": [Hobby.to_dict(h) for h in Hobby.query.all()]})


if __name__ == '__main__':
    app.run()

データを適当にいれた後は
こんな感じでjsonが返ってきます!

参考にした動画

Flaskで1対多のJSON APIを作る

日本語ベースのflask関連の記事があんまりないのでまとめてみました〜

Flaskで多対多のJSON APIを作る

pythonはコード量も少なくてシンプルに書けるのでとても楽しいです!

完成物はこちら

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask.json import jsonify

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:@localhost/one-to-many'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

"""
    データベースの作成手順は、
    1.まず python コンソールで
    from app import db でインポートして
    2.one-to-manyのデータベースを作成する(直接mySqlで作るか、seqel proなどを使用すると楽です )
    3.作成し終わったら、再びpython コンソールで
    db.create_all() を叩いて完成!
"""


# class にクエリをまとめるととても綺麗になるのでオススメ
class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    hobbies = db.relationship('Hobby', backref='person', lazy='dynamic')
    """
    hobbiesではカラムが追加しているのではなく、Hobbyに対して関連性を設定
    to_dict()メソッドはオブジェクトをjsonで返すためのメソッド
    """

    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            # Personに紐づいているHobbyを全部出力
            'hobby': [Hobby.to_dict(hobby) for hobby in self.hobbies]
        }


class Hobby(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'))

    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
        }


@app.route('/')
def index():
    return jsonify({"data": [Person.to_dict(person) for person in Person.query.all()]})


if __name__ == '__main__':
    app.run()

特別なことはしていないので、もしわからないところがあれば比較的簡単に情報は見つかるのではないかと思います

データを適当にいれた後
実際に動かしてみるとこんな感じでデータが返ってきます!

参考にした動画

matplotlib 画像が表示されない

matplotlibを使って画像を表示したかったのですが、なぜかできずにちょっと手間取ってしまいました

該当コード

import matplotlib
matplotlib.use('Agg')

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df = pd.read_csv('./pima-data.csv')

def plot_corr(df, size=11):
    corr = df.corr() 
    fig, ax = plt.subplots(figsize=(size, size))
    ax.matshow(corr) 
    plt.xticks(range(len(corr.columns)), corr.columns)  
    plt.yticks(range(len(corr.columns)), corr.columns)  
    plt.savefig('correlation.png') # グラフを保存する
    plt.show()


plot_corr(df)
# もともと
matplotlib.use('Agg')

# こっちに変更↓
matplotlib.use('TkAgg')

こうすることで問題は解決できました
問題は ‘Agg’がGUIバックエンド対応していないことのようです
参考にした記事にもうちょこっと載っているので、詳しく知りたい方はそちらで確認してください

参考にした記事

matplotlib plot window won’t appear

matplotlib をimport するとエラーが出る

マシンラーニングを勉強してるときにmatplotlibをimportしたらなんかエラーが出てきました

該当コード

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df = pd.read_csv('./pima-data.csv')
print(df.shape)

エラー内容

 File "/.pyenv/versions/3.5.1/lib/python3.5/site-packages/matplotlib/pyplot.py", line 115, in <module>
    _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()

以下のように編集することでエラーが解決できました〜

import matplotlib  # 追加
matplotlib.use('Agg') # 追加
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df = pd.read_csv('./pima-data.csv')
print(df.shape)

参考にした記事
How to resolve import matplotlib.pyplot as plt error?
Using matplotlib without Tkinter #7115

rails APIでページネーションを実装する

データ量が多くなって来たのでページネーションを入れました〜

railsでページネーションといえば ‘kaminari’がデファクトスタンダード的な存在だと思うので
とりあえず kaminari を使用しました

[toc]

gemの追加

gem 'kaminari', '1.0.1'
#gem を追加した bundle installします
$ bundle install

コントローラーに突っ込む

# (params[:page]) -> URLからpage番号を取得
#(params[:page] ||= 1) -> page番号が指定されていなかったらデフォルトで1で実行
# per(5) -> 1ページあたり5件表示
def index
    @customers = Customer.page(params[:page] ||= 1).per(5).order('created_at DESC')
    render 'index', :formats => [:json], :handlers => [:jbuilder]
 end

動いているか確認

http://localhost:3000/customers?page=1

上記リンクにアクセスすると

こんな感じで表示されました!

参考にした記事

Creating Rails 5 API only application following JSON:API specification
【Rails4】kaminariをAPIで利用する

rspec undefined local variable or method `json’

rails のアプリをテストするためにrspecを使っていたらタイトルのエラーが出てきました

 undefined local variable or method `json' for #<RSpec::ExampleGroups::CustomersController::GETIndex:0x007fa926cdc9a0>
       Did you mean?  JSON

こちらがテストコードです

require 'rails_helper'

describe CustomersController, type: :request do
  describe 'GET #index' do
    before do
      @customers = create_list(:customer, 3)
      get '/customers', fotmat: json
    end

    it 'returns 200 status' do
      expect(response).to be_success
      expect(response.status).to eq(200)
    end

    it 'contains body' do
      json = JSON.parse(response.body)
      expect(json['data'][0]['id']).to eq(@customers[0].id)
      expect(json['data'][1]['id']).to eq(@customers[1].id)
      expect(json['data'][2]['id']).to eq(@customers[2].id)
    end
  end
end

最初は it’ contains body’ ,,, のところをコメントしたりしてたんですけど、
エラーログがいつまでたっても変わらないので json に該当するようなところを探してみたら

 before do
      @customers = create_list(:customer, 3)
      get '/customers', format: json  # コロンが入っていないのと、 formatがタイポ
  end

ものすごく初歩的なミスをしていました;;;
あと、今回はjsonを出力するAPIだったので、 formatごと決して無事グリーン来ましたー!

CustomersController
  GET #index
    returns 200 status
    contains body

Finished in 0.26729 seconds (files took 5.16 seconds to load)
2 examples, 0 failures

Angular4 mapメソッドを使うとエラーが出る

Angularでmapメソッドを使おうとしたらエラーが出てきました

Property 'map' does not exist on type 'Observable<Response>'

こちらをインポートすることで解決できましたー

import 'rxjs/Rx';

Angular 2 beta.17: Property ‘map’ does not exist on type ‘Observable

csvファイルを読み込もうとしたらエラーがでた

csvを読み込んでデータベースに登録しようとした

Errno::ENOENT (No such file or directory @ rb_sysopen

という初めて見るエラーがでてきました

こちらが該当箇所

CSV.foreach("posts.csv") do |row|
  Post.create(
      id: row[0],
      title: row[1],
      brief: row[2],
      body: row[3],
      created_at: row[4],
      updated_at: row[5]
  )
end

パスを指定してやることで解決しました〜

CSV.foreach(Rails.root + "db/posts.csv") do |row|
  Post.create(
      id: row[0],
      title: row[1],
      brief: row[2],
      body: row[3],
      created_at: row[4],
      updated_at: row[5]
  )

end

参考にした記事

Errno::ENOENT (No such file or directory @ rb_sysopen

activeadminにckeditorを入れる

今働いているところはベンチャー企業なので、時間もお金もリソースも全然ない
なので、railsなどを使用することで開発スピードを早めたり無駄がないように奮闘しています

現状だと、activeadminのフォームにそのままHTMLのタグを手で入れながらブログなどを書いてるわけですが、
とてもやりづらいし、エンジニアでない人だと一から教えないといけないので効率よくできないものかと考え導入を決めました〜

[toc]

Gemfile

gem 'activeadmin', github: 'activeadmin'
gem 'devise'
gem 'ckeditor'#, github: 'galetahub/ckeditor'

インストールとか

$ bundle install

$ rails generate active_admin:install

$ rake db:migrate 

configの設定

# To load a javascript file:
config.register_javascript 'ckeditor/init.js'

scaffoldingとactiveadminの設定など

$ rails g scaffold project name:title description:text

$ rake db:migrate

$ rails generate active_admin:resource project

次にproject.rbを修正

ActiveAdmin.register Project do

permit_params :title, :description

form do |f|
  f.inputs do
    f.input :title
    f.input :description, :as => :ckeditor
  end
end

end

jsファイルを追加

var CKEDITOR_BASEPATH = '/assets/ckeditor/';

完成!

とりあえずはこんな感じで動きます

フォントサイズも無事に指定できてるっぽいです!

全体的に不必要なボタン類が多いのと、画像を追加・引っ張ってくるための修正を加えれば
良さそうなので、かける時間の割にいい成果物が得られました!

参考にした記事

How to add ckeditor to active admin on Rails
galetahub/ckeditor