20190724のRailsに関する記事は11件です。

resourcesメソッド

本日、Railsのアプリ作成で便利なメソッドがあったので備忘録として。

resourcesメソッド
RESTfulな設計を実現するために開発者自身でHTTPメソッドとURLとアクションの紐付けを行うのは少々手間がかかります。
そこでresourcesメソッドの登場です。resourcesメソッドは上記の手間を省き、自動でRESTfulなルート定義を生成します。

routes.rbにresources :name(nameはリソース名:usersとか)と記述する事で
今までたくさん書いていた複数のルーティングを一括取得する事ができます。

参考
https://www.sejuku.net/blog/27728#resources

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

既存のRuby on RailsプロジェクトにJenkins と Docker で CIを導入する

要約

引き継いだプロジェクトなどで既存のRailsアプリにCIがない場合に、気軽にテストを書いてCIを回す文化を醸成したいと思って対応した内容の記録です。

対象読者

Railsのプロジェクトを運用している方で、引き継いだプロジェクトなど何からの事情によりテストを書く環境がない、または、CI環境を構築したいが、日本語の情報が少ない(自分がそうでした)ために構築に苦労している方に向けた記事です。

構成

Untitled Diagram.png

構築手順

1. ビルドマシンの準備

  • 適当なLinuxマシンを用意してください。
  • 今回の例ではCentos7を使用しています。

2. dockerインストール

3. docker-composeインストール

4. Jenkins(スタンドアロン版)のインストール

  • Jenkinsもdockerに閉じ込めたかったのですが、コンテナ上でdocker-compose の使用がうまく動かなかったため、今回はやむなくJenkinsだけは ビルドマシン上にwar配置という形をとりました。
# Jenkinsの起動スクリプト作成
$ mkdir ~/myjkdir
$ cd myjkdir
$ wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war .
$ cat <<EOT> start_jk.sh
JENKINS_JAVA_OPTIONS="-Xmx2048m -XX:MaxPermSize=512m -Dorg.jenkinsci.plugins.durabletask.BourneShellScript.LAUNCH_DIAGNOSTICS=true"
nohup java -jar jenkins.war &
EOT
$ chmod +x start_jk.sh
$ chown $USER:$USER start_jk.sh

5. Railsにビルド用の各種設定を行う

  • railsアプリをdockerにのせるための手順はこちらの通りで動作しました。
  • https://docs.docker.com/compose/rails/
  • ※ 後述していますが、この際、採用するイメージのミドルウェアのバージョンは実際に使用しているものに合わせるようにしましょう。コピペで進むとビルド出来ないなど後々不安定な挙動に悩むことになります。

6. ビルドマシンでdocker-composeのイメージビルド

# 適当なディレクトリに上記リポジトリをチェックアウトして、dockerイメージのビルド
cd /myapp_dir
# Checkout from SCM .
docker-compose build
docker images
# エラーなく、イメージがビルドできていることの確認
docker-compose up
# コンテナ起動確認
docker-compose run web bundle exec rake db:create

7. Jenkinsファイルの用意

pipeline {
  agent any
  stages {
    stage('build') {
      steps {
        sh 'echo "Hello World"'
       }
    }
    stage('test') {
      steps {
        sh 'docker-compose run web bundle exec rake db:create'
        sh 'docker-compose run web bundle exec rake db:schema:load'
        sh 'docker-compose run web bundle exec rake test test/**/*.rb'
      }
    }
  }
}

8. Jenkinsでビルドジョブ(pipeline)を作成し実行

  • 無事ビルド完了。 これで、テストを書いていけば自動テストが回りデグレの防止などコード品質向上に 寄与してくれることでしょう。 私も安心して眠れます。(テストを書いてから寝ろ)

はまったポイント

以下では、上記CI環境構築の間にハマったポイントを記載します。

1. 既存アプリのミドルウェアバージョンを良く確認しましょう。

  • レガシーなプロジェクトだと、使用しているソフトウェアのバージョンが古いこともあり、 公式等の記述コピペで進むとうまく動かない状況に陥ります。 docker imageに採用するタグ(バージョン)を良く確認しましょう。
  • ※ 例えばruby2.3とpostgres9.4の組み合わせのシステムの場合

    • Dockerfile
