20210425のRubyに関する記事は16件です。

Atcoder 緑になりました

はじめに 桜も散り若葉が輝く季節、皆様いかがお過ごしでしょうか。 この度、緑コーダーになりましたのでご報告いたします。 道のり 2019-09-28から2021-04-25まで574日間、いやあ本当に才能がないですね。 ここまで時間が掛かったのは、茶埋めにこだわり過ぎて、緑や水色Diffをやらなかったことと反省しています。 しかし、2020-03に茶コーダーになったときはまだPerlでプログラミングしていたわけで、そこからRubyに転向し2020-05にRuby 技術者認定試験 Silver に合格しましたしたり、2020-11にRuby 技術者認定試験 Gold に合格しましたしたりとサボっていたわけではないです。 ただし、木構造とかいまだ苦手ですし、ABCの下位ではあまり出題されない動的計画法にやたらと凝ったり(Ruby で解く AtCoder ABC 128 C 動的計画法/Ruby で解く AtCoder ABC057 C 動的計画法/Ruby と Python で解く AtCoder ABC178 D 動的計画法/Ruby と Perl と Java で解く AtCoder ABC 129 C (後編) 動的計画法/Ruby と Python で解く AtCoder ABC011 C 動的計画法/Ruby と Python で解く AtCoder ABC153 E 動的計画法/Ruby で解く AtCoder Educational DP Contest D ナップサック問題/Ruby で解く AtCoder Educational DP Contest E ナップサック問題)、効率の悪いこともしています。 まとめ AtCoderさん ありがとうございます AtCoder Problemsさん ありがとうございます 百折不撓 やり方は何通りでもある プログラミングを楽しもう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PyCall を使って Ruby でハートを描く その 2

はじめに 以前 PyCall を使って Ruby でハートを描く という記事を書きました。それから約 4 年後、久しぶりに PyCall を触ってみました。今度は 3D のハートを描画してみようと思います ❤️ PyCall について PyCall は Ruby から Python のコードを呼び出すことができる、mrkn (Kenta Murata) さんが作成されている Gem です。この mrkn さんは numpy.rb や matplotlib.rb など、Python で非常に有名なライブラリのラッパーライブラリも作成してくれています。今回はそれらも使用します。 バージョン情報 $ ruby -v ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin20] $ gem list | grep -e "pycall" -e "numpy" -e "matplotlib" matplotlib (1.1.0) numpy (0.2.0) pycall (1.3.1) $ python --version Python 3.9.2 $ pip list | grep -e "numpy" -e "matplotlib" matplotlib 3.4.1 numpy 1.20.2 コード Stack Overflow の how to draw a heart with pylab という記事に記載されている Python のコードを Ruby に書き換えました。 require 'matplotlib/pyplot' require 'numpy' Axes3D = PyCall.import_module('mpl_toolkits.mplot3d').Axes3D def calculate_3d_heart(x, y, z) (x**2 + (9.0 / 4) * y**2 + z**2 - 1)**3 - x**2 * z**3 - (9.0 / 80) * y**2 * z**3 end def plot_3d_heart xmin, xmax, ymin, ymax, zmin, zmax = [-1.5, 1.5] * 3 fig = Matplotlib::Pyplot.figure ax = fig.add_subplot(111, projection: '3d') a = Numpy.linspace(xmin, xmax, 100) b = Numpy.linspace(xmin, xmax, 40) a1, a2 = Numpy.meshgrid(a, a) # numpy.ndarray は each や to_a ができないので index で値にアクセスする。 b.size.times do |i| x = a1 y = a2 z1 = b[i] z2 = calculate_3d_heart(x, y, z1) ax.contour(x, y, z1 + z2, [z1], zdir: 'z', colors: ['red']) end b.size.times do |i| x = a1 z = a2 y1 = b[i] y2 = calculate_3d_heart(x, y1, z) ax.contour(x, y1 + y2, z, [y1], zdir: 'y', colors: ['red']) end b.size.times do |i| y = a1 z = a2 x1 = b[i] x2 = calculate_3d_heart(x1, y, z) ax.contour(x1 + x2, y, z, [x1], zdir: 'x', colors: ['red']) end ax.set_zlim3d(zmin, zmax) ax.set_xlim3d(xmin, xmax) ax.set_ylim3d(ymin, ymax) Matplotlib::Pyplot.show end plot_3d_heart 上記の Ruby スクリプトを実行すると Tk のウィンドウが開きます。 若干血しぶきが飛び散っているのはご愛嬌 ? ちょっとした悩み Python ではスカラー値を x、ベクトル値を X のように変数名の大文字と小文字を使い分けているが、Ruby ではどうすればいいのでしょう ? Ruby だと大文字は定数と判断されるためです。 参考 mrkn/pycall.rb: Calling Python functions from the Ruby language mrkn/numpy.rb: Numpy wrapper for Ruby mrkn/matplotlib.rb: matplotlib wrapper for Ruby numpy.ndarray — NumPy v1.20 Manual mpl_toolkits.mplot3d.axes3d.Axes3D — Matplotlib 3.4.1 documentation
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[初学者メモ]Rubyの%記法で文字列を表す

