Code Serendipity

Keyword: Ruby, Python, javascript, RoR, heroku, AWS...

Code Serendipity

Keyword: Ruby, Python, wordpress, javascript, AWS...

wordpressに独自のユーザープロフィール項目を追加する<textarea形式/input形式>

https://s.w.org/images/backgrounds/wordpress-bg-medblue.png

wordpress のユーザープロフィールに新しい項目を追加したいとき、 それをテキストフィールドとしてインラインのフォームで表示する方法はたくさん載っているけれど、 テキストエリア形式にするにはどうしたらいいんだろうか、ということを調べましたのでまとめます。

日本語文献は見つからなかったので、誰かの参考になればいいなと。

ユーザープロフィールページに表示するコード

function.php に、以下のコードを貼ってください。

my_show_extra_profile_fields() の中のhtmlは、実現したい内容に合わせて、

  • name
  • id, class
  • value

などの属性値を変えてくださいね。

add_action( 'show_user_profile', 'my_show_extra_profile_fields' );
add_action( 'edit_user_profile', 'my_show_extra_profile_fields' );

function my_show_extra_profile_fields( $user ) { ?>

    <h3>以下、追加するフィールド</h3>

    <table class="form-table">

        <tr>
            <th><label for="biography">Biography</label></th>

            <td>
            <textarea name="biography" id="biography" class="regular-text" cols="30" rows="5">
           <?php echo esc_html(get_the_author_meta('biography', $user->ID) ); ?>
         </textarea>
                
            </td>
        </tr>

    </table>
<?php }

textarea ではなくテキストフィールドを実装したい場合は<textarea>...</textarea>の部分を変更して

<input type="text" name="twitter" id="twitter" value="<?php echo esc_attr( get_the_author_meta( 'twitter', $user->ID ) ); ?>" class="regular-text" />

のようにすればOKです。

ちなみに、

<?php echo esc_html(get_the_author_meta('biography', $user->ID) ); ?>

は、テキストエリアに保存した項目を表示するためのコードです。

追加した項目をデータベースに保存させるためのコード

function.php に以下のコードをペースとしてください。

項目を増やすなら、update_usermeta() を追加してゆきます。

add_action( 'personal_options_update', 'my_save_extra_profile_fields' );
add_action( 'edit_user_profile_update', 'my_save_extra_profile_fields' );

function my_save_extra_profile_fields( $user_id ) {

    if ( !current_user_can( 'edit_user', $user_id ) )
        return false;
    update_usermeta( $user_id, 'biography', $_POST['biography'] ); // ここを追加してゆきます
}

update_usermeta の二つ目の引数は、フィールドIDと同じになるようにしてください。

参考

Adding and using custom user profile fields

OAuthの仕組みとchrome拡張機能への利用

OAuthとは?

facebookの自分のアカウントを今使っているサービスと連携したいと考えている花子」を例に出すと,

facebookに花子が登録した情報や投稿、花子がアクセス権限を持つ各種機能(facebookの友達の情報を見たり投稿を読む)に対し、

花子の許可を受けたほかのサービスがアクセスする ために

花子がサービスに対して許可を与え サービスがfacebookの提供するAPIにアクセスする際に許可を受けていることを証明する

…という一連のフローを、セキュアに実現することを目的とした「アクセス権限の付与」のためのプロトコルです。

ポイントは、連携しようとしているサービスじたいには、facebook の認証情報(パスワードとeメール)を教えなくて良いこと。facebookが、かわりに、「そうだよー、この人はfacebookでこのアカウントを使っているよ。保証するよ。直接パスワードを教えたくないから、代わりに固有のアクセストークンをあげて、これを送ってくれれば今度から花子を通さなくても、連携しているサービスだと連携するよ。」と言ってくれるわけです。

http://image.itmedia.co.jp/ait/articles/1208/27/r20_zu01.jpg ちなみに、OAuthの用語で、

  • 花子のような連携サービスのアカウントの持ち主(主人公):Resource Owner
  • いま使っている, facebookと連携したいサービス:OAuth Client
  • 他サービスの要請によって連携してくれるfacebookのような、OAuthをサポートしたAPIを提供しているサービス:OAuth Server

といいます。

1) Authorization Request

OAuth ClientはユーザーをOAuth Serverにリダイレクトさせます。

2) Authenticate User & Get Approval

リダイレクトを受けたOAuth Serverは、ユーザーを認証し、その後ユーザーに対して該当Clientへのアクセス権限付与を許可するかどうかを尋ねます。

3) Authorization Response(認可レスポンス)

ユーザーがアクセス権限の付与を許可すると、OAuth ServerはユーザーをOAuth Clientにリダイレクトして戻します。この際、リダイレクトURLには、アクセス権限付与を示すトークンが含まれます。

4) Obtain Access Token

アクセストークンを受け取ると、それが期限切れになるか、あるいは無効化されるまでは、(基本的には何度でも)それを使ってAPIにアクセスできます。