FROM ruby:2.3
...
  • docker-compose.yml
db:
 image: postgres:9.4
...

2. docker関連ファイルの改行コードはLFで統一

所感

テストが気軽にかける環境をローコストで手に入れることはソフトウェア品質向上に寄与すると思っています。Rails単体でも、かなり簡単にテストができる仕組みが入っていると思いますが、さらにDB回りやシステム全体のビルドテストとなると、Dockerみたいなアプリをパッケージにできる仕組みで手軽に作って捨てる環境を作りたいところですが、現状まだまだ設定が煩雑だったり日本語情報が少なかったりと、環境構築に障壁を感じました。少しでもこの記事が同じような境遇の方のお役に立てば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsでPostGISなカラムに値を入れる

TL;DR

PostGIS入れてactiverecord-postgis-adapter入れてgeometry型カラムを持つモデル作ったけどRailsでどうやって値入れるんだっけ?
→これでいけそう。

RGeo::Geographic.spherical_factory(srid: 4326).point(139.7003912, 35.6897376)

環境

mac OS X mojave
Ruby on Rails 5.2.3

検証

  • PostgreSQLをインストール(PostGISも)
$ brew install postgresql
$ brew install postgis
$ brew services postgresql start
  • Railsプロジェクトを立ち上げ、 activerecord-postgis-adapter gemを追加
$ rails new test_application
$ cd test_application
$ echo "gem 'activerecord-postgis-adapter'" >> Gemfile
$ bin/bundle
  • DBを初期化
$ bin/rails db:create
$ bin/rails db:gis:setup
  • モデルを作成
$ bin/rails g model Location name:string point:geometry #geometry型でモデルを作成
$ bin/rails db:migrate
Location.create(
  name: "新宿駅",
  point: RGeo::Geographic.spherical_factory(srid: 4326).point(139.7003912, 35.6897376)
)
  • DBに値が挿入されていることを確認
$ bin/rails c
irb(main):001:0> Location.all
=> #<ActiveRecord::Relation [#<Location id: 1, name: "新宿駅", point: #<RGeo::Cartesian::PointImpl:0x3fcd7929c4e0 "POINT (139.7003912 35.68973764)">>]>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

database名を変更したい時

database名を変更したい時

復習のためにアプリを何個も作成していると、同じ名前のデータベースを作成してしまってエラーになってしまうのを避ける方法。

terminal
Database 'sample1_development' already exists
Database 'sample1_test' already exists

データベースはconfig/database.ymlに基づいて作成されます。

そのため、この中の記述を変えてあげればいいのです。

database.yml
# MySQL.  Versions 4.1 and 5.0 are recommended.
#
# Install the MYSQL driver
#   gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
#   gem 'mysql2'
#
# And be sure to use new-style password hashing:
#   http://dev.mysql.com/doc/refman/5.0/en/old-client.html
development:
  adapter: mysql2
  encoding: utf8
  database: sample1_development
  pool: 5
  username: root
  password:

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  adapter: mysql2
  encoding: utf8
  database: sample1_test
  pool: 5
  username: root
  password:

production:
  adapter: mysql2
  encoding: utf8
  database: sample1_production
  pool: 5
  username: root
  password:

database:の後の

database: sample1_development

database: sample2_development

_testも同様に

変えてあげれば、rake db:createできます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】SNS認証で何もエラーを吐かずにリダイレクトされる件www

はじめに

Twitter認証、Facebook認証の実装をしていたところ突如としてFacebook認証だけが何もエラーを吐かずにリダイレクトされる現象についておそらく世界でただ一人僕だけが起こしたであろう(そんなわけない)エラーについての記録を残したいと思います。

ストーリー構成は以下になります。
原因だけ知りたい方は飛ばしてください。

①Twitter認証、Facebook認証の実装!ウェイ!
②あれ?いつのまにかFacebook認証だけできねえ!
③せや!Facebook認証できないし、Google認証代わりにつけたろ!
④Facebook認証もGoogle認証もできない?
⑤色々いじってたらTwitter認証も同じ現象に??
⑥原因

①Twitter認証、Facebook認証の実装

