kikeda1104's blog

備忘録・技術に関することを書いています。(webエンジニア)

constraintsの利用について

後輩にvimの折り畳み開閉のショートカットキーを聞かれてて、忘れてたのに落ち込んだり、

参加したセミナーでテストコードに関する有益な話を聞けてほっこりしてます。

コミュ力って重要。

Railsのroutes.rbで、ルーティングを無条件で利用すると、public下の置いているファイルとルーティングが当たってしまうので、

これを回避するためにURIを変えるか。制限を入れるかを考えていて、制限を入れることにしました。

constraintsを使って定義する。

環境

constraints

定義したルーティングに制限を追加することできます。

# config/routes.rb
Rails.application.routes.draw do
   get 'users/:user_id' => 'users#show', constraints: /\d+/
end

これは、ブロックも利用できて、複数のルーティングに制限を加える際に利用できる。

Rails.application.routes.draw do
   constraints /\d+/ do
     get 'welcome/:id' => 'welcome#show'
     ...
   end
end

今回は、DBの値を利用した制限を追加する形で実装を進めていてconstraintsのファイル保存場所について

appを検討したが、ひとまずlibに保存しています。

まず、lib/autoloadを起動時に自動で読み込むようにします。

# config/application.rb
...
config.autoload_paths += %W(#{Rals.root}/lib)
...
# lib/autoload/constraints/zone_constraint.rb
class ZoneConstraint
  def matches?(request)
    paths = request.path_info&.split('/')&.reject(&:blank?)
    paths.size.times do |i|
      case i
      when 0
        fail if ExampleA.find_by(key: areas[i]).blank?
      when 1
        fail if ExampleB.find_by(key: areas[i]).blank?
      when 2
        fail if ExampleC.find_by(key: areas[i]).blank?
      else
        fail
      end
    end
    true
  rescue
    false
  end
end

最後にroutes.rbに制限を加えます。

# config/routes.rb

constaints ZoneConstraint do
  get ':example_a/:example_b/:example_c' => 'example#index
  ...
end

データベースに保存されていない場合、ルーティングを参照しないようにします。

参考

Rails3 事始め: [Rails3] 現在のURLを取得(request オブジェクト)

rails routing constraintsについて | 日々雑記

constraintsの意味 - 英和辞典 Weblio辞書

Rails のルーティング | Rails ガイド

Railsアプリのモジュールはどこに置くべきか問題 (公開版)

friendly idを利用したURI設計

プロジェクトでSEO対策と数値を含めずにURIを設計するため、friendly_idを採用してURIの再設計をしました。

railsではURIにmodelの主キーを含める形の設計が主になりますが、数値では分かりづらくなります。(resourceでは作成されませんが)

それほど複雑な仕様でもないため、gemを使わず、参照しているmodelのnameカラムがありましたので英語名を追加することで実現しました。

サンプルコードは、実際に実装したコードとは異なります。

環境

Rails appの作成

# rails new friendly_app
# cd friendly_app
# ./bin/rails g scaffold users name_en:string
# ./bin/rails db:migrate

実装

app/models/user.rbに、idではなくname_enを利用するように書き換える。

# app/models/user.rb
モデルに'#to_param'を追記する。

class User < ApplicationRecord
 validates :canonical_name,
        uniqueness: { case_sensitive: false },
        format: { with: /\A[A-Za-z][\w-]\z/ },
        length: { minimum: 3, maximum: 25 }

  def to_param
    name_en ? name_en : id.to_s
  end

  def self.find(input)
    find_by(name_en: input) || super
  end
end

rails s

app serverを起動して。

# ./bin/rails s

動作確認

  • users/newでユーザを作成する。
  • users/:name_enに移動する。

f:id:kikeda1104:20160829233032p:plain

まとめ

route.rbがresourcesのままになっており params[:id]でname_enの値を受け渡すことになりわかりずらくなるので、idを受け渡さない画面ではroute.rbを変更しました。

参考URL

Friendly URLs in Rails · GitHub

Railsで、URLにIDでなく名前を入力して、アクセスする方法 - Qiita

ActiveRecord::Integration

Railsの正規表現でよく使われる \A \z って何?? - Qiita

Rspecでseeds.rbをリセット時に読み込む。

プロジェクトにrspecとfactory girlのgemを追加して seeds.rbを読み込んでから、毎回テストを起動したかったのでこのあたりをまとめておく。

環境

rspecとfactory girlの導入

まずは、Gemfileにrspec_railsfactory_girl_railsを追加してbundle installします

# Gemfileにgemを追加
group :development, :test do
  gem 'rspec_rails'
  gem 'factory_girl_rails'
end

group :test do
  gem 'database_clear'
end
bundle install

rspec install

$ rails g rspec:install

環境別のseedを作成する

これはRails.env.hoge?で切り分ければ、seeds.rbにまとめることもできる。

env毎のファイルを作成する。

mkdir db/seeds
touch db/seeds/test.rb
touch db/seeds/development.rb
touch db/seeds/production.rb

db/seeds/test.rbdb/seeds/development.rbに記述を追加

values = { email: 'hoge@example.com'... } # attriubutesを設定する。
Admin.create(values)

seeds.rbに下記のコードを追加。

load(Rails.root.join( 'db', 'seeds', "#{Rails.env.downcase}.rb"))

テスト時にdbをリセットして、seedsを読み込む。

#clean_withの引数に、exceptでクリーンにしないmodel名を記述することもできます。

config.before(:suite) do
  load Rails.root.join('db', 'seeds.rb')
  DatabaseCleaner.clean_with :truncation
  # DatabaseCleaner.clean_with :truncation, { except: %w(categories brands) }
end

参考URL

blog.inouetakuya.info

環境ごとに投入する初期データを変える - Qiita

環境にあわせてrake db:seedを実行する - how to code something

gem unicornの起動・定義・再起動

こんにちは。kikedaです。 毎回忘れるので、備忘録代わりに書いておきます

unicorn

コマンド

  • 起動

    railsのrootディレクトリで実行する

bundle exec unicorn_rails -c config/unicorn.rb -E development -D
  • 停止

    railsのrootディレクトリで実行する

kill -QUIT `cat /tmp/unicorn.pid`

もくもく会を主催した感想

kikedaです。 先日(1/10)にもくもく会を主催しました。

もくもく会に参加することはしばしばありましたが、主催する側になるのは初めてで、 開催してみて気になることや、反省点がありましたので、ずらずらと書いていきたいと思います。

(ちなみにだれかを批判するつもりはありません。)

集合時間がやや遅れる。

これは、参加するとき僕もよく遅刻していました。 主催する場合、会場を開く時間と自己紹介の時間をずらしておくといいかもしれませんね。

だれがなにをしているのかわからない。

途中で参加される方で、質問できるならしたかったけれども、だれがなにを知っているのかわからなかったとのこと。これは上記の自己紹介の時間をずらすことや、テキストによる共有や、チャットを準備することで解決しようかなと考えています。

質問できると助かる。

これは、自分のもくもく会の方向性で、経験者枠と未経験者(学生、プログラミング歴が浅い)などの枠で分けて、質問に答えられる方と分けることも考えていました。ただ、言語のしばりがなく、集まっている方の技術レベルが明確にならない以上(なおかつ、そういういった対応を極力したくない場合、自分がもくもくするために来ているため)、絶対数を確保するのは「もくもく会」という形だと実現できないかなと思っています。そもそもできている会については良いと思います。

僕は、もくもく会を1人で作業するよりか複数人で作業するほうが捗るという趣旨に賛同して開催しています。その個人個人がもくもく作業できるのが理想かなぁと思っていて、それでも時間を割いて、参加者の中で質問を受け付けていても構わない方で、扱える言語を調べて、サポートするのが自分の主催するもくもく会でできることだと思いました。

また開催して欲しいという声について

定期的に開くというのが、義務みたいになってしまうと感じていまして、自分のやりたいときに、開こうと思っています。

今後のもくもく会について

不特定多数の人たちが集まって、その中の人達で、質問したり、回答したりしていくことが自然かなぁと思っていまして、できる限りそれをコミュニティの運営方法でカバーできないかなと考えています。

良い方法や、知識があれば今後、もくもく会に適用していきたいですし、もくもく会の方向性も固めていきたいと思っていますので、参加者の方々、また開催する際には、楽しんでもくもくもらえれば嬉しいかぎりです。

ではでは。

link_toのリンク文字列にHTMLタグを入力したい(Rails 3系、Rails4系)

kindle voyageをやっと手に入れました。kikeda1104です。

link_toに、htmlタグを含めたい際の記述について、調べたのでこちらに書きたいと思います。 備忘録ですね。

コード

やりたいコードは下記になりますね。

  <a href="#"><p>リンクです</p></a>

修正したコード

で、Railsのヘルパーで書き直すと。

  <%= link_to "#" do %>
    <p>リンクです</p>
  <% end %>

この手のものはさっさと覚えて進めたいですね。

PHPのempty関数

備忘録ですね。自分のローカルの環境では、エラーが発生しなかったのですが、他の方の環境ではエラーになり、対応しました。

環境

  • codeigniter 2.2
  • PHP 5.5系

empty関数

引数が空であるかを評価して、true/falseを返却する関数です。 ただし、issetなどの変数を評価する関数と引数により返す値が変わりますので、そのあたりの細かい知識は前提として持っておいたほうが良いです。

エラーになった際のコード。サンプルです。

if (empty(set_value('domestic', 'hoge')) {
  echo 'true';
}

修正コード

$value = set_value('domestic', 'hoge');

if (empty($value)) {
  echo 'true';
}

以上で、動作します。

MySqlの列挿入

定義済みのテーブルに列を追加するsql。ただ稼働中のサービスのテーブルに追加する際には、 考えたほうがよいです。

今回は、レコード数0件のテーブルなので、alterで追加しますね。

列の追加

alter table テーブル名 ADD 列名 型

以上です。

MySql 外部参照制約

こんにちは。kikedaです。

スキーマを作成して、外部参照制約をつける機会があったので、備忘録です。Googleで検索することはあるんですが、やはり自分のブログを検索して、作業する機会が多いので「他人」より「自分」に向けての、記事を多くなりそうです。

MySqlの外部参照制約

MySqlで外部キーを持つテーブルで、関係を記述することにより、外部キーの元となるマスタテーブルの値もしくは、テーブルそのもの削除と更新を防止することができます。挙動については、指定するパラメータにより細かく変えることができますが、今回の目的は、マスタテーブルのレコードを、外部キーが参照しているレコードが存在する間は、削除と更新を防止させます。 親のレコードが消されて、つながりが示されなくなるのを防ぎます。

外部参照制約をつける。

> alter table table_name add constraint 制約名 foreign key (外部キーの列名) references テーブル名(列名) on delete cascade on update cascade;

MySql Workbenchを利用することで、データベースやテーブルを定義をして、Sqlを作成することができますので、そちらから利用することもオススメです。

以上です。

codeigniterのヘルパー

こんにちは。RubyRailsが触りたいですが、日々を過ごしているkikedaです。

「あんな技術のないやつらに・。」とか空耳を聞くくらいなので、記事書いたら休みたいです。

今日は、codeigniterを触っていて、ヘルパーを覚える機会があったので、そちらを記述していきます。

viewで使われるヘルパー

form_input

まずは、input type="text"をcodeigniterのヘルパーで記述します。

<?php echo form_input('name',  set_value('name', $data ? $data->id : ''), 'class="wrapper"' ) ?>

set_valueは、formのaction先でvalidation_ruleをセットして、validation->runをを走らせた際に、codeigniterが保持してくれる値です。validation->runで値の検証がエラーになった際に、検証した値を名前を指定して保存することができます。もちろんリクエスト毎ですよ。

form_checkbox

<?php echo form_checkbox('name', '1', $value ? $value == '1' : '', 'class="chk"') ?>

ひとまず、2つだけご紹介でした。 ちなみに、公式のサイトに各種ヘルパーの利用サンプルと解説が載っていますので、詳細はそちらを参考にしてください。

以上。