ステップバイステップで体験できるサイト

説明を読んでもわかりにくい場合はこちらを。体験しながら学ぶことができます。

f:id:serendipity4u:20170708223451p:plain

OAuthの仕組み丸分かり体験サイト

chrome extensionでOAuth

1) chrome extension OAuth ライブラリをダウンロードしextensionファイルに置く

以下からとってくる。

oauth2-extensions/lib at master · borismus/oauth2-extensions · GitHub

2) Content Scriptに挿入する

"content_scripts": [
  {
    "matches": ["http://www.google.com/robots.txt*"],
    "js": ["oauth2/oauth2_inject.js"],
    "run_at": "document_start"
  }
],

3) access token URL を許可する

"permissions": [
  "https://accounts.google.com/o/oauth2/token"
]

4) background.htmlにて, OAuthライブラリを追加

<script src="/oauth2/oauth2.js"></script>

5) OAuth 2.0 のエンドポイントを設定

クライアントID, クライアントシークレット, APIスコープを明確にして, authorize() メソッドを利用します。Authorize メソッドは新しいウィンドウをポップアップで開いてくれます。

var googleAuth = new OAuth2('google', {
  client_id: '17755888930840',
  client_secret: 'b4a5741bd3d6de6ac591c7b0e279c9f',
  api_scope: 'https://www.googleapis.com/auth/tasks'
});

googleAuth.authorize(function() {
  // Ready for action
});

アクセストークンを利用

step 5 によってユーザーはauth.getAccessToken()メソッドでアクセストークンを得ることができます。

xhr.setRequestHeader('Authorization', 'OAuth ' + myAuth.getAccessToken())

もしくはURLに付加する形

myUrl + '?oauth_token=' + myAuth.getAccessToken();

でOAuthサーバーのAPIを叩くことができます。

参考

OAuth 2.0 from chrome extensions | Boris Smus

Tutorial: OAuth - Google Chrome

Rails5 user_idじゃなくてusernameでusers#show

https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQOYCLQiJswVDipk0KNGHm9IBIqjKJkusWSZ30Y_8kbpkZRux3F8Q

twitter.com/kansiho みたいな感じでuser nameでusers#showにつなげたいときありますよね。

config/routes.rb

Rails.application.routes.draw do
    get '/:username' => 'users#show', :constrain => { :username => /[a-zA-Z-]+/ }
end

このとき、最終行に書くことを注意してください。 root_url/settings とかもusernameだと解釈されないように、最後にすることで優先順位を下げるわけです。 404ページなんかもこのように最終行付近に設定しますよね。

app/controller/users_controller.rb

class UsersController < ApplicationController

  before_action :set_user, only: [ :show]

  def set_user
    @user = User.find_by(username: params[:username])
    if @user == nil
      redirect_to root_path(notice: "ユーザーが存在しません")
    end
  end
end

ターミナルで確認してみましょう。

$ rake routes

 GET    /:username(.:format)              users#show {:constrain=>{:username=>/[a-zA-Z-]+/}}

設定されました!

参考

stackoverflow.com

rails で /users/:id ではなく /:username な routing にする方法 · Yuichi Takada

Rails5でDeviseにプロフィール画像項目を追加するときのTips

https://pbs.twimg.com/profile_images/1123677732/logo_avatar_large.png

gemを入れる

deviseはインストールされている前提で進めます。

gem 'devise'
# 以下、追加
gem 'carrierwave'
gem 'mini_magick'

uploaderを作る

$ rails g uploader Avatar

avatar_uploader.rb で, include Carrierwave::MiniMagickコメントアウトして有効化するのを忘れないこと。

uploaderをUserにマウント

app/model/user.rb

  mount_uploader :avatar, AvatarUploader

migrationする

class AddUserAvatar < ActiveRecord::Migration
  def change
    add_column :users, :avatar, :string
  end
end

ストロングパラメータの設定(sign up で追加したい場合のみ)

application_controller.rb

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:avatar])
  end
end

before_filter はRails5では非推奨(before_actionを利用)なのに注意してください。

View

<% if current_user.avatar.url.present? %>
    <%= image_tag(current_user.avatar.url) %>
    <%= f.label :remove_avatar do %>
      <%= f.check_box :remove_avatar %>
    <% end %>
  <% end %>
  <%= f.file_field :avatar %>
  <%= f.hidden_field :avatar_cache %>

参考

How to: use carrierwave with devise · carrierwaveuploader/carrierwave Wiki · GitHub

WebSocketとはなにか

WebSocket(ウェブソケット)は、コンピュータ・ネットワーク用の通信規格の1つ。

XMLHttpRequest(いわゆるAjax)の欠点を解決する技術として開発された。Ajaxの弱点というのは、クライアントからサーバーに通信できても、サーバーからクライアントに通信を行う方法がなかったこと。サーバ、クライアントの双方向で通信できる双方向通信を実現するための技術規格として生まれたもの。