はじめに この記事はプログラミング初学者である私の学習用記事です。 Qiitaでの投稿とMarkdown記法の練習、アウトプットを目的としています。 内容としては大したものではないためあしからず。 Rubyの%記法を使う理由 %を使用することでコードをすっきりさせることができます。 文字列を%記法で書く まず、%記法は文字列を表す際に使われます。 文字列の中で " や ’ を使用する場合は、バックスラッシュによるエスケープが不要になり見やすくなります。 %Q ""(ダブルクォーテーション)と同様に使えます。 Qは省略することが可能。 ダブルクォーテーションと同等のため、変数や定数の展開もできます。 %Q puts %Q(Rubyを学習中です。) # => Rubyを学習中です。 puts %(Rubyを学習中です。) # => Rubyを学習中です。 languages = "Ruby" puts %(#{languages}を学習中です。) # => Rubyを学習中です。 %q ''(シングルクォーテーション)と同様に使えます。 定数や変数の展開はできません。 %q puts %q(Rubyを学習中です。) # => Rubyを学習中です。 %W 式が展開できる(ダブルクォーテーションの機能をもつ)配列を表します。 %W favorite_food = curry p %W(#{favorite_food} stew) # => ["curry", "stew"] %w 式を展開しない(シングルクォーテーションの機能をもつ)配列を表します。 %W favorite_food = curry p %w(curry stew) # => ["curry", "stew"] 参考元 学習にはドットインストールさんを使用させて頂いてます。 以下の記事も参考にさせて頂きました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】ハッシュに関する式展開

はじめに この記事は、Ruby/Railsの学習期間約1ヶ月の著者が書きました。 初投稿となりますので、誤った解釈があるかもしれません。 その場合は、コメント等頂けますと幸いです。 環境 この記事ではmacOS Big Sur 11.2.3にインストールしたRuby:2.7.2を使っています。 式展開の基本 #{}を用いることにより、文字列内に変数や式の中身を展開することができます。 以下が例になります。 name = "山田" puts "私の名前は#{name}です。" こちらを実行すると 私の名前は山田です。 と表示され、変数nameの中身を展開していることが分かります。 ハッシュの式展開 では、以下のようなハッシュがあるとします。 (今回ハッシュの説明は省略します) user = { name: "山田", age: 25 } ハッシュから情報を取り出して以下の通り出力させることを考えましょう。 私の名前は山田です。年齢は25歳です。 式展開を利用し、以下の2行目のコードを追加します。 hash_expansion.rb user = { name: "山田", age: 25 } puts "私の名前は#{name}です。年齢は#{age}歳です。" 実行すると以下のようなエラーが出ました。 undefined local variable or method `name' for main:Object (NameError) 変数nameが定義されていないようです。 nameはハッシュのキーであるため、今回のような場合は#{name}と書いてもnameに対する値(バリュー)を取り出せません。 ハッシュのデータの取り出し方 では、どのようにハッシュのデータを式展開で取り出せばよいか。 さて、ここでハッシュのデータの取り出し方を確認しましょう。 user = { name: "山田", age: 25 } puts user[:name] puts user[:age] 出力結果は以下となります。 山田 25 このように、ハッシュの値は変数[:キー]の形で取り出すことができます。 ではこの形に式展開を用いるのを考えてみましょう。 #{}に変数[:キー]を入れて先ほどのコードを修正します。 hash_expansion.rb user = { name: "山田", age: 25 } puts "私の名前は#{user[:name]}です。年齢は#{user[:age]}歳です。" 果たして結果は... 私の名前は山田です。年齢は25歳です。 無事にハッシュ内の「名前」と「年齢」を式展開#{変数[:キー]}を用いて出力することができました! まとめ 式展開はハッシュ内の値に対しても利用できることを説明しました。 このような式展開の方法もあるのだと知っていただければ幸いです。 今後もRuby/Railsを学習する過程で、有益な情報を発信できればと思いますので、良ければLGTMお願いします!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu 20.04.1 LTS上にRuby3.0.0とRails6

Ubuntu 20.04.1 LTS Ruby 3.0.0 Rails 6.1.0 現在の環境にインストールします sudo apt update -y sudo apt upgrade -y 開発に必須のパッケージとRuby on Railsで必要なパッケージをインストール sudo apt-get -y install git curl g++ make libyaml-dev libxml2-dev libxslt-dev sqlite3 libsqlite3-dev nodejs npm sudo apt install build-essential -y sudo apt install -y libssl-dev libreadline-dev zlib1g-dev git clone https://github.com/sstephenson/rbenv.git ~/.rbenv 環境変数Pathを設定します。 echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc echo 'eval "$(rbenv init -)"' >> ~/.bashrc シェルを再起動します。 exec $SHELL -l ruby-buildをインストールします。 git clone https://github.com/sstephenson/ruby-build.git~/.rbenv/plugins/ruby-build Rubyをインストール rbenv install 3.0.0 rbenv global 3.0.0 yarnのインストール sudo apt install curl Railsのインストール gem install -v 6.1.0 rails
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

deviseを使った複数モデルログイン実現後の他のモデルの扱い

