Ruby(Rails)」タグアーカイブ

Apache+PassengerでRailsを動かす

passengerインストール(gem)

sudo gem install passenger

sudo /usr/local/bin/passenger-install-apache2-module
を実行する。(該当ファイルが見つからない場合。sudo find / -name “*passenger*” -type f)

最後に必要な追加が表示される。
sudo apt-get install libcurl4-openssl-dev
sudo apt-get install libcurl4-gnutls-dev
sudo apt-get install apache2-dev
sudo apt-get install libapr1-dev
sudo apt-get install libaprutil1-dev

表示されたとおり不足の機能をインストールして、もう一回以下を実行。
sudo /usr/local/bin/passenger-install-apache2-module

All goodと表示されるまで繰り返せばOKのハズだけど、今回は、
fatal error: openssl/pem.h: そのようなファイ ルやディレクトリはありません
と表示されてしまう。

必要な追加では表示されないが、opensshでエラーなので、
以下をインストールしてみる。
sudo apt-get install libssl-dev

インストールが無事終了すると、
LoadModule passenger_module /var/lib/gems/2.3.0/gems/passenger-5.1.2/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /var/lib/gems/2.3.0/gems/passenger-5.1.2
PassengerDefaultRuby /usr/bin/ruby2.3
</IfModule>
のように表示されるので、apacheの設定に追加する。

基本設定

もともとのDocumentRootは
/home/okamura/www
だったので、そこで
rails new test_app
を実行して新しいrailsのフォルダを作成してみた。

実体としては
/home/okamura/www/test_app
がrailsのプロジェクトフォルダとなる。

VirtualHostの項目で
DocumentRoot /home/okamura/www/test_app/public
として、開発なので以下を追加しておく。
RailsEnv development

これで問題なく動いた。

サブディレクトリで複数動かす場合

railsのpublicの実体が
/home/okamura/www/test_app/public
apacheのconfでのdocumentrootが
/home/okamura/www/test_app/public
とするのが基本。

サブディレクトリで複数のアプリを動かしたい場合。
apacheのconfでdocumentrootを
/home/okamura/www
にする。

RailsBaseURI /app1
RailsBaseURI /app2
を追加する。

railsのpublicの実体のシンボリックを作る。
sudo ln -s /home/okamura/ruby/asagao/public /home/okamura/www/app1
sudo ln -s /home/okamura/ruby/pico_planner/public /home/okamura/www/app2

apacheのconfはこんな感じ。
DocumentRoot /home/okamura/www
RailsBaseURI /app1
RailsBaseURI /app2
RailsEnv development

Ruby文法基礎

画面出力

puts 改行、print 改行なし
gets 入力
p はputs 変数.inspectと同じ

変数

ローカル変数

注意、変数のスコープは上位のスコープを探さない。
ブロック、メソッド、クラス/モジュール定義の終わりまで。

class Hoge
   x = “bye”
  def initialize
    x = “hello”
    puts x
  end
end
h = Hoge.new #=> hello

インスタンス変数

class User
  def say
    puts @x
    @x = “b”
    puts @x
  end
  def self.say2
    puts @x
    @x = “a”
    puts @x
  end
end

User::say2
#=> 空白
#=> a
u = User.new
u.say
#=> 空白
#=> b

@を前置する
インスタンス生成時に作られない。値の代入時に実体が生成される。
クラス定義内で定義しない。
通常メソッド内で定義するがスコープはクラス内となる。
(ローカル変数の場合メソッド内だけになってしまう。)
使えるのはinitializeメソッドとインスタンスメソッドのみ

@前置きの変数をクラスメソッド内で操作してもインスタンス側に変更はない。
クラスメソッド内での@前置きの変数はクラスインスタンス変数として動作している模様。

クラス変数

class User
  @@x = “hello”
  def say
    puts @@x
  end
  def self.say2
    puts @@x
  end
end

User::say2 #=> hello
u = User.new
u.say #=> hello

@@を前置して、クラス定義の中に書く。
クラスメソッド、インスタンスメソッド、クラス定義式内でアクセス可能

クラスインスタンス変数

class User
  @x = “hello”
  def say
    puts @x
  end
  def self.say2
    puts @x
  end
end

User::say2 #=> hello
u = User.new
u.say #=>  空白

作り方は、@を前置きするのはインスタンス変数と一緒で、クラス定義内で定義するだけ。
機能はほぼクラス変数。違いはインスタンスメソッドからアクセスすることはできない

クラス・インスタンス変数のまとめ

@も@@もクラス内スコープ
ただ、@@はクラスで既に実体があるが、
@はインスタンス生成後、さらに代入などの処理があって実体ができる。