WebSocketでは、サーバとクライアントが一度コネクションを行った後は、必要な通信を全てそのコネクション上で専用のプロトコルを用いて行う。つまり、最初の通信の確立じたいはHTTPプロトコルだが、そのご別のWebSocket専用のプロトコルで通信する。通信時に指定するURLは「http://www.sample.com/」ではなく,「⁠ws://www.sample.com/」の形式である。(80ポートではなく、443ポートでの通信を行う時はwss://になる)

従来の手法に比べると、新たなコネクションを張ることがなくなる・HTTPコネクションとは異なる軽量プロトコルを使うなどの理由により通信ロスが減る、といったメリットがある。

WebSocketの接続を確立するために、クライアント側はまず ハンドシェイク要求 を送る。そして、サーバー側はハンドシェイク応答を返す。

例:

ウェブブラウザが以下の要求をサーバー側に送る:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

サーバー側は以下の応答を返す。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

リクエストとレスポンス・ヘッダの中で重要なポイントは大きく4つ。

(1) WebSocketの接続先を指定する「Host」

(2)ハンドシェイク応答を得るための「Sec-WebSocket-Key」

(3)クライアントとのコネクションを維持するための「Sec-WebSocket-Accept」

(4)WebSocketのバージョンを指定する「Sec-WebSocket-Version」

 以上のリクエストとレスポンス・ヘッダにより、WebSocketによる接続が確立される。

http://www.xoriant.com/blog/wp-content/uploads/2015/02/img4-webS.png

参考

WebSocket - Wikipedia

【Rails5】ActionCableリアルタイムチャットを実装。

https://image.slidesharecdn.com/newfeaturesinrails5-151020085545-lva1-app6892/95/new-features-in-rails-5-4-638.jpg?cb=1445331597

Action Cableは、 WebSocketとRailsのその他の部分をシームレスに統合するためのものです。Action Cable が導入されたことで、Rails アプリケーションの効率の良さとスケーラビリティを損なわずに、通常のRailsアプリケーションと同じスタイル・方法でリアルタイム機能をRubyで記述できます。クライアント側のJavaScriptフレームワークとサーバー側のRubyフレームワークを同時に提供する、フルスタックのフレームワークです。Active RecordなどのORMで書かれたすべてのドメインモデルにアクセスできます。

Action Cable の概要 | Rails ガイド

概念, 用語

Publish/subscribe

出版-購読型モデルとも呼ばれる非同期メッセージングパラダイムの一種。メッセージの送信者(出版側)が特定の受信者(購読側)を想定せずにメッセージを送るようプログラムされたもの。出版されたメッセージにはクラス分けされ、購読者に関する知識を持たない。購読側は興味のあるクラスを指定しておき、そのクラスに属するメッセージだけを受け取り、出版者についての知識を持たない。出版側と購読側の結合度が低いため、スケーラビリティがよく、動的なネットワーク構成に対応可能である。

出版-購読型モデル - Wikipedia

サンプルアプリを作る

習うより慣れよ、ということで、チャットアプリを作る。 今回は Rails 5.1.1 ruby 2.4.0 で行った。 なお

qiita.com

にならった。

ActionCableはRails5じゃないとデフォルトで実装されていないので注意。

まずはRoomsコントローラと、content カラムを持つMessageモデルをデータベースに持つシンプルなアプリを作る。Rails既習ユーザを想定しているため, 前提をざっくり書くと

  • Rooms Controller#showにて@messages = Message.all
  • Rooms#showのViewにて _message.html.erb パーシャルを作り、そこでmessage.contentを表示。
  • routes.rbでroot ‘rooms/show'を設定

このアプリをリアルタイムチャットにしていく。

チャンネルを作成する rails g channel

Channelの果たす役割は、通常のMVC設定でコントローラが果たす役割と似ている。 ActionCableの論理的な作業単位をカプセル化する。チャンネルがあることで、コンスーマ(クライアントサイド)は、チャンネルを購読することができるようになる。

$ rails g channel room speak

を叩くと、以下の2つのファイルが作成される。

$ rails g channel room speak
    create  app/channels/room_channel.rb
    create  app/assets/javascripts/channels/room.coffee

作成されたチャンネルファイルを見ると最初から以下のsubscribed, unsubscribed, speakの3つのメソッドが定義されている。

# Be sure to restart your server when you modify this file. Action Cable runs in an EventMachine loop that does not support auto reloading.
class RoomChannel < ApplicationCable::Channel
  def subscribed
    # stream_from "some_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def speak
  end
end

確認する

localhost:3000 の(つまりクライアントサイドの) consoleにて App.room.speak() と打ち込むと、 Railsのログ(サーバーサイド)に、

f:id:serendipity4u:20170703120758p:plain

RoomChannel#speak と出るではないか! (嬉しくて3回やった)

クライアントサイドからサーバーサイドに通信できていることが確認できた。

さて、ここでrails console(サーバーサイド)で、