記事の目的 railsのgemであるdeviseはユーザー登録機能を実現するために使用されている最もポピュラーなライブラリの一つかと思いますが、 アプリケーションを作成する上で複数モデルログインをしたいと考える場合もあるかと思います。 (よく見るのは管理者と一般ユーザーを切り分けるタイプのものですかね。) 今回はdeviseを活用した複数モデルログインを実現した後、他のモデルをどのように紐付けていくのかをまとめました。 本論 複数モデルログイン この記事は複数モデルログインの機能自体は実現した前提での内容となります。 複数モデルログイン機能の構築には、勝手に引用してしまい恐縮ですが、良記事がございますので下記ご参考いただければ。 http://freecamp.life/rails-devise-admin1/ 筆者のケース 私は現在日本にいる外国人が日本でチューターを探すためのマッチングアプリのようなものを作っています。 そのため「外国人」と「チューター」としての会員登録、ログイン機能をつけています。 なのでコントローラーの構成は app |- controller |- foreigner #(外国人) |- tutor #(チューター) となっており、ルーティングは devise_for :foreigners, skip: :all devise_scope :foreigner do get 'foreigners/sign_in' => 'foreigners/sessions#new', as: 'new_foreigner_session' post 'foreigners/sign_in' => 'foreigners/sessions#create', as: 'foreigner_session' delete 'foreigners/sign_out' => 'foreigners/sessions#destroy', as: 'destroy_foreigner_session' get 'foreigners/sign_up' => 'foreigners/registrations#new', as: 'new_foreigner_registration' post 'foreigners' => 'foreigners/registrations#create', as: 'foreigner_registration' get 'foreigners/password/new' => 'foreigners/passwords#new', as: 'new_foreigner_password' end devise_for :tutors, skip: :all devise_scope :tutor do get 'tutors/sign_in' => 'tutors/sessions#new', as: 'new_tutor_session' post 'tutors/sign_in' => 'tutors/sessions#create', as: 'tutor_session' delete 'tutors/sign_out' => 'tutors/sessions#destroy', as: 'destroy_tutor_session' get 'tutors/sign_up' => 'tutors/registrations#new', as: 'new_tutor_registration' post 'tutors' => 'tutors/registrations#create', as: 'tutor_registration' get 'tutors/password/new' => 'tutors/passwords#new', as: 'new_tutor_password' end となっております。 別のモデルの追加 ここからは別のモデルを追加する方法について説明していきます。 今回は、外国人登録したユーザーが、チューターとのマッチング希望を出すためのモデルを作成していきます。 モデル作成 ここではneedモデルというものを作成します。 モデルの作成は特段代わりはなく、 rails g model need でOKです。 その後のマイグレーションファイルやモデルファイルのバリデーション/アソシエーション等の設定も普通通り行っていきます。 コントローラー作成 さてここからが本題です。 今回はforeignerに紐づくモデルだったので、コントローラーはforeignerコントローラーフォルダの中に作成していきます。 下記の通りコマンドを打ち込んでください。 rails g controller foreigners/needs するとapp/controller/foreignersの下にneeds_controller.rbが作成されるかと思います。 ファイルの中身はこんな感じで作成されるはずです。Foreignersの中のNeedsControllerという内容になっていますね。 class Foreigners::NeedsController < ApplicationController (略) end ルーティング 続いてルーティングです。 ルーティングに関してはforeignerの名前空間の中で設定していきたいので、 (略) namespace :foreigners do resources :needs end を追記します。 こうすることでdeviseを活用した複数モデルログイン機能と、それに紐づいたモデルの設定が完了です。 あとはアクションなりviewの設定をよしなにやっていけばOKです! ※viewもapp/views/foreignersの下にneedsディレクトリが生成されているので、そこにファイルを作成していきましょう。 ご指摘等ございましたらコメント頂けると幸いです!!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]kaminariでページネーション機能を作る

はじめに 最近、ページネーション機能を実装したので、本記事に簡単にまとめます。 ページネーション機能 ページネーションとは、内容の多いページを複数のWebページに分割し、各ページへのリンクを並べてアクセスしやすくするために設置するものです。よく比較されるものとして、無限スクロールがありますが、どちらを実装するかは各々のメリットデメリットをよく理解してから実装するのが良いかと思われます。場合によっては、実装することがマイナスとなりうるためです。(例えば、チャット画面でページネーション 機能があると切り替えが面倒ですよね) 実装 実装方法は簡単で、kaminariというgemを使用します。 gem `kaminari` ※bundle install忘れないように!!! 次にコントローラを実装します。 controller.rb class HomeController < ApplicationController def index @posts = Post.all @posts = Post.page(params[:page]).per(20) end end per()については、何投稿ごとにページを切り替えるか指定しています。 あとは、ビューに以下を設置します。   index.html.erb <%= paginate @posts %> 極論、これで完成です。めちゃくちゃ簡単ですね。 とはいえ、細かい設定したいですよね。 そうした場合は以下のコマンドを叩いてください。 rails g kaminari:config そうすると、以下のような設定ファイルが生成されます。 コメントアウトを外して、変えたい部分を変えてください Kaminari.configure do |config| # config.default_per_page = 25 # 1ページ辺りの項目数 # config.max_per_page = nil # 1ページ辺りの最大数 # config.window = 4 # ex 値が2の場合 .. 2 3 (4) 5 6 .. # config.outer_window = 0 # ex 値が2の場合 .. (4) .. 99 100 # config.left = 0 # ...になったときの左側の表示数 # config.right = 0 # ...になったときの右側の表示数 # config.page_method_name = :page # メソッド名 # config.param_name = :page # ページネーションのパラメーターの名前 end あと、個人的に次へボタンを消したいなと思ったのですが、これはビューファイルごと消してやるといいかと思います。 その場合は、以下のコマンドを叩いてビューファイルを生成します。 rails g kaminari:views default なお、bootstrapをkaminariに適用する場合は以下のようにします rails g kaminari:views bootstrap3 あとは、個人でCSSを当ててもらえれば、それらしきものができるかと思います。 おわりに ざっくりとkaminariのまとめをしました。個人的には簡単で嬉しいものの、やっぱり作った感がなくて、、、、なので一から自分で作ってみようかな〜なんて考えています。 みなさんも是非試してみてはいかがでしょうか
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

form_withでのmodelとurlの指定の違いはSr?