例えば、
class User
  @x = “hello”
  def say
    puts @x
  end
end
u = User.new
u.say
これでは空白が出力
@xを@@xにすればhelloが出力される。

class User
  @@x = “hello”
  def self.fst
    @@x = “bye”
  end
  def say
    puts @@x
  end
end
User::fst
u = User.new
u.say #=> bye
クラス変数は実体がクラスにあるので、クラスメソッドでの変更後
インスタンスを生成すると変更の影響を受けている。

つまり、@も@@もスコープはクラスの変数。
@をクラスで定義したりクラスメソッドで定義すると、クラス変数と同様のクラスインスタンス変数になるが、
値を入れておいてもインスタンス生成時に値が破棄される。
(インスタンスでの@とクラスにある@が別のスコープの別変数として存在している)

継承についても注意が必要で、@@は継承後も値は破棄されないが、
@は継承時にインスタンス生成と同じように破棄される。

@も@@も共にスコープはクラスなので、@をクラス変数の様に使うことも可能だが、
そうすると、インスタンスや継承時の動作に注意が必要。

class User
  @x = “hello”
  def self.fst
    puts @x
    @x = “bye”
    puts @x
  end
  def say
    puts @x
  end
end
User::fst
u = User.new
u.say
#=> hello
#=> bye
#=> 空白
@変数をクラス変数の代わりに利用。インスタンスで使わないなら問題ない。

グローバル変数

$を前置
スコープ無視

モジュール

module Hoge
  x = “hello”
  def self.say
    x = “bye”
    puts x
  end
  def sayHello
    puts “Hello Hello”
  end
end
Hoge::say #=> bye
ここのxはローカル変数であって、スコープ外なのでx=byeがないとエラー

class HogeHoge
  include Hoge
end
HogeHoge::say
モジュールでのクラスメソッドはインクルードされない。

h = HogeHoge.new
h.say #=> NG
h.sayHello #=> Hello Hello
モジュールのクラスメソッドはインクルードされない。
インクルードされるのはインスタンスメソッドのみ

module Fuga
  @x = “hey”
  def self.say
    puts @x
  end
end
Fuga::say #=> hello

class FugaFuga
  include Fuga
  def say
    puts @x
  end
end

f = FugaFuga.new
f.say #=> 空白
Fugaでの変数が@@xならheyと表示される
ミックスインでも@@はインクルードされるけど、@は破棄されるということ。

演算子

=== は、ほとんど == と同じだけど、
正規表現 === 変数 だとマッチするかどうか、
クラス === 変数 だとそのクラスのオブジェクトかどうか判断する。

数値
Fixnum
Bignum
Float

型はないので自由な値が入る。入っている値によって
指し示すオブジェクトが変わる。

型の自動変換はないので、
to_s
to_f
to_i

文字列

連結は+

“”は式展開あり #{ xxx }
”は式展開なし

囲う

%q = ‘xxx’と同じ
%Q = “xxx”と同じ
% = “xxx”と同じ
%r{xxx} = /xxx/と同じ(正規表現)
%w(xxx,xxx,xxx) は配列(Wだと式展開あり)

配列

[“dog”,”cat”]

include?
length
empty?
などのメソッドがある。

追加は <<

要素を超えて、取り出すとnil、加えると自動で大きくなる。
オブジェクトなら何でもはいる。

条件分岐

0,や空文字もtrueになる。falseはnilとfalseだけ。
比較演算子はtrue/falseを返す b = (a == c)等
条件分岐に入ると、真偽問わず、スコープの中にある変数は初期化される。

スコープ

if,for,while,case
などの条件式で、スコープを作らない。

メソッド、ブロックではスコープができる。

x = “hello”
def fnc
  x = “bye”
  puts x
end
puts x
fnc
#=> hello
#=> bye

面白いのは、インスタンス変数でも同じということ
これは既にmainというクラスの中にいるから。

@x = “hello”
def fnc
  @x = “bye”
  puts @x
end
puts @x
fnc
#=> hello
#=> bye

クラスで囲うとどうなるか。

class User
  @x = “hello” #<1>
  def fnc
     @x = “bye”
     puts @x
  end
  puts @x #<2>
end
u = User.new
u.fnc
#=> hello
#=> bye

この結果も同じだけど、これはインスタンス生成時に、classが評価されて、
最初のhelloが出力されている。実際、u.fncを呼ばなくてもhelloは出力されるし、
<1><2>のどちらかを消すとhelloを出力されない。

そのあとのbyeは普通どおりインスタンスからfncを呼んでいるから出力される。