Message.create! content: 'Hello world!'

とやってもリアルタイムに更新されることはない。リロードしないと、表示されない。まだ足りないのである。

speakアクションを設定する

app/assets/javascripts/channels/room.coffee

App.room = App.cable.subscriptions.create "RoomChannel",
  # (省略)

  speak: (message) ->
    @perform 'speak', message: message //サーバーサイドのspeakアクションにmessageパラメータを渡す

このspeakメソッドによって, 全クライアントに, 受け取ったmessageデータをブロードキャストしている。

app/assets/javascripts/channels/room.coffee で、クライアント側がデータを受け取った時の挙動を定義する。

received: (data) -> 
  alert data['message']

Redisサーバを起動する。Redisとは一意のキーと、保存したい値のペアでデータを保存する(KVS:KeyValueStore)・データを全てメモリ上に持つ(なので動作が高速)という特徴を持つデータベースである(詳しくは RailsのセッションストアとしてRedisを使う(Mac/EC2:AmazonLinux) - Qiitaを参照 )。

$ redis-server

Railsサーバーを再起動する。

ブラウザのlocalhost:3000のコンソールで

> App.room.speak('hello')

とすると、アラームが表示される。

フォームでデータを送信する

app/view/rooms/show.html.erb

にて、

<form>
<input type='text' data-behavior='room_speaker'>
</form>

を用意する。これをリターンキーで送信できるようにするために, app/assets/javascripts/channels/room.coffeeにおいて

jQuery(document).on 'keypress', '[data-behavior~=room_speaker]', (event) ->
  if event.keyCode is 13 # return キーのキーコードが13
    App.room.speak event.target.value # speak メソッド, event.target.valueを引数に.
    event.target.value = ''
    event.preventDefault()

を追記する。(蛇足だが, jqueryを使っているのでGemfile に gem ‘jquery-rails'を追加しておくこと+ application.jsに//=require jquery, //= require jquery-ujs を追加のこと) この状態でフォームに入力してエンターキーを押すと、

異なるブラウザのクライアントも, リアルタイムで受信するわけです(2ツノブラウザでlocalhost:3000を開いて, 並べています).

f:id:serendipity4u:20170703143937p:plain

入力したmessageを保存する

app/channels/room_channel.rb で、 speakアクションが呼ばれたらdata[‘message’]をMessageオブジェクトとして保存するようにする。

  def speak(data)
     Message.create! content: data['message']
  end

さらに、 Messageモデルのコールバックとして, Messageオブジェクトが保存されたら, 非同期でブロードキャスト処理をするように設定する。

$ rails g job MessageBroadcast

app/jobs/message_broadcast_job.rbが作成される。

class MessageBroadcastJob < ApplicationJob
  queue_as :default

  def perform(message)
    ActionCable.server.broadcast 'room_channel', message: render_message(message)
  end
  
  private
  def render_message(message)
     ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message })
  end
end

app/model/message.rbにて、オブジェクトが保存されたら、ジョブを実行することを定義する。

after_create_commit { MessageBroadCastJob.perform_later self}

これで、保存とhtmlのアラーム表示が行われるようになった。

f:id:serendipity4u:20170703150407p:plain

今度は、このdata[‘message’]に入っているhtmlを使って、表示を書き換える。

サーバーからデータを受け取り、ブラウザに反映

そのためには、app/assets/javascripts/channels/room.coffee のreceived 部分を書き換える。

app/assets/javascripts/channels/room.coffee

data[‘message’]にhtmlが入っているから, append するだけ.

received: (data) ->
  $('#messages').append data['message']

これでクライアント間で完全にリアルタイムチャット化されます。

f:id:serendipity4u:20170703151316p:plain

参考

qiita.com

Action Cable の概要 | Rails ガイド

befool.co.jp

Real-Time Rails: Implementing WebSockets in Rails 5 with Action Cable | Heroku

Ruby on Railsユーザ向け速習CoffeScript + vim のシンタックス設定

https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2015/03/1427207179CoffeeScriptLogo-300x300.png

Ruby on Railsの生みの親であるDHHが、次期バージョンのRails3.1でjQueryやSCSSと合わせて、CoffeeScriptをデフォルトとして採用するとTwitter上で発言して注目を集めた.

Rubyist, Pythonia にはとっても馴染みやすいので, 手っ取り早くこれを頭に入れておけば読める書けるという特徴をメモがてら紹介する. ただCoffeeScript自体の可読性が高いだけでなく, javascriptコンパイルした時によりベストプラクティスに近いコードを簡単に生成できることがわかった.

coffee script のメリット

CoffeeScriptJavaScript の危険な部分を無くそうと、下記のような工夫をしている。

  • 全ての変数は var ありとなるため、勝手にグローバル変数もどきにはならない。
  • バグの元になりやすい曖昧な == が使えない。( CoffeeScriptで==書くと、javascriptに変換されたとき、===になっている。)
  • swich文では末尾に break があると見なされる。
  • インデントによるブロックを採用し、暗黙のセミコロン問題を発生させない。
  • デフォルトの変換では function(){…}() で囲まれため、名前空間の汚染が無い。