以下を参考にしました
https://freesworder.net/rails-facebook/
https://freesworder.net/rails-twitter/

②あれ?いつのまにかFacebook認証だけできねえ!

facebook側の設定とコードを何度確かめてもわからない。
Twitterはログインできたのでコードに間違いがあるわけないと思っていた愚か者。

③せや!Facebook認証できないし、Google認証代わりにつけたろ!

以下を参考にしました。
https://qiita.com/kazuooooo/items/47e7d426cbb33355590e#google
https://qiita.com/bino98/items/596b5cffeca7c104bd90

④Facebook認証もGoogle認証もできない?

ここで一度、設定側を疑ったがそもそもそんなに設定することもないためやはりコードに間違いがあるのではないかということにやっと気づく。そしてやっとコンソールを触りだした愚か者である。

ここにbinding.pryを挟んでSNS認証をする際に作成されるuserの中身をtwitterとそれ以外で比較することに。

user.rb
  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

    unless user
      user = User.create(
        uid:      auth.uid,
        provider: auth.provider,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20],
        user_name: auth.info.nickname,
      )
    end
    binding.pry
    user
  end
 
twitter
[1] pry(User)> user
=> #<User id: 48, email: "751654649833279488-twitter@example.com", created_at: "2019-07-24 06:47:32", updated_at: "2019-07-24 06:47:32", uid: "751654649833279488", provider: "twitter", user_name: "hataponnu">
facebook
[1] pry(User)> user
=> #<User id: nil, email: "802531940128861-facebook@example.com", created_at: nil, updated_at: nil, uid: "802531940128861", provider: "facebook", user_name: nil>
google
[1] pry(User)> user
=> #<User id: nil, email: "112060568058062888716-google_oauth2@example.com", created_at: nil, updated_at: nil, uid: "112060568058062888716", provider: "google_oauth2", user_name: nil>

うーん、facebookとgoogleはuser_nameがnilになってるなあ。。。(ここではまだ原因に気づいてない模様)

ということでnicknameではなくnameを取得するように修正してみた。

user.rb

  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

    unless user
      user = User.create(
        uid:      auth.uid,
        provider: auth.provider,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20],
        user_name: auth.info.name, #←ここ
      )
    end
    binding.pry
    user
  end

お!ちゃんととれてる!! でもまだ治らない?

google
[1] pry(User)> user
=> #<User id: nil, email: "112060568058062888716-google_oauth2@example.com", created_at: nil, updated_at: nil, uid: "112060568058062888716", provider: "google_oauth2", user_name: "hiroki hatakeda">

⑤Twitter認証も同じ現象に??

なんとこの修正を加えたことによりTwitterログインができなくなりました。ということで中身を見てみることに。

twitter
[1] pry(User)> user
\=> #<User id: nil, email: "751654649833279488-twitter@example.com", created_at: nil, updated_at: nil, uid: "751654649833279488", provider: "twitter", user_name: "hatakeda hiroki">

ここで気づいてしまったんです。

⑥原因

user_nameカラムにこんなバリデーションはってました。???
・nilを許可しない
・半角英数字のみ
・20文字以内

user.rb
  validates :user_name, presence: true, length: { maximum: 20 }, uniqueness: { case_sensitive: false }, format: { with: /\A[a-z0-9]+\z/i, message: "英数字以外の文字は使用できません" }

どうやらfacebookとgoogleではuser_nameがnilになっていたのと
不要なスペースがあることで半角英数字のみというバリデーションに引っかかっていたようですね。

ということでSNS認証でユーザーが作成される際、
user_nameカラムで許可している英数字だけでランダムで設定することにして解決。

user.rb
 def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

    unless user
      user = User.create(
        uid:      auth.uid,
        provider: auth.provider,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20],
        user_name: User.rondom_name,    #←ここ
      )
    end
    user
  end

   private
    def self.dummy_email(auth)
      "#{auth.uid}-#{auth.provider}@example.com"
    end

    def self.rondom_name  #←と、これ
      "#{((0..9).to_a + ("a".."z").to_a).sample(10).join}"
    end

プログラミングむず過ぎワロタァ!?

SNS認証でエラー吐かずにリダイレクトされたらバリデーションを疑ってみましょう?

結論