インスタンス生成後も@x = “hello”は生きているけど、それはクラスのスコープであって
インスタンスには存在しない。

class User
  def fnc
    @x = “b”
    puts @x
  end
  def fnc2
    puts @x
  end
end
u = User.new
u.fnc
u.fnc2
#=> b
#=> b

インスタンス変数はクラススコープなので、最初fncでbが入り、次のfnc2でもその値が生きている。
fncをせずにfnc2を呼ぶと空白が出力される。

メソッド

途中で抜ける場合 returnも使える。
初期値を指定できる
def xx(var = “hello”)
end

引数の数量不定にすると配列になる
def fuc(*var)
end

第1引数はfstに入り、それ以降がvarの配列へ
def fuc(fst, *var)
end

名称について
? = true/falseを返す
! = 破壊的メソッド

ブロック

メソッド呼び出し時に定義する。メソッドに渡す処理の塊。
渡したメソッド内ではなく、ブロックを定義したスコープにいる。
yieldでメソッド側からブロックに引数を渡せる。

例外処理

begin

rescue
  例外時
else
  例外がない場合
end

メソッドなら
def

rescue
  例外時
else
  例外がない場合
end
とも書ける。

rescue => 変数で取り出す。

ハッシュ

population = {“France”=>100}
puts population [“France”]

キーがシンボルなら、以下の書き方ができる。

pop = {:fr => 100 }
なら、
pop = { fr:100 }
とできる。(スペースはいれない)

取り出すときは
pop [:fr]
となる。

範囲

1..10 # 1から10まで
1…10 # 1から9まで

正規表現

=~ で比較できる。
!~ は逆

string.gsubで置き換え。

日付

日時はTimeクラス
Dateオブジェクトは日付だけを扱う

日時の取り出し

t = Time.now
t.year
t.month
t.day
t.hour
t.min
t.sec

作る時

Time.local(2015,12,31,23,59,59)

整形はstrftime

t = Time.now
t.strftime(“%Y/%m/%d %H:%M”)

参照渡し

参照の値渡しになっている。

str1 = “hello”
str2 = “goodbye”

print “str1=”, str1.object_id, “\n”
print “str2=”, str2.object_id, “\n”

str1 = str2 #ここでstr1もstr2も”goodbye”を指している
str1.upcase!

print “str1=”, str1.object_id, “\n”
print “str2=”, str2.object_id, “\n”

puts str1,str2

str1=71129430
str2=71129420
str1=71129420
str2=71129420
GOODBYE
GOODBYE

クラスとメソッドについて

ドット記法はメソッド呼び出し
レシーバ.メソッド

二重コロンは
定数呼び出し、メソッドも呼べる。

rubyのインスタンスの内部的にはインスタンス変数とメソッドへのリンクだけ。
メソッドの定義はクラスに持っている。

ただ、通常のメソッド定義だとインスタンスに紐付いてクラスから直接呼べない

インスタンスメソッドをクラスから呼ぶNG
class Hoge
  def piyo
    ”hoge”
  end
end
p Hoge.piyo #=> undefined method

インスタンスメソッドをインスタンスから呼ぶOK
class Hoge
  def piyo
    ”hoge”
  end
end
h = Hoge.new
p h.piyo #=> hoge

クラスメソッドをクラスから呼ぶOK
class Hoge
  def self.piyo
    ”hoge”
  end
end
p Hoge.piyo #=> hoge

クラスメソッドをインスタンスから呼ぶNG
class Hoge
  def self.piyo
    ”hoge”
  end
end
h = Hoge.new
p h.piyo

と分けられる。

アクセサメソッド

自動で生成したい場合、インスタンス変数の名前をシンボルで渡す。
attr_accessor :name

そうすると、以下の2つのメソッドを自動で作る。
name=(value) # setter
name # getter

実体は以下のような感じ
class User
  def name
    @name
  end
  def name=(name)
    @name = name
  end
end

それぞれ1つだけでいい場合。
attr_reader :name
attr_writer :name

クラス内でアクセッサメソッドを呼ぶ時、
レシーバを省略して呼ぶと、ローカル変数とみなされてしまうので注意

メソッドのアクセス範囲

public

どこからでも

private

同クラス、サブクラスから読める。
レシーバ付けられない。関数形式でしか呼び出せない。

protected

同クラス、サブクラスから読める
レシーバ付けられる。
そのメソッドを持つオブジェクトがselfの場所でのみ呼び出せる

Ruby NET/SSH NET/SCP接続実験

SSH接続

SCP接続

レンサバで運用しているMySQLのバックアップをローカルのUbuntuへ保存。
必要であればcronに登録。