そして、もう一つ重要なのは読みやすさだ。Python から採用したインデントによるブロックはかなり強力だ。これだけでも、採用する価値は十分にある。

CoffeeScriptは本当に駄目なのか? - Qiita

CoffeeScriptの特徴

Pythonライクにインデントでブロックを表現

配列はこう

items = [
  "aaa"
  "bbb"
  "ccc"
]

ハッシュはこう

items = [
  {
    title: "コーラ"
    price: 150
  }
  {
    title: "トマトジュース"
    price: 120
  }
  {
    title: "ビール"
    price: 300
  }
]

セミコロンがいらない, 変数の宣言にvar がいらない

str = "hoge"
age = 30

式展開 Ruby と一緒で ダブルコーテーションの中に#{}

name = "Hanako"
str = "I am #{name}"    # "I am Hanako"

コメントの書き方

###
 複数行のコメント。これはコンパイル後も残るよ
###

# 一行コメント。これはコンパイル後消えるよ。

メソッド

javascriptだと,

//javascript

function display_alert() {
    alert("aaa" + piyo);
}

だったのが, CoffeeScriptでこうなる

//CoffeeScript
display_alert = ->
  alert "aaa"
  return

引数を受け取るなら

display_alert = (content) ->
  alert 'aaa' + content
  return

alertに括弧がいらないのに注目。

例えば足し算なら

add = (a, b) -> a + b
add(3,7) # 10

-> と => の違い

this の扱いが変わる。 -> だとthisはfunctionの中を指しますが、=> だとthisはfuctionの外側のthisになります。

if

if true == true
  console.log 'trueだよ'
else
  console.log 'false だよ'

for ループの中のif を whenで書ける

arr = [1..100]
for i in arr when i %2 == 0
  console.log "#{i} は偶数です"

ヒアドキュメント

‘’‘ でいける。

html = '''
<ul>
  <li> Hiii </li>
  <li> Hello </li>
</ul>
'''

デフォルト引数が渡せる

fnc = (arg = 1) ->
 console.log arg

undefined とnullのチェックが簡単

detarame_var? #false
detarame_var?.detarame_method #undefined
#javascriptだとundefinedのものに対してアクセスしようとするとTypeErrorで怒られるが, それがない.

Vimでのシンタックスハイライト設定

https://github.com/kchmck/vim-coffee-script

の Install using Pathogen の方式で 設定した。

pathogen.vim - Poor man's package manager. Easy manipulation of 'runtimepath' et al : vim online を.vim/配下に置いて .vimrcにpathogenを以下のように設定し

call pathogen#infect()
syntax enable
filetype plugin indent on

./vim/bundle 配下に

 git clone https://github.com/kchmck/vim-coffee-script.git ~/.vim/bundle/vim-coffee-script/

vim-coffe-scriptを取ってきて

$source ~/.vimrc

で反映する。

f:id:serendipity4u:20170703135929p:plain

こんな風になりました。

参考

qiita.com

www.infiniteloop.co.jp

RailsではじめてのVue.js :サンプルコード

https://jp.vuejs.org/images/logo.png

Vue.js とは

Vue.jsはMVVMと呼ばれる設計パターンを採用しているフレームワークです。MVVMフレームワークではModel、View、 ViewModel の3つでアプリケーションを構築します。このシリーズでは、設計パターンに関するややこしい話については触れません。双方向データバインディングを実現することに特化しているため、とてもシンプルにわかりやすく書くことができます。

Vue.jsを使いこなす - Vue.jsとは | CodeGrid

Vue.js のコアは、単純な{{テンプレート構文}}を使って宣言的にデータを DOM に描画することを可能にするシステムです。データと DOM は関連付けられ、そして全てがリアクティブになっています。

はじめに - Vue.js

<div id="app">
  {{ message }}
</div>


<script>
var app = new Vue({
  el: '#app', // #対象となるHTML要素。ここで指定した要素に対し、dataで指定した値がバインドされる。
  data: {
    message: 'Hello Vue!'
  }
})
</script>

表示非表示をvue.jsで簡単に: v-ifディレクティブ でboolean型に

<div id="app">
  <p v-if="seen">Now you see me</p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    seen: true
  }
})

ここで

app.seen = false;

にすると消える!

ループ:v-forディレクティブ

<div id="app">
  <ol>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ol>
</div>
var app = new Vue({
  el: '#app',
  data: {
    todos: [
      { text: 'Learn JavaScript' },
      { text: 'Learn Vue' },
      { text: 'Build something awesome' }
    ]
  }
})

さらに、pushメソッドで

app.todos.push({ text: 'New item' })

追加/表示できる。

ユーザーのアクションをひろう:v-onディレクティブで リッスン要素(click, etc.)と実行関数を指定

<div id="app">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>
</div>