コンソールで確かめるの大切。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

参考リンク: RailsでViewを扱う方法

[Rein: RailsのActiveRecordでDB制約やデータベースビューを使えるgem(README翻訳)]https://techracho.bpsinc.jp/hachi8833/2017_09_11/45365

MySQLで利用できるかどうかなど未調査

※ 追記
ViewのCreateとApplicationRecordの利用はMySQLでも大丈夫でした

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6 のちょい足しな新機能を試す58(ActiveRecord::Errors#of_kind?編)

はじめに

Rails 6 に追加されそうな新機能を試す第58段。 今回は、 ActiveRecord::Errors#of_kind? 編です。
Rails 6 に ActiveRecord::Errors#of_kind? メソッドが追加されました。

Ruby 2.6.3, Rails 6.0.0.rc1, PostgreSQL 10.7 で確認しました。Rails 6.0.0.rc1 は gem install rails --prerelease でインストールできます。

$ rails --version
Rails 6.0.0.rc1

User モデルを作る

User モデルを作ります

$ bin/rails g model User name

User モデルを修正する

validation を追加します。

app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
end

rails console で確認する

rails console を実行して確認します。

irb(main):001:0> user = User.new
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.validate
=> false
irb(main):003:0> user.errors.of_kind?(:name)
=> false
irb(main):004:0> user.errors.of_kind?(:name, :blank)
=> true
irb(main):005:0> user.errors.of_kind?(:name, "can't be blank")
=> true
irb(main):006:0> user.errors.of_kind?(:name, :presence)
=> false

試したソース

試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try058_errors_of_kind

参考情報

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

simple_formのcollection_radio_buttonsのinclude_hiddenオプション

simple_formのcollection_radio_buttonsで詰まったところがあったので記載。

環境

Rails 5.2.2
simple_form 4.1.0

詰まった時の状況

特定のレコードの状態の時に collection_radio_buttons で生成したradio buttonをdisableにしていた。
対象のカラムはint(modelでenum指定)でnot null

collection_radio_buttons で生成する際に

<input type="hidden" name="model_name[column_name]" value="">

も一緒に生成され、対応するカラムのparamがblankでpostされてしまった。

対応

include_hidden: false をオプションとして渡す

<%= f.collection_radio_buttons :column_name, ~~, include_hidden: false %>

Readme等に記載見当たらずなかなかたどり着けなかった。。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

macOS Mojave で RMagick gem を使う 2019年7月編

macOS を Mojave にアップグレードしたら bundle install で RMagick が入らないよ!
またかよ。
(OS アップグレードのたびに起きるあれの解決策。)

前提環境

$ cc を実行して command not found だったら、Xcode commndline をインストールする。
$ xcode-select --install

原因

Homebrew で ImageMagick v.7 が入ったのが原因。RMagick は v.7 非対応。(2019-07現在)
https://github.com/rmagick/rmagick/issues/256

$ brew uninstall imagemagick
$ brew install imagemagick@6
$ brew link imagemagick@6
$ gem install rmagick # (または bundle install)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

create,editのSQL文が発行されないだ!

Started GET "/admin/posts/new?utf8=%E2%9C%93&authenticity_token=ml6gSUnqTKTuGQKPd9ZWFdDr8ODFm%2Bx2IuNwOcy%2Fpv%2BbpthhN0OxPRWD3YSGP6LeTSbPfYljLG09WtyO7dQWug%3D%3D&post%5Btitle%5D=fa&post%5Bcontent%5D=fa&post%5Bpost_date%5D=2019-07-17&commit=%E6%8A%95%E7%A8%BF" for ::1 at 2019-07-23 09:06:42 +0900
Processing by Admin::PostsController#new as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"ml6gSUnqTKTuGQKPd9ZWFdDr8ODFm+x2IuNwOcy/pv+bpthhN0OxPRWD3YSGP6LeTSbPfYljLG09WtyO7dQWug==", "post"=>{"title"=>"fa", "content"=>"fa", "post_date"=>"2019-07-17"}, "commit"=>"投稿"}
  Rendering admin/posts/new.html.erb within layouts/application
  Rendered admin/posts/_form.html.erb (2.9ms)
  Rendered admin/posts/new.html.erb within layouts/application (6.8ms)
Completed 200 OK in 88ms (Views: 85.7ms | ActiveRecord: 0.0ms)

まず、Started GETのURLがおかしいっていうかGETじゃなくてPOSTになるべき

そして、Processing by [コントローラ名#メソッド名] as HTMLは処理が行われたコントローラとメソッド名と取得した形式を示している
参考:ログの見方

createいってないやんん
なのでbinding.pryも使えず、、、、

本来こうゆうログが出て欲しかった

Started POST "/admin/posts" for ::1 at 2019-07-24 08:02:25 +0900
Processing by Admin::PostsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"ugtj2S2144qyRefhnBdSOIxtphgJth7Yp7EERh2xPe5zTvaUoJOQzqjKOq9AGi6thh4MvwTmL5sJa31oXpG1dg==", "post"=>{"title"=>"fa", "content"=>"fa", "post_date"=>"2019-07-10"}, "commit"=>"投稿"}
  User Load (0.4ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 4 LIMIT 1
  ↳ app/controllers/application_controller.rb:5
   (1.7ms)  BEGIN
  ↳ app/controllers/admin/posts_controller.rb:17
  CACHE User Load (0.0ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 4 LIMIT 1  [["id", 4], ["LIMIT", 1]]
  ↳ app/controllers/admin/posts_controller.rb:17
  Post Create (0.3ms)  INSERT INTO `posts` (`title`, `content`, `post_date`, `user_id`, `created_at`, `updated_at`) VALUES ('fa', 'a', '2019-07-10 00:00:00', 4, '2019-07-23 23:02:25', '2019-07-23 23:02:25')
  ↳ app/controllers/admin/posts_controller.rb:17
   (1.0ms)  COMMIT
  ↳ app/controllers/admin/posts_controller.rb:17
Redirected to http://localhost:3000/admin/posts

状況をみていく

こんなコントローラを書いた
いたって正常だ

posts_controller.rb
class Admin::PostsController < ApplicationController
  before_action :require_user
  before_action :set_post, :only => [:show, :edit, :update, :destroy]

  def index
    @posts = Post.all
  end

  def new
    @post = Post.new
  end

  def create
    @post = Post.new(post_params)
    unless @post.valid?
      @post.user_id = current_user.id
      @post.save
      redirect_to admin_posts_path, :notice => '記事を登録しました。'
    else
      render :action => "new" 
    end
  end

  def show
  end
  def edit
  end

  def update
    if @post.update_attributes(post_params)
      redirect_to admin_posts_path, :notice => '記事を更新しました。'
    else
      render :action => "edit"
    end    
  end

  def destroy
    @post.delete
    redirect_to admin_posts_path
  end

  private
  def post_params
    params.require(:post).permit(:title, :content, :post_date, :user_id)
  end

  def set_post
    @post = Post.find(params[:id])
  end
end

こんなviewをかいた
form_withの使い方に自信がなかったのでそこが違うのかとurlをパスにしたりform_tagに変えてみたりしてみたが違ったようだ

new.html.erb
<%= form_with model: [:admin, @post], :url => { :action => 'create' }, local: true  do |f| %>
  <div class="form-group">
    <%= f.label :title, '投稿タイトル' ,:class => "label-s"%>
    <%= f.text_field :title, class: 'form-control' %>
  </div>
  <div class="form-group">
    <%= f.label :content, '投稿内容' %>
    <%= f.text_area :content, class: 'form-control', rows:10 %>
  </div>
  <div class="form-group">
    <div class="input-group date" id="datetimepicker1">
      <%= f.label :post_date, '日付', for: "datetimepicker1", class: "pt-2 pr-2"%>
      <%= f.date_field :post_date, class: 'form-control' %>
    </div>
  </div>

  <%= f.submit '投稿', class: 'btn btn-info btn-block mt-5' %>
<% end %>

原因は、layoutファイルapplication.html.erbに書いていたyeildを囲む部分の記述だ

application.html.erb
    <div class ="justify-content-container-fuluid mt-5 mb-5">
      <div class="container text-center">
        <div class = "col-md-7 container"> #form class
          <%= yield %>
        </div> #/form
      </div>
    </div>

ここの部分がformタグ担っていたのが原因だ。

久しぶりにbootstrapを使って引っかかったところでした。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

アイデア共有サービスを作った話

本日、人生で初めてシッカリ目に作ったのでWebアプリを公開したので、それについて書きます。
実はまだ、自分の実装したい機能全てを実装できてるわけではないのですが、取り敢えず一段落着いたので記事を書きました!

『〇〇作った』系の記事はよく見ますが、いざ自分が書くとなるとどう書いて良いのか分からないものですね・・・

筆者情報

21歳。今日から就活を始めたプー太郎です。
Ruby on Railsを勉強し始めて、はや1年半が経過しました。
10ヶ月ほどフロントエンドと、Python3ヶ月、C#3ヶ月ほどの薄っすらな実務経験(というレベルでもないけど)有り

前社でのパワハラを受け退職、半年ほど自転車で日本一周をしていました。
前社勤務時の成果物はなにも残せていなかったので、就活に向けて何かサービスを作ることにしました。

他のサービスとの差別化

企業が運営するアイデア投稿サービス

日本でアイデア投稿サービスというと、実は知られてはいないですがたくさんあります。
企業さんが運営するアイデア投稿サービスだと、ideastationWemakeなどなど
ただ、企業さんが募集してユーザーが投稿する形だと、

  • 限られた範囲でしか新しいものが生まれない
  • 気軽に思いついたアイデアを投稿することができない
  • コンペ形式でアイデアが消費される個人的な嫌悪感

を感じていました。

個人が運営するアイデア投稿サービス

では、個人が気軽に投稿できるサービスは何があるかというと、HIRAMEKI CAFEというサービスがあります。
(他にある場合は、コメントを頂けると幸いです)

こちらは個人開発のwebサービスで、私の理想とするサービスにとても近いものでした。
ただ、このサービスも以下の点で、私の要望にマッチしていませんでした。

  • Web/ネイティブアプリ系アイデアの投稿しか出来ない
  • アイデアを投稿することで完結しており、実現にコミットできない
  • イベントなどが行われておらず、コミュニティが活発でない

最終目標

なので、私が目指す形としては『アイデアの実現』に重きをおいたサービスとしました。
色々なサービスを比較した結果

  • 個人が個人に向けてアイデアを共有できる
  • ジャンルに関係なくアイデアを投稿できる
  • アイデアに対しては拍手を送れるようにする(アイデアに対する要望度をパラメータ化したい)
  • 気軽に利用できるように、各SNSでのOAuth認証を実装する
  • 検索・タグ付け機能を実装したい
  • 実現したアイデア・してないアイデアにステータスを付与して視覚的に目立たせたい

な感じで行こうかな、と考えました。

また、上記のサービスを作る上での課題は

  • コミュニティを活発に保つ仕組みづくり
  • ユーザーが自発的にアイデアを実現させられるような道作り

でした。

技術 7/24現在

gem

  • gem 'rails', '~> 5.2.3'
  • gem 'pg', '>= 0.18', '< 2.0'
  • gem 'puma', '~> 3.11'
  • gem 'sass-rails', '~> 5.0'
  • gem 'uglifier', '>= 1.3.0'
  • gem 'mini_racer', platforms: :ruby
  • gem 'turbolinks', '~> 5'
  • gem 'jbuilder', '~> 2.5'
  • gem 'bootsnap', '>= 1.1.0', require: false
  • gem "jquery-rails"
  • gem "kaminari"
  • gem "rails-i18n"
  • gem 'rinku'
  • gem 'omniauth'
  • gem 'omniauth-github'
  • gem 'omniauth-twitter'
  • gem 'omniauth-facebook'
  • gem 'meta-tags'

開発期間を1周間としたので、なるべく楽に作れるようにしました。

データベース

erd.png
拍手はuser_idとidea_idを持ったapplauseテーブルを作りました。
後々、どのアイデアに誰がいくつ押したかのデータを使いたかったので、applauseテーブルにcountカラムを用意しました。
拍手機能を実装してる方のTipsがなかったのですが、大体みんなこんな感じですよね・・・?

ちょっとした工夫

特定のタグは用意しなかった

ユーザーに自分の投稿したアイデアのタグを決めてもらうようにしました。
タグ自体は

"web, site, app, phone"

のようなカンマ区切りで受取り、以下の処理で整形、保存しています。

idea.rb
  def prepare_tag
    text = read_attribute(:tag)
    # 必要以上のスペースとタグ、コロンとダブルコロンを削除
    tag = text.gsub(/^,+|[[:blank:]]|\"|\'|,+$/, "").split(',').reject{|v| v.empty?}.uniq.join(',')
    write_attribute(:tag, tag)
  end

カンマでさえ区切って保存すれば、後はsplit(",")で配列化して色々使用できました。
FireShot Capture 044 - テスト1 - Mecha Better - localhost.png
こんな感じ。

実際の開発現場でもタグ付け機能はこのような手法で実装しているのでしょうか?
他にいい方法があるのかしら?

アイデアのステータス毎に色を変えた

アイデア実現に重きをおきたいので、すぐに視覚でアイデア毎の状態が分かるようにしました。
div_color.png
title.png

OAuth認証はTwitter/Facebook/Github

Githubの認証は需要が少なそうでしたが、諸々の設定が簡単そうだったのと、Githubが好きなので追加しました。
OAuth処理に関するコードはごくごく短くすみました

config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
    provider :github, Rails.application.credentials[Rails.env.to_sym][:github][:key], Rails.application.credentials[Rails.env.to_sym][:github][:secret], scope: "user,repo"
    provider :twitter, Rails.application.credentials[Rails.env.to_sym][:twitter][:key], Rails.application.credentials[Rails.env.to_sym][:twitter][:secret]
    provider :facebook, Rails.application.credentials[Rails.env.to_sym][:facebook][:key], Rails.application.credentials[Rails.env.to_sym][:facebook][:secret]
end
models/user.rb
    def self.find_or_create_from_auth(auth)
        email = auth[:info][:email]
        provider = auth[:provider]
        uid = auth[:uid]
        icon = auth[:info][:image]
        oauth_token = auth[:credentials][:token]
        case provider
        when "facebook" then
            name = auth[:info][:name]
        when "github", "twitter" then
            name = auth[:info][:nickname]
        end

        self.find_or_create_by(provider: provider, uid: uid) do |user|
            user.email = email
            user.name = name
            user.icon = icon
            user.provider = provider
            user.uid = uid
            user.oauth_token = oauth_token
        end
    end

APIのIDやらは環境変数で対応することが多いみたい?ですが、Credentialsが楽チンでとても良かったですな!

credentials.yml.env
development:
  github: 
    key: xxxxxxxxxxxxxx
    secret: XXXXXXXXXXXXXXXXXX

こんな感じです。
Credentialsは正直 "rails-env-credentials" なるGemを使った方がスマートに書けたなぁっと、たった今後悔してます・・・

(未)完成サービス

こちらになります。
Mecha Better
top.png

ある程度人に見せられる見た目になったので公開しましたが、今の時点では単にアイデアの投稿サイトなのです・・・
やはり『実現することに重きをおいた』サービス作りは念頭にあるので、今後実装予定の機能として

  • アイデアに対して、実現したい人(グループ可)が立候補できる
  • 開発者用ルームを作り、ルーム内でタスク登録や進捗の管理が出来るようにする

という感じで、タスク管理のプラットフォームも兼ねたサービスになれば、『実現することに重きをおいた』サービスと言えるかな、と思っています。
ただ、同一サービス内に専門性の高い機能を実装すると、気軽にアイデアを投稿したい層からすれば敷居が高いように感じる可能性はあります。

この辺りは、まだまだ色々な角度から考える必要がありそうです。

さいごに

Ruby on Railsを勉強し始めて2年半ですが、正直今まで紆余曲折あったとはいえ、もうちょっと成長しておくべきでした・・・
今こうしてみると、大したことも機能もないし、デザインもイマイチ・・・
日々精進して行かねば!

ただ、この1週間サービスの開発を通して、多少なりともスキルが向上したようにも感じています。
せっかくですから、なんとかこのサービスのユーザを増やしていきたいですね。

それと、大阪で働き口を探さねばなりません。
どなかた、僕を雇ってくださいまし。。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む