Rubyファイル操作

bash_historyの重複削除

ApacheのCGIでRubyを呼び出す。

Apacheの設定

sudo find / -name 000-default.conf
で検索かけると2箇所ある。

/etc/apache2/sites-enabled/000-default.conf
/etc/apache2/sites-available/000-default.conf

設定を読み込まれているのは、enabledで、availableの
設定ファイルへシンボリックしている。

mods-enabledの中でシンボリックしているのは、
cgid.conf
cgid.load
だけ。

mods-availableの中にcgi関連は、
authnz_fcgi.load
cgi.load
cgid.conf
cgid.load
proxy_fcgi.load
proxy_scgi.load
だけ。

sites-availableを以下のように変更。
<Directory /home/okamura/www/>
Require all granted
AllowOverride All
Options +ExecCGI
AddHandler cgi-script .rb
</Directory>

CGI側(Ruby)

rubyのファイルに以下のように記述し、
chmod +x で実行権限をつければOK。

エラーの場合、
改行コードが違っていてハマッた。Winで作ってLinuxに転送の場合注意。

GETを受取たい場合

送信側(Form)

CGI(Ruby)

UbuntuへのRuby、Railsのインストール Railsの使い方基本

必要であればPassengerも
Apache+PassengerでRailsを動かす

インストール

sudo apt-get update
sudo apt-get install ruby
ruby -v
gem -v (rubyのverによってはgemが入らない)
sudo apt-get install ruby-dev zlib1g-dev liblzma-dev
sudo gem install nokogiri
sudo gem install rails
rails -v

プロジェクト作成

以下は普通の流れ。

rails new xxx(ここでxxxフォルダが作成される。初回のみsqlite関連のエラーがでる)
sudo apt-get install sqlite3
sudo apt-get install sqlite3 libsqlite3-dev
sudo gem install sqlite3
sudo apt-get install nodejs
bundle install
rails s -b 0.0.0.0

インストール後プロジェクト作成

ここから自分用

rails new xxx -B -C -T -d sqlite3
B:bundleスキップ
C:ActionCable関連生成しない
T:テスト関連生成しない

もしプロジェクトを別PCからのコピーする場合。コピーしたフォルダで
bundle update
rake db:migrate
を実行する必要がある。

タイムゾーン設定

/config/application.rb

config.time_zone = ‘Tokyo’
と追加。

Gemfileを編集

ここでは
Coffee-rails
を削除し、必要であればrubyのバージョンも指定して以下を追加する。
gem ‘bootstrap’
gem ‘tether-rails’
gem ‘font-awesome-sass’
を追加し、
bundle install
を実行。

bundlerはgemのバージョン管理をするプログラムで、
gemの依存関係が書かれたgemfile.lockを生成する。
手作業で編集するのはgemfileで、gemfile.lockはいじらない。
gemfile.lockのある場所でbundle installとすると、プロジェクトに必要なgemが入る。
bundlerが読んでいるのはlockのほうで、
bundle updateをするとlockを無視し、Gemfileを元にインスト、lockの再生成する。
Gemfileの中
‘=>1.3.0’ の表記は、1.3.0 以上という意味
‘~>4.1.0’ の表記は、4.1.0 以上 4.2以下

generators.rbの編集(rails gコマンドの設定)

config/initializers
の中に
generators.rb
を作成し以下を記述。
Rails.application.config.generators do |g|
 g.helper false
 g.assets false
 g.skip_routes true
 g.test_framework false
end

 cssの設定

/assets/stylesheets/application.css
をscssに変更して、さらに同フォルダにmain.scssを作成。

application.scssには、以下を記述。
@import ‘bootstrap’;
@import ‘font-awesome-sprockets’;
@import ‘font-awesome’;
@import ‘*’;

Javascriptの設定

/assets/javascript/application.js
の中に以下を追記
//= require tether
//= require bootstrap-sprockets

モデルの作成

rails g model member
(単数形)
ここでマイグレーションクスリプトができる。

テーブル名: members
クラス定義: Member
クラスファイル: member.rb
テスト: member_test.rb

config/routes.rb

resources :members
と記述する。

マイグレーションスクリプト設定

migrateスクリプトはテーブルを定義する。
/db/migrate/xxx

参考
http://railsdoc.com/migration

データベース関連

rails new のときにデータベース接続用のymlが自動で作成される。
config/database.yml
が設定ファイル。

データベース作成・削除

rake db:create
テスト、開発用ができる。

rake db:create RAILS_ENV=production
本番用だけできる。

rake db:dropb
テスト、開発を削除できる。

rake db:dropb RAILS_ENV=production
本番用を削除できる。