<script>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})

</script>

双方向データバインディング

データバインディングとは、JavaScriptのオブジェクト(モデル)をHTMLテンプレート(ビュー)に結び付けるための機能。

html

<div id="app">
    <input type="text" v-model="name"> <!-- v-model 属性を追加 -->
    <div>Hello {{name}}!</div>
</div>
<script src="vue.js"></script>
<script src="app.js"></script>

app.js

var vm = new Vue({
  el: "#app"  // id="app"となっている要素を、ViewModelとして使う宣言
});

Railsに組み込む

コマンド一発でvue.jsをインストールできるようにwebpackerを入れる。 webpackerはRails 5.1 から導入された、従来のasset piplineとwebpackをつかったJSアプリケーションを共存させるための仕組み。Yarnに依存している。Webpackerが管理するJavaScriptのパスは、app/javascript/packs/になっている。webpackのサポートを有効にするには、rails newコマンドのオプションで–webpackを使用するか、Gemfileのgem ‘webpacker'の部分を有効にして、bin/rails webpacker:installを実行する。 Yarn は5.1 からデフォルトでサポートされるようになった。これによって、package.jsonがアプリケーションに追加され、node_modulesがアセットパイプラインのパスに追加されます。

gem 'webpacker', github: 'rails/webpacker'

f:id:serendipity4u:20170702143626p:plain

その後、

$ rails webpacker:install:vue

とすればvue.jsが使えるようになります。

参考

blog.spicelife.jp

全然Windows開発したことのない人がVisual StudioでVisual C++でHello Worldやる時に読むといいまとめ(超基本)

https://isocpp.org/files/img/cpp_logo.png

Visual Studio とはmicrosoft統合開発環境である。今回はMacに入れたwindowsVisual StudioからC++でコードを書くという初めての試みの3乗をやるので、念のためブログに調べたことを書いておく。ちなみに私は今までターミナルのvimRailsアプリを作るという素朴な開発環境,Command+Rを高速で行う技術だけ磨いていた, IDEは使ったことなかった。今まで使ってきた言語はRuby, python, PHP … 総じて、コンパイルのいらない、いわゆるインタプリタ言語というやつで、恥ずかしながら、アドレスとかポインタとかそこまで意識してこなかった。。。

統合開発環境とは、なにか。改めて。

IDE(統合開発環境とは)

プログラムの作成には、テキストエディタコンパイラという 2種類の道具を使う必要があった。

分割コンパイル等によってプログラムのファイル構成が複雑になると、ソースから実行ファイルを得るためのビルド手順を自動化するツール(make や Ant、MSBuild など) が必要になる。

また、プログラム作成にはこれら以外に、動作時のプログラムの間違いを見つけて修正する手助けをするデバッガ、テストを自動化するテストツール、プログラムの各部分の性能を細かく測定することで性能向上の手助けをするプロファイラ、プログラムの修正過程を管理するバージョン管理システム、必要な機能追加やプログラムの誤りの修正状況を管理するバグ管理システム、デバッグ/リリースビルドや動作ターゲットや派生開発のターゲットなどによる設定の違いを管理する構成管理ツール、関係する画面設計などを手助けするGUI作成ツール、体系的なプログラムの修正を補助するリファクタリングツール、など、さまざまなツールを使う必要がある。

これらのツールを一つのツールから統一的扱うことが出来るようにしたのが、統合開発環境 (Integrated Development Environment, IDE) である。

Visual Studio 統合開発環境の使い方

Visual Studio 用語

Visual Studio でのプログラム作成には、以下の流れがある。 1. VS.NETの起動 2. プロジェクト(Windowsアプリケーション)の新規作成 3. プロジェクトのビルド(=プログラムの生成) 4. 生成されたプログラムの実行 5. VS.NETの終了(=プロジェクトの保存)

VS.NETで作ったプログラム(「.NETプログラム」と呼ばれる)は、「.NET Framework」という実行プラットフォーム上で動作する。

http://image.itmedia.co.jp/ait/articles/0405/19/dt-easyvs01.gif

プロジェクトとはなにか

VS.NETでは、1つの「(VS.NETの)プロジェクト」から1つの「プログラム」が生成できる。なお「プロジェクト」とは、プログラムの生成に必要な複数のファイル(「ソース・ファイル」と呼ばれる)をまとめたものである。つまりプロジェクトとは、VS.NET専用のフォルダのようなもので、複数のソース・ファイルを整理するための入れ物である。プログラムを作成するには、まず、このVS.NETのプロジェクトを1つ新規作成する必要がある。これには、IDEのメニュー・バーから[ファイル]―[新規作成]―[プロジェクト]を選択する。

連載簡単!Visual Studio .NET入門:第1回 初めての「Visual Studio .NET」 (3/4) - @IT

Hello World してみよう