はじめに form_withを使用中に気になったので調べてまとめてみました。 目次 urlの指定 modelの指定 modelとurlの指定の違い まとめ 参考 urlの指定 urlの書き方 form_with url: url_path 例) <%= f.text_field :emai%> <%= f.submit %> urlでは指定したurlに対してPOSTメソッドを行う。 :scope scope指定すると「指定すると現在のURLに対応したメソッドにフォームを送信」してくれる つまり、loinフォームを作成していてsessionControllerを使っている場合はsessionControllerのnewメソッドに送信してくれることになる ストロングパラメーターの設定 params.permit(:email) urlの場合は構造階層を意識することなくストロングパラメーターを設定できる。 modeleの指定 modelの書き方 form_with model: @model 新しく作られたオブジェクトの場合 例) user = User.new controller間の処理の流れ new => create この場合は渡されたオブジェクトの値が空の場合Rallsが自動でcreateメソッドを呼び出してくれる。 ストロングパラメーターの値指定 urlを指定して値を渡した場合は直接値を指定しできたが moelの場合は構造階層になるので指定方法が変わる 「Userモデルのemailを指定する」といった形に切り替える params.requitre(:user).permit(:email) となり、params[:user][:email]という構造階層での指定が必要になる。 modelとurlの指定の違い modelは中身が入っていると自動でeditメソッドを呼び出す ストロングパラメーターの指定方法が違う まとめ 個人的両方の使いどころ ログインフォームはurl指定 登録フォームはmodel指定 参考 【Rails】form_with/form_forについて【入門】
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

form_withでのmodelとurlの指定の違いは?

はじめに form_withを使用中に気になったので調べてまとめてみました。 目次 urlの指定 modelの指定 modelとurlの指定の違い まとめ 参考 urlの指定 urlの書き方 form_with url: url_path 例) <%= f.text_field :emai%> <%= f.submit %> urlでは指定したurlに対してPOSTメソッドを行う。 :scope scope指定すると「指定すると現在のURLに対応したメソッドにフォームを送信」してくれる つまり、loinフォームを作成していてsessionControllerを使っている場合はsessionControllerのnewメソッドに送信してくれることになる ストロングパラメーターの設定 params.permit(:email) urlの場合は構造階層を意識することなくストロングパラメーターを設定できる。 modeleの指定 modelの書き方 form_with model: @model 新しく作られたオブジェクトの場合 例) user = User.new controller間の処理の流れ new => create この場合は渡されたオブジェクトの値が空の場合Rallsが自動でcreateメソッドを呼び出してくれる。 ストロングパラメーターの値指定 urlを指定して値を渡した場合は直接値を指定しできたが moelの場合は構造階層になるので指定方法が変わる 「Userモデルのemailを指定する」といった形に切り替える params.requitre(:user).permit(:email) となり、params[:user][:email]という構造階層での指定が必要になる。 modelとurlの指定の違い modelは中身が入っていると自動でeditメソッドを呼び出す ストロングパラメーターの指定方法が違う まとめ 個人的両方の使いどころ ログインフォームはurl指定 登録フォームはmodel指定 参考 【Rails】form_with/form_forについて【入門】
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

sketchupでruby その13

概要 sketchupでrubyやってみた。 練習問題やってみた。 練習問題 コップを描け。 写真 サンプルコード def glass model = Sketchup.active_model entities = model.active_entities x = 0 y = 0 z = 0 r = 30 n = 24 pts = [] pts[0] = [20, 0, 50] pts[1] = [15, 0, 5] pts[2] = [15, 0, 0] pts[3] = [13, 0, 0] pts[4] = [13, 0, 5] pts[5] = [18, 0, 50] base = entities.add_face pts circle1 = entities.add_circle(Geom::Point3d.new(x, y, z), Z_AXIS, r, n) status = base.followme(circle1) entities.erase_entities circle1 end 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on rails 単体テスト

苦手なテストについてふりかえろうと思い書いております。 今回は単体テストについて 単体テストコード モデルやコントローラーなどの機能ごとに問題がないか確かめます. バリデーションの挙動を確認します。 Ruby on Rails内にも、アプリケーションのテストコードを記述する機能を設けることができます。その機能はRSpecというGemを使うことで便利に実装できます。 Gemを追加しましょう Gemfile group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails', '~> 4.0.0' end 注意するのが、group :development, :testというグループの中に記述しましょう。 一番下ではないです。 bundle installを実行しましょう % bundle install インストールが完了すると、以下のようにディレクトリやファイルが生成されます。 create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb .rspecに設定を追加しましょう --require spec_helper --format documentation ここで、FactoryBotというものも導入 FactoryBot インスタンスをまとめることができるGemです。他のファイルであらかじめ各クラスのインスタンスに定める値を設定しておき、各テストコードで使用します。 Gemfileを編集しましょう group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails', '~> 4.0.0' gem 'factory_bot_rails' end この時も、group :development, :test doの中に記述するように注意してください。 Gemを導入するために、bundle installを実行しましょう。 % bundle install コマンドを実行して、テストファイルを作成しましょう rails g rspec:model user FactoryBot導入後はテストコードを記述するファイルを生成すると同時に、自動生成されます。 先にテストコードのファイルを作成してると、Factory.Bot用のファイルは自分で作成します。 factoriesの下にファイル名.rbで作る インスタンスの各値を設定しましょう FactoryBot.define do factory :user do nickname {'test'} email {'test@example'} password {'000000'} password_confirmation {password} end end 設定したインスタンスを生成するためには、FactoryBot.build(:user)という記述をテストコードの中に記述します。 require 'rails_helper' RSpec.describe User, type: :model do describe '#create' do before do @user = FactoryBot.build(:user) end context 'ユーザ新規登録ができる時' do it 'nicknameとemail,passwordとpassword_confirmation,family_nameとfist_name,family_name_kanaとfist_name_kana,birthdateが存在すれば登録できる' do expect(@user).to be_valid end it 'passwordが6文字以上であれば登録できること' do @user.password = '123abc' @user.password_confirmation = '123abc' expect(@user).to be_valid end end context 'ユーザ新規登録ができない時' do it 'nicknameが空では登録できない' do @user.nickname = '' @user.valid? expect(@user.errors.full_messages).to include("Nickname can't be blank") end 〜中略〜 context 'ユーザ新規登録ができる時' do~endを使って、正常系と異常系を分けると見やすくなる インスタンスを生成する際に、FactoryBotで設定した値は、'test@example'など固有のものでした。しかし、これから複数のテストを行う際に、「すでにemailの重複したインスタンスが存在する」といったような意図しない形で弾かれてしまうことがあります。 そんな時に使うのが、 Faker ランダムな値を生成するGemです。メールアドレス、人名、パスワードなど、さまざまな意図に応じたランダムな値を生成してくれます。 Gemfileに以下の様に追記します。今回はFakerをテストコードのために使用するので、これまで同様group :development, :test doの中に記述しましょう。 group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails', '~> 4.0.0' gem 'factory_bot_rails' gem 'faker' end そして % bundle install Fakerを使う場合 FactoryBot.define do factory :user do nickname {Faker::Name.initials(number: 2)} email {Faker::Internet.free_email} password {Faker::Internet.password(min_length: 6)} password_confirmation {password} end end ただ、複雑なバリデーションの場合は自分で仮に作った方が簡単な時がある。 例えばパスワードを英数字混合とかにしてたら、たまに数字のみになったりしてテストがエラーになったりする 最後にテストの実行コード bundle exec rspec spec/models/テストしたいファイル名.spec.rb
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on rails でのアプリケーションの作り方