テーブルの作成

rake db:migrate
テスト、開発用

rake db:migrate RAILS_ENV=production
本番用

migrateコマンドを実施するとschema.rbができる。

テーブルを作成後変更の場合、
rails g migration クラス名
でできたファイルにadd_column等を書いて再度db:migrateでOK

テーブルのバージョンを戻す場合
rake db:migrate VERSION=2015xxxx(数字の部分だけ)
rake db:rollbak(ひとつ前のバージョン)

現在のバージョン
rake db:migrate:status

テーブルの破棄(マイグレーションの書き直し)

rake db:migrate:reset

rake db:drop
rake db:create
rake db:migrate
の3つと同じ効果がある。

ちなみに、
rake db:reset
は、
rake db:drop
rake db:create
rake db:schema:load
rake db:seed
と同じ効果がある。

rake db:setup
は、
rake db:create
rake db:schema:load
rake db:seed
と同じ効果がある。

シードデータ

アプリを作ったときにdb/seeds.rbができる。
中にスクリプトを書いて以下を実行。

i  = model_class.new
i.col_name = “xxx”
i.save!
というのが基本

rake db:seed
テストと開発

rake db:seed RAILS_ENV=production
本番

でデータが挿入される。

ルーティング

root “control_name#action_name”
はルートアクセス用。これは
:root
でこのパスが取得できるようになる。

基本は
request_type path => “control_name#action_name”

as: を付けることでシンボルで指定できる。

例1

routes.rb: 
get “bad_request/:a/:b/:c” => “top#bad_request”

top_controller.rb:
  def bad_request
  render :text => “hello world” + ” ” + params[:b] + ” ” + params[:a] + ” ” + params[:c]
end

以下のアドレスでアクセスすると
http://192.168.102.15/app1/bad_request/taro/Mr/123

ブラウザには以下のように表示される。
hello world Mr taro 123

get “lesson/:action(/:name)” => “lesson”
のようにパラメータに()を付けると省略可能。
:actionに入る名称がコントローラで、そのまま呼ばれる。

コントローラの作成

rails g controller members
リソース用のコントロール作成
(CRUDのような集合に対する操作をするのは複数形、それ以外は単数形)

クラス定義: MembersController
クラスファイル: members_controller.rb
テンプレートフォルダ: app/views/members/アクション名
テスト: members_controller_test.rb

コントローラでは以下を定義していく。
index /members
new /members/123
create /members/new
show /members/123/edit
edit /members – POST
update /members/123 – PATCH
destroy /members/123 – DELETE

rails gの変更をしていなければ、コントローラ作成と同時に5個のファイルが生成される。
controllers/top_controller.rb
views/top/index.html.erb
helpers/top_helper.rb
assets/javascript/top.js
assets/stylesheets/top.scss

変更したい場合は、generators.rbを修正する。

ビューの作成

/views/controller_name/method_name.html.erb
が自動で呼ばれる。

アクションの定義がなくてもビューは呼び出される。

テンプレートの作成

全体を囲うテンプレートは、
views/layouts
に入っている。
application.html.erb
ビューが入るのは
<% yield %>

ただし、
views/layouts/controller_name.html.erb
が存在する場合、
application.html.erbより優先して、
上記のファイルが読まれる。

アクション内で
render layout: false
とすると、テンプレートが読み込まれない。
ビューは読まれる。
アクション内で、
render :text => “xxx”
とすると、xxxだけでビューもテンプレートも呼ばれない。

ヘルパーメソッド

app/helper
の中で定義する。

ビューの中で自由に使えるメソッド

バリデーション

モデルの中に書く。以下のような感じ
validates :number,presence: true, length:{ オプション }

saveが呼ばれたタイミングで登録しようとした値が正しいかチェック。

モデルの更新方法

モデルのクラスメソッド

ファインダーメソッド
find: 主キー(id)を渡す
find_by: カラム:値のハッシュを渡す

クエリメソッド
where: カラム:値のハッシュを渡す
find_by_sql: SQLを渡す。

findなどレコードで取得するのがファインダーメソッドで、モデルに直接使う(クラスメソッド)
レコードはモデルオブジェクトとなる。

whereなどのクエリメソッドだとリレーションオブジェクトが返ってくる。検索条件を保持している。
リレーションオブジェクトにはファインダーメソッドが使える。

開発時のモード

development: 開発
test: 自動テスト用
production: 本番

railsやrakeコマンドは実行時に
RAILS_ENV
の中の環境変数によって動作が変わってくる。

コードの中でも
Rails.env.development?

Rails.env.production?
などでtrue/falseで確認できる。