C++の教科書の簡単なサンプルコードをVisual C++で動かす方法はふたつあります。一つは「空のプロジェクト」を作る方法、もう一つはVisual Studioが用意するコンソール・プリケーションのテンプレートを利用する方法です。まず、「空のプロジェクト」を作る方法を示します。メニューから「ファイル/新しいプロジェクト」を選びます。左側のテンプレートで「Visual C++」を選び、「Win32 コンソール アプリケーション」を選びます。下のところでプロジェクトの「名前」や「場所」を適当に決めます。

アプリケーションの設定で「コンソール アプリケーション」を選び、追加のオプションを「空のプロジェクト」として「完了」ボタンを押します。 メニューから「プロジェクト/既存項目の追加」を選びます。「C++ ファイル(.cpp)」を選び、名前を付けます。ここでは「Hello.cpp」とします。コードを打ち込んだら、打ち込んだら、メニューから「デバッグデバッグなしで開始」を選びます。

J.S.エコハのブログ: 初心者がVisual C++で"Hello World"を表示させる方法

C++ とは

なお、以下の例には

C++の超基本 - PukiWiki

を大いに参考させていただいた。

最初におまじないを入れる(後述)。

#include<iostream>
using namespace std; 

main(){} の中に処理をかいていく

int main(){ 

 処理1;
 処理2;
 ........ 

 return 0;
}

キーボードからの入力出力

変数xにキーボードから値を入力させるには、

  • cin: console input の省略形
  • cout: console output の省略形

を使う。 改行は、

  • endl: end line の省略形

で可能。 これらの変数は、

#include <iostream>

で読み込んでいる、C++標準ライブラリのI/Oストリームで提供されている。

cin >> x;
//プログラムを実行すると入力待ちになる、値をキーボードで打ってリターンを押せば入力される。

//変数xの値を画面に出力するには

cout << x;

// 改行して出すには endl

cout << "整数 a=" << a << endl; cout << "実数 x=" << x << endl;

ループ

for

for(int i=0; i<10; i++) cout << i << endl;

while

int i=0;
while( i<10 ){
 cout << i << endl;
 i++;
}

if, else if

elsif ではなくて else if とスペースはいることに注意

if(A) X;
else if(B) Y;
...
else Z;

配列

//型 配列[配列の数];

 
double v[3]; // doubleは実数の型を示す。v[0]   v[1]   v[2]ができた

// 初期値を一気に入れるなら{を使う。 double v[3]={1, 2, 3};

ファイルに書き込む

#include <fstream> // これでfout関数などが使えるようになる
int main(){

 .....

 ofstream fout("file.txt"); // ファイル名を命名

 .....
 
 fout << "Hello, World!" << endl; // 書き込み

 .....
 
 fout.close(); //  ファイルを保存して閉じる

 .....

 return0;
}

アドレスとアクセス

変数の前に「&」を付けると、その変数のメモリアドレスを表現できる。

cout << &a << endl; //0012FF50

アドレスが0012FF55 とかのとき、*(0012FF55) とすれば、そのアドレスにあるデータにアクセスできる。アスタリスク+アドレスで、そのアドレスのデータにアクセスできると覚えておく。

アドレスとポインタ

アドレスを保存するためだけの、変数を、データ型に*をつけることで表現できる。

たとえば、ある整数 int a=2; があったとき、 そのaのアドレスを保存する変数を、 int* pointer; と宣言することができて、実際にはaのアドレスは&aで示されるから、 pointer = &a;

// データの型* 変数;


int* p; //整数のデータのアドレス用のポインタ
int a = 100;
p = &a;

配列とポインタ

double v[3]={1,2,3};

としたとき、v[0]のアドレスは、vなのである。 連続する配列のアドレスは連続しているので、&(v[1]) == (v + 1), &(v[2]) == (v + 2) である。

足し算関数sum()を作ってみる

#include <iostream>
using namespace std;

// ポイント:main関数より先に、さらに、main関数の外に宣言しているのに注目

int sum(int a, int b); //関数sumの宣言
void output(int a); //関数outputの宣言
 
int main(){
    int a;
    a=sum(2,5); //関数sumの呼び出し
    output(a); //関数outputの呼び出し
    return 0;
}

//関数sumの定義


int sum(int a, int b){
    int c=a+b;
    return c;
}

//関数outputの定義
void output(int a){
    cout << "答えは" << a << "です。" << endl;
}

 

関数とポインタ

以下、引数が増えていく関数を作ろうとしているが、間違っている例。

#include <iostream>
using namespace std;
void plusone(int x); 
int main(){ 
    int a=1;
    plusone(a);
    cout << a << endl;
    return 0;
} 
void plusone(int x){
    x++;
}

main関数の変数aとplusoneの変数xは全く別物であって、plusone()がmain()のaに代入されていないことによる。 そこで、ポインタを使ってaのアドレスにアクセスしてaの値を書き換える。

int main(){ 
    int a=1;
    plusone(&a); // &でaのアドレスを取得。
    cout << a << endl;
    return 0;
} 
void plusone(int* p){ // aのアドレスを入れて
    (*p)++; // そのアドレスのデータ(*p)を1増やす。
}