自分用にまとめようと思ったやつです railsで新規アプリケーションをつくるうえでターミナルでうつコマンドをまとめてみようと思いました。 rails newコマンド Railsで新規アプリケーションを作成する際に使用します コマンドを実行する際には作成したいアプリケーション名を最後につけてrails new アプリケーション名とコマンドを実行します。 % rails new アプリケーション名 rails newコマンドで雛形を作成するときには、以下の2つの指定を行います。 -使用するRailsのバージョンの指定 -オプションの指定 ①使用するRailsのバージョンの指定 % rails _6.0.0_ new アプリケーション名 -オプション名 -dオプション -dオプションは、rails newコマンドにつけることができるオプションです。 -dオプションをつけると、作成するアプリが利用するデータベースの管理システムの種類を指定できます。 % rails new アプリケーション名 -d データベース管理システム名 コントローラーを作成 % rails g controller コントローラー名 気をつけることは、コントローラーの命名規則は、複数形を使用する コントローラー名の後ろにアクション名をつけるとそのアクションのviewファイルも作ってくれる。 viewファイルは自分で直接つくることもできる その際には、○○.html.erbとつくる 〇〇にはアクション名をつける 直接つくる時は、コントローラー名の下に作られているか注意!! モデルを作成しよう rails g modelコマンド % rails g model モデル名 モデルの命名規則は、単数形を使用する これ重要!! すると、マイグレーションファイルとmodelファイルがつくられる。 マイグレーションファイルに追加するカラム名と型を追加していきます。 [例] class CreatePosts < ActiveRecord::Migration[6.0] def change create_table :posts do |t| t.text :memo t.timestamps end end end これだけでは、テーブルはできません。 マイグレーションを実行しなければいけません。 % rails db:migrate こんな感じにターミナルにでればOK!! == 20XXXXXXXXXXXX CreatePosts: migrating ====================================== -- create_table(:posts) -> 0.0395s == 20XXXXXXXXXXXX CreatePosts: migrated (0.0396s) =========================== これでテーブルが作成☆ たまに、カラム名をまちがえた!!修正したい!!などは、やり方が複雑です 一度、戻します。 rails db:rollbackコマンド マイグレーション実行による変更を差し戻すためのコマンドです。 ロールバック→マイグレーションファイルの修正→マイグレートで、テーブルを修正できます。 % rails db:rollback して マイグレーションファイルを修正 そして % rails db:migrate をする これで、確認することもできる % rails db:migrate:status database: first_app_development Status Migration ID Migration Name -------------------------------------------------- down 20190820071210 Create posts downは戻っている upはmigrateしている rails dコマンド rails gコマンドで生成したファイル一式をすべて削除するコマンドです。つまり、rails dコマンドは、rails gコマンドとは逆の動作を行うものと言えます。 1つのファイルだけではなく、関連するファイルも一気に削除してくれるので、不要なファイルが残ってしまうことを回避できます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

sketchupでruby その12

概要 sketchupでrubyやってみた。 練習問題やってみた。 練習問題 ドーナッツを描け。 写真 サンプルコード def donut model = Sketchup.active_model model.start_operation('Create Donut', true) group = model.active_entities.add_group num_segments = 24 center_radius = 1.m thickness = 0.5.m origin = Geom::Point3d.new(0, center_radius, 0) circle = group.entities.add_circle(origin, X_AXIS, thickness, num_segments) face = group.entities.add_face(circle) path = group.entities.add_circle(ORIGIN, Z_AXIS, center_radius, num_segments) face.followme(path) model.commit_operation end 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】暗号生成(password generator)プログラムを作ってみた

初めに あるサイトで新規会員登録をしようとすると「強力な暗号?」みたいなのが出てきて、クリックすると長いパスワードが自動生成されたという経験があります。それと似たような内容を学習したので、rubyでプログラムを作ってみました。 ※内容に間違いなどがある場合はご指摘をよろしくお願いします。 結果物 文字(アルファベット)と記号、数字の数を順番に入力すると入力した合計分の強力なパスワードが生成される。 作業手順 ①やりたいことをまず文章で書く(アルゴリズム) ②細かな問題の記述 ③文章を元にフローチャートを書く ④プログラムを書く 大きな流れ アルファベットを用意する 記号を用意する 数字を用意する 結果を表示させる もう一度やり直すかプログラムを終了するか選ばせる 細かな作業&ロジック ランダムに生成された文字列、数字、記号をくっ付けた結果は文字列、数字、記号の順になっているため、ランダムに混ぜてあげる必要がある 上記の結果物をランダムに混ぜるには配列にする必要がある 配列にした上でshuffle関数を使ってランダムにする 配列になっている結果物は文字列に戻す(join関数を使う) フローチャート 暗号を生成する関数を作成 文字列と数字、記号が入っている配列を用意します。ユーザーから入力してもらった引数(文字の数、数字の数、記号の数)を利用し、文字列と数字、記号を引数の分だけくっ付けます。くっ付けた結果を配列に入れ直し、ランダムに混ぜたあと文字列に戻します。 #アルファベット(大、小)と数字(0~9)、記号を配列で用意する LETTERS = ("a".."z").to_a + ("A".."Z").to_a NUMBERS = ("0".."9").to_a SYMBOLS = ['!', '#', '$', '%', '&', '(', ')', '*', '+', '~', '¥', '[', ']', '?', '<', '>', '/', '@'] #暗号を生成する関数を定義 def cipher(number_of_letters, number_of_numbers, number_of_symbols) output = "" #出力結果を保存する入れ物を用意 number_of_letters.times do #入力された文字の数だけ、LETTERSから取り出してくっ付ける random_letter = LETTERS[rand(LETTERS.length)] output << random_letter end number_of_numbers.times do #入力された数字の数だけ、NUMBERSから取り出してくっ付ける random_number = NUMBERS[rand(NUMBERS.length)] output << random_number end number_of_symbols.times do #入力された記号の数だけ、SYMBOLSから取り出してくっ付ける random_symbol = SYMBOLS[rand(SYMBOLS.length)] output << random_symbol end #くっ付けた暗号文は文字列、数字、記号順になっているため、それをランダムに混ぜる処理 array_output = [] #ランダムにした結果の入れ物を用意 array_output = output.chars #String型になっているoutputを配列に変換 array_of_cipher_text = array_output.shuffle #array_outputを混ぜる(並び順をランダムにする) cipher_text = array_of_cipher_text.join #配列のarray_of_cipher_textをsrtingにする return cipher_text #完成物(cipher_text)をreturn end メインの処理を記述 loop文を使って「いいえ」を入力するまで繰り返し実行されるようにします。 #メインの処理 loop do #それぞれ文字数、記号の数、数字の数を入力してもらう puts "パスワードに使うアルファベットの文字数を教えてください。" input_number_of_letters = gets.to_i puts "記号の数を教えてください。" input_number_of_symbols = gets.to_i puts "数字の数を教えてください。" input_number_of_numbers = gets.to_i #結果の出力 returned_cipher_text = cipher(input_number_of_letters, input_number_of_symbols, input_number_of_numbers) #cipher関数の実行 puts "生成された暗号文は「#{returned_cipher_text}」です。" #もう一度やり直すかプログラムを抜けるかを選択してもらう puts "もう一度やりますか?「はい」か「いいえ」を入力してください。" restart = gets.chomp if restart == "いいえ" #いいえを入力した場合はさようならが出力され、プログラムを終了 puts "さようなら" break end end 実行結果は以下の通り ❯ ruby password_generator.rb パスワードに使うアルファベットの文字数を教えてください。 10 記号の数を教えてください。 5 数字の数を教えてください。 8 生成された暗号文は「*&%Rt9w!>C[4c8&f9lt>s6b」です。 もう一度やりますか?「はい」か「いいえ」を入力してください。 いいえ さようなら 参考記事 https://docs.ruby-lang.org/ja/3.0.0/method/String/i/chars.html https://docs.ruby-lang.org/ja/3.0.0/method/Enumerable/i/entries.html https://docs.ruby-lang.org/ja/3.0.0/method/Range/i/each.html http://pikawaka.com/ruby/rand https://docs.ruby-lang.org/ja/latest/method/Array/i/shuffle.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【未経験者向け】Rails api×React×Dockerで開発環境構築