ファイルを分割してsumプログラムを作る

C++では一般的に、ヘッダー部(.h)と実装部(.cpp)を分ける。そのほうがコンパイル時間が早くなる・ビルド済みの実装部と要件定義を示すヘッダー部だけ配布するというシチュエーションがありうるかららしい

main.cpp

#include <iostream>
#include "func.h" // ヘッダファイルである、func.h (後述)を読み込む。iostreamはもともと用意されているので、<>で囲むが、自分で作ったヘッダファイルは二重かっこ"で囲む。
using namespace std; 

int main(){
    int a;
    a=sum(2,5); //関数sumの呼び出し
    output(a); //関数outputの呼び出し
    return 0;
}

func.cpp

#incl ude <iostream>
using namespace std;
func sum(int a, int b){
   c = a + b;
   return c;
}
void output(int a){
    cout << "答えは" << a << "です。" << endl;
}

func.h

関数の宣言だけを集めたファイル。ヘッダファイルという。 コンパイルのいらない部分だけを書くようにする。 したがっておまじない(include…)はいらない

int sum(int a, int b); 
void output(int a);

dll ファイルとは

Windowsを使ったことのなかった自分は、DLL??は??という感じであったが・・・ なんのことはない、Windowsにおける実行ファイルの拡張子である。 Windows.NET Frameworkの実装においては、アセンブリにはプロセスアセンブリ (EXE) とライブラリアセンブリ (DLL) の2種類がある。DLLは、EXEファイルから呼び出されて、EXEファイルに機能を提供するためのファイル。DLLは、Dynamic Linking Library(ダイナミック・リンキング・ライブラリ)の略で、よく使う機能は互いに共同で使えるように独立させておき、必要に応じ てアプリケーションが共同して使えるようにしたソフトである。EXEを補佐する役割があるのがDLLと考えればよいようだ。

Macしか使ったことのない人間がBootCampでWindowsを入れてMacライクにする

https://support.apple.com/library/content/dam/edam/applecare/images/ja_JP/macos/macos-sierra-boot-camp-hero.jpg

Windows OSでしか動かないソフトウェア, ハードウェアをどうしても使いたかった。macbook2016 8gbでは、Virtual Boxみたいな仮想環境だと動作が鈍くなりそうだと思い、Mac 標準機能であるBootCampを利用することにした。 なおparacellという選択肢もあったが、ハードウェア周りに弱い(USBポートを認識しなかったりする?)らしいのでやめておいた。

Bootcamp でwindowsをいれるには

  • Windows のライセンスキーをAmazonかなんかで手に入れる。1.3万円程度であった。
  • Windows のイメージファイル(*.ios)を手に入れる。windows公式サイトから落とせる。
  • Boot Camp アシスタントを開き、該当するイメージファイルを選択して進めていく。

公式サイトを見て入れば簡単にできると思われる。

Boot Camp で Mac に Windows をインストールする方法 - Apple サポート

快適に使うためのBootCampの初期設定

1. スクロール方向を逆にする

  • ファイル名を指定して実行、の項目でregeditを入力し、「レジストリ エディター」を開く。
  • コンピューター¥HKEY_LOCAL_MACHINE¥SYSTEM¥ControlSet001¥Enum¥HID¥VID_¥¥Device Parameters のディレクトリから自分の使っているマウスホイールに割り当てられているIDのものを探し、FlipFlopWheel項目をクリックして、「DWORD(32ビット)値の編集」ウィンドウが表示されたら、「値のデータ」を「1」に変更し、「OK」をクリックする。
  • 再起動する。

詳しくは

Boot Camp上のWindows - スクロールをナチュラル(逆)方向に変更 - PC設定のカルマ を見てください。

2. commandキーをcontrolキーにする

初期設定のままだとcommandキーにwindowsキーが割り当てられて使いづらい。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,02,00,00,00,1d,00,5b,e0,00,00,00,00

これを *.reg 拡張子でデスクトップなどに適当に保存し、レギストリエディタでImport してから再起動すると反映される。

詳しくは

MacbookProのBootcampで、CommandボタンをCtrlキーにする方法 - のびっこ日記 を見てください。

3. 日本語- Roma字の切り替えをcommand + space キーで行えるようにする

下記サイトを参考に、Microsoft IME 詳細プロパティにて、「Ctrl+SPACE」に『IME オン/オフ』(もしくは変換モード切替)を設定すればよい。

[Mac] BootCampなWindows 7を快適に操作するためにした設定 & やったこと | Tools 4 Hack

## ターミナルどこ?

Windows用の仮想ターミナルは、コマンドプロンプトという名前になる。

vim 使えるようにしたい

初期状態で入っていないので取ってくる。 www.kaoriya.net

覚えておくべきコマンド

  • dir : ls
  • del: rm
  • move: mv ( rename, move )
  • xcopy : cp