Rails×React×Dockerにて開発環境を構築したので、アウトプット用に残しておきます。 下記の記事を参考にして構築していきました。 DockerでRuby on Rails + Reactを別々にアプリ作成する環境構築手順 Docker使ってReact × Rails(API)の環境構築 前提知識の確認 自分は初学者でrailsでしかWebアプリを構築した事がなかったのですが、Dockerで開発環境を構築する場合は、 rails newをする前に、いくつかのファイルを用意する必要があります。 ※詳しくはこちらが分かり易い Docker 公式ドキュメントの Rails Quickstart 完全解説 簡単に伝えると、プロジェクトのディレクトを作成した後rails newをする前にDocker環境構築用のファイルをいくつか作成した後で、 rails newやcreate-react-app行う。 フォルダ構造は下記のような形からスタートする アプリ名 backend Dockerfile entrypoint.sh Gemfile Gemfile.lock frontend Dockerfile docker-compose.yml ①ファイルを用意していく 上記構造のディレクトリとファイルを作成したら、中身を記述していく。 ※アプリ名と記載がある部分は、ご自分で作成中のアプリ名に変更して下さい。 docker-compose.yml docker-compose.yml version: "3" services: db: image: mariadb command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci environment: MYSQL_DATABASE: "アプリ名_development" MYSQL_ROOT_PASSWORD: "password" volumes: - mysql-data:/var/lib/mysql/data - /tmp/dockerdir:/etc/mysql/conf.d/ ports: - 3306:3306 backend: build: context: ./backend/ dockerfile: Dockerfile command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3001 -b '0.0.0.0'" volumes: - .:/アプリ名 ports: - "3001:3001" depends_on: - db frontend: build: context: ./frontend/ dockerfile: Dockerfile volumes: - ./frontend:/usr/src/app/frontend working_dir: /usr/src/app/frontend command: sh -c "npm start --host 0.0.0.0 --port 3000" ports: - "3000:3000" stdin_open: true volumes: mysql-data: {} dbには、mysqlを使用しております。 rails(backend)側では、3001番ポートで立ち上がるよう設定しており、react(frontend)側では3000番ポートにしてあります。 docker-compose.yml backend: build: ports: - "3001:3001" frontend: build: ports: - "3000:3000" rails側のファイル用意(全部で4つ) Dockerfile entrypoint.sh Gemfile Gemfile.lock Dockerfile(アプリ名/backend/Dockerfile) Dokcerfile. FROM ruby:2.7.2 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /アプリ名 WORKDIR /アプリ名 COPY Gemfile /アプリ名/Gemfile COPY Gemfile.lock /アプリ名/Gemfile.lock RUN bundle install COPY . /アプリ名 # Add a script to be executed every time the container starts. COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3001 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"] Gemfile Gemfile. source 'https://rubygems.org' gem 'rails', '5.2.5' railsのバージョンは5.2.5にしてあります。 最近発生していたmimemagi関連のエラーを回避する為ですが、 rails6系が良い方は、6.0.3.6又は6.1.3.1であれば、エラー回避出来るようなので、どちらかを指定して下さい。 ※詳しくは下記を参照下さい RailsのGPL混入問題についてまとめ(mimemagic) Gemfile.lock touch Gemfile.lockで作成したら、空ファイルのままで大丈夫です。 entrypoint.sh entrypoint.sh #!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /アプリ名/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@" これで、rails側の準備はOKです。 react側のファイル用意 Dockerfile(アプリ名/frontend/Dockerfile) FROM node:14.15.1-alpine ※この記述だけで大丈夫です。 ②Dockerコマンドを実行する 順番に実行して下さい。 アプリ名 $ docker-compose run backend rails new . --force --no-deps --database=mysql --api アプリ名 $ docker-compose build アプリ名 $ docker-compose run --rm frontend sh -c "npm install -g create-react-app && create-react-app frontend" 成功すると、見慣れたディレクトリ構造になってるかと思います。 database.yml(backend/config/database.yml)を修正する database.yml default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: 自分で設定 password: "自分で設定" host: db socket: /var/run/mysqld/mysqld.sock development: <<: *default database: アプリ名_development test: <<: *default database: アプリ名_test usernameとpasswordは、お好きに設定して下さい。mysqlをターミナルから使用する際に求められます。 再びDockerコマンドを実行 アプリ名 $ docker-compose up アプリ名 $ docker-compose run api rake db:create 下記の画面が出ていれば、成功 rails(localhost:3001) react(localhost:3000) 最後に 記事をまとめるのは、難しいですね・・・ 初めてなので、稚拙な部分も沢山あったかと思いますが、 不明点や記述の仕方に対するフィードバックが御座いましたら、お教え頂けますと幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

active model serializers のレシピ集 & 個人的ベストプラクティス集

はじめに 他に便利な使い方があれば教えてもらえると幸いです 間違っている箇所があれば教えてもらえると幸いです レシピ 条件付き attribute 条件でキーの有無が変わるときは下記のように書けます。 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :posts_count, if: -> { object.posts.present? } do object.posts.count end end シリアライザ内で使えるパラメーターを渡す シリアライザにキー、バリューを渡すことで app/controllers/users_controller.rb class UsersController < Api::ApplicationController def show render json: current_user, serializer: UserSerializer, hoge: 'test' end end or ActiveModelSerializers::SerializableResource.new( user, serializer: UserSerializer, adapter: :attributes, hoge: 'test' ).serializable_hash シリアライザ内において instance_options からその値を参照することができます。 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :test_val do instance_options[:hoge] end end 個人的ベストプラクティス シリアライザは明示的に指定した方が良さそう シリアライザを明示的に指定なくてもモデルのクラス名から推測して UserSerializer を使ってくれますが、 app/controllers/users_controller.rb class UsersController < Api::ApplicationController def show render json: current_user end end UserSerializer を変更したときの影響範囲を調べるときにシリアライザ名で grep しにくい 一目でどのシリアライザを使っているかわかりにくい ことからシリアライザを明示的に指定した方が良さそうです。 app/controllers/users_controller.rb class UsersController < Api::ApplicationController def show render json: current_user, serializer: UserSerializer end end attribute とメソッドを2つ使うよりは attribute のみでキーを出力した方が良さそう attribute とメソッド定義を2つ書くより app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :name_hoge def name_hoge "#{object.name}_hoge" end end attribute ブロックのみを使った方がシンプルになります。 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :name_hoge do "#{object.name}_hoge" end end proc のため return は使えないことに注意してください メソッドの処理そのままでメソッド名と異なるキー名を使いたいときは attribute を使った方が良さそう attribute ブロックを書くより attribute :is_admin do object.admin? end attribute メソッドの key オプションを使った方がシンプルに書けます。 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :admin?, key: :is_admin end リソースのハッシュ出力では adapter: :attributes オプションを使ってルートキーを出力させない方が良さそう serializable_hash[:post] のようにキー名を指定する書き方をするとシリアライザの名前空間が変わったり、type メソッドに渡す値が変わるとキー名が変わってしまいデグレが起こる可能性があるので、ルートキーが必要ない場合は adapter: :attributes を使用してキー名を記載しない方が良いと思います。 単一リソース ActiveModelSerializers::SerializableResource#serializable_hash を使います。 serializer オプションにシリアライザを指定します。 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :single_post do ActiveModelSerializers::SerializableResource.new( object.single_post, serializer: PostSerializer, adapter: :attributes ).serializable_hash end end 複数リソース each_serializer オプションにシリアライザを指定します。 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :posts do ActiveModelSerializers::SerializableResource.new( object.posts, each_serializer: PostSerializer, adapter: :attributes ).serializable_hash end end アソシエーションをシリアライズするときは has_many, has_one, belongs_to を使うよりも手動でシリアライズした方がパラメーターを渡すことができるので良さそう アソシエーションも返却するときは has_many などのメソッドを使えばシンプルに書くことができますが、 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer has_many :posts, serializer: PostSerializer end パラメーターを渡すことはできません app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer # hoge_param は PostSerializer に渡らない has_many :posts, serializer: PostSerializer, hoge_param: 'hoge' end アソシエーションのシリアライザにパラメーターを渡したいときは手動でシリアライザを展開しなければなりません app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :posts do ActiveModelSerializers::SerializableResource.new( object.posts, each_serializer: PostSerializer, hoge_param:'hoge', adapter: :attributes ).serializable_hash end end ルートキーにメタ情報を追加したいときは meta オプションを使う方が良さそう キー名にこだわりがなくルートキーと同じ階層にメタ情報を追加したいときは meta を使うと楽です。 app/controllers/users_controller.rb class UsersController < Api::ApplicationController def show render json: current_user, serializer: UserSerializer meta: {time: Time.zone.now} end end meta を使わない場合は hash を自前で作ることになるのでコードが煩雑になると思われます。 app/controllers/users_controller.rb class UsersController < Api::ApplicationController def show hash = { user: ActiveModelSerializers::SerializableResource.new(current_user, serializer: UserSerializer, adapter: :attributes).serializable_hash, meta: {time: Time.zone.now} } render json: hash end end ディレクトリの切り方はコントローラーに準じた方が良さそう 使いたい user serializer がコントローラーのメソッドごとに違う場合は app/controllers/users_controller.rb class UsersController < Api::ApplicationController def index ... end def show ... end end serializers 配下にフラットにシリアライザファイルを作成するよりも app/serializers/index_user_serializer.rb app/serializers/show_user_serializer.rb 返却されるオブジェクトはAPIのエンドポイントに依存しているので、コントローラーのクラス名の名前空間、メソッドに応じてディレクトリを切った方がわかりやすいと思っています。 app/serializers/users/index/user_serializer.rb app/serializers/users/show/user_serializer.rb 汎用的ではなく1つのエンドポイントでしか使われないシリアライザはシリアライザ内にクラス定義した方が良さそう 1つのエンドポイントでしか使われない特殊なシリアライザならばファイルに切り出して、コードを参照するときに別ファイルを見にいくよりも app/serializers/special_post_serializer.rb シリアライザクラス内にシリアライザを定義した方がコードを追いやすいかもしれません。 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :special_post do ActiveModelSerializers::SerializableResource.new( object.posts, serializer: UserSerializer::SpecialPostSerializer, adapter: :attributes ).serializable_hash end class SpecialPostSerializer < ApplicationSerializer attribute :special_post_key do 'value' end end end 名前空間が変わらないので基本的には type を指定した方が良さそう type メソッドを使うことでルートキーの名前を固定することができます。 app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer  type 'user' attribute :name end ActiveModelSerializers::SerializableResource.new( user, serializer: UserSerializer, ).serializable_hash => {user: {...}} type を指定しないとシリアライザの名前空間によってルートキーの名前が変わってしまいます。 app/serializers/v2/user_serializer.rb class V2::UserSerializer < ApplicationSerializer attribute :name end ActiveModelSerializers::SerializableResource.new( user, serializer: V2::UserSerializer, ).serializable_hash => {'v2/user' => {...}} 名前空間に関わらず一意のリソースの名前を使うことの方が多いと思うので type は指定した方が良いと思われます。 # ルートキーが変わるとこのようなコードがデグレを起こす可能性がある user_res = ActiveModelSerializers::SerializableResource.new(...).serializable_hash user_res[:user][:name] シリアライザ内でデータの出どころがわかりにくいので scope は使わない方が良さそう scope を使用すると指定した情報をそのままシリアライザに持っていくことができますが、下記の例の場合 current_post がどこから来たのかがわかりにくいため app/controllers/users_controller.rb class UsersController < Api::ApplicationController def show render json: current_user, serializer: UserSerializer, scope: current_user.current_post, scope_name: :current_post end end app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :post_name do current_post.name end end 通常のパラメーターで渡した方がわかりやすいと思っています。 app/controllers/users_controller.rb class UsersController < Api::ApplicationController def show render json: current_user, serializer: UserSerializer, current_post: current_user.current_post end end app/serializers/user_serializer.rb class UserSerializer < ApplicationSerializer attribute :post_name do instance_options[:current_post].name end end has_many のアソシエーションで order を使うときはそれ専用のアソシエーションをモデルで定義した方が良さそう 下記記事を参照してください。 has_manyで紐づくモデルをSerializerの中でorderするとSQLキャッシュのN+1が起きる問題をなんとかしたい
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む