20200812のRubyに関する記事は15件です。

RubyからCocoaを使ってみる

RubyからCocoa(macOSのAPI)を使ってみる。
以前、RubyCocoaというものがあった。今は動かなくなっているようだ。
近いものとして、cocoaというgem packageがある。
https://github.com/patrickhno/cocoa/

インストールする。

% gem install cocoa
Successfully installed cocoa-0.1.6
Parsing documentation for cocoa-0.1.6
Done installing documentation for cocoa after 3 seconds
1 gem installed

サンプルプログラムを実行してみる。

test1.rb
require 'cocoa'
Cocoa::NSAutoreleasePool.new
app = Cocoa::NSApplication.sharedApplication
app.setActivationPolicy Cocoa::NSApplicationActivationPolicyRegular
app.activateIgnoringOtherApps true
alert = Cocoa::NSAlert.alloc.init.autorelease
alert.setMessageText "Hello world!"
alert.runModal

% ruby test1.rb
/usr/local/lib/ruby/gems/2.7.0/gems/cocoa-0.1.6/lib/cocoa/objc/method_def.rb:154: warning: constant ::Fixnum is deprecated
/usr/local/lib/ruby/gems/2.7.0/gems/cocoa-0.1.6/lib/cocoa/objc/method_def.rb:154: warning: constant ::Fixnum is deprecated
/usr/local/lib/ruby/gems/2.7.0/gems/cocoa-0.1.6/lib/cocoa/objc/method_def.rb:154: warning: constant ::Bignum is deprecated

無事実行されるのだが、warningが気になるな。今度、修正してみよう。

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

google search console の sitemap の api client は searchconsole ではなく webmasters にある

概要

google search console のサイトマップに対する API のクライアントを探していたときに sdk の searchconsole ディレクトリを見て、サイトマップの操作に対するメソッドがないなあと少しはまったので共有です。

結論

ruby sdk の例ですが、
searchconsole_v1 ではなく、
https://github.com/googleapis/google-api-ruby-client/blob/master/generated/google/apis/searchconsole_v1/service.rb

webmasters にサイトマップの API はあります。
https://github.com/googleapis/google-api-ruby-client/blob/master/generated/google/apis/webmasters_v3/service.rb

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

Rubyにおける正規表現について

Ruby の正規表現について

先日カリキュラムで学習した正規表現について、『暗号がいっぱい書いてある・・・』という状態でしたので、『学んだ事の整理』と『学習のアウトプット』も兼ねて記事にしてみました。

  • 正規表現って?

    文字列の集合を一つの文字列で表現する方法の一つである。正則表現(せいそくひょうげん)とも呼ばれ、形式言語理論の分野では比較的こちらの訳語の方が使われる。まれに正規式と呼ばれることもある。(wikipediaより抜粋https://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE)

これだけだと分かりづらいので、アプリケーションに触れていると『パスワードが6文字未満だと登録できません』とか『電話番号にハイフンが入っていると・・・』というような事が多々あります。では、これは一体どのようにして判断をしているのでしょうか?

例えば電話番号を登録するような場合、

id name tel
1 Aさん 090-0000-0000
2 Bさん 09000000000

Aさん→ハイフンありで登録
Bさん→ハイフンなしで登録 

といった状況が生まれたりします。これだと別フォーマットで管理する事になってしまうので、統一した方が管理がしやすいです。その際に『余分なハイフンは消す!』といった処理をすると管理もしやすくなります。
このように、『文字列に特定の文字が入っているかどうか?』や『特定の文字を取り除く』といった処理を行う技術が正規表現となります。
正規表現は様々な言語で同じようなコードで表す事ができるので、形を覚えてしまえば別の言語にも応用できるようになっています。

  • 正規表現のメソッド

Rubyでは主に下記3つのメソッドが重要且つよく使われています。

subメソッド

文字列の指定した部分を別の文字列に置き換えるメソッドです。例えば下記のコードのような使い方をします。
 greeting = "Hello,world"
=>"Hello,world"

 greeting.sub(/Hello/,"Good morning")
=>"Good morning,world" 

/で囲まれた"Hello"という文字列を"Good morning"に置き換える事ができました。

matchメソッド

引数に指定した文字列が、呼び出した文字列の中に含まれているかどうかを判断するためのメソッドです。
 greeting = "Hello,world"
=>"Hello,world"

 greeting.match(/Hello/)
=> #<MatchData "Hello">

greeting.match(/Good morning/)
=> nil 

上記のように、greetingに代入された文字列は"Hello,world"なのでmatchメソッドで引数を/Hello/で指定した場合にはMatchDateとして"Hello"が呼び出されています。しかし引数を/Good morning/に指定すると、代入された文字列の中には含まれていない文字列となるので、『nil』と表示されます。

gsubメソッド

subメソッドと同じく文字列を置換するためのメソッドですが、g(グローバルメソッド)がつく事で、文字列内に指定した文字列が複数含まれる場合、その全てを置換する役割を持っています。電話番号を例にしてみると
telA = '090-0000-0000'
=> "090-00000-0000"

telA.gsub(/-/,'')
=> "090000000000"

このように/で囲ったハイフンを取り除く事ができました。
以上のように、メソッドで取り除く文字列や含まれる文字列を指定する事で文字列に制約をかける事ができます。指定するための記述方法は以下にまとめましたので、使うときがありましたら参考にしてください。

パターン 意味
[a-z] アルファベットaからzまでのいずれかにマッチ
\d 数字にマッチ
[a-z\d] 英数字のいずれか1つにマッチ
{n,m} 直前の文字が少なくともn回、多くてm回出現するものにマッチ
i 大文字と小文字を区別せずに検索(最後につける)
. どの1文字にもマッチ
+ 直前の文字が1回以上の繰り返しにマッチ
\A 直後の文字が先頭にある文字列にマッチ
\z 直前の文字が末尾にある文字列にマッチ
[ぁ-んァ-ン一-龥] 角括弧に囲まれたかな、カナ、漢字いずれかにマッチ
?= 直後に設定した文字が続く文字列にマッチ
*? 直前に設定した文字が0回以上続く文字列をチェックし、?の直後の文字が出た段階でその1文字を返す
/\A(?=.?[a-z])(?=.?[\d])[a-z\d]+\z/i 先頭が任意の文字0回以上と英数字で始まり、末尾が英数字の1回以上の連続する文字列にマッチし、大文字小文字の区別がない(英数字混合のパスワードをチェックする時など使えます)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ターミナル が立ち上がらない

こんなことありませんか?
ターミナルで rails s を打ち込んだところ

 Address already in use - bind(2) for "127.0.0.1" port 3000 (Errno::EADDRINUSE)

とエラーが出ることがありますが
・Address already in use 
(アドレスは既に使用されております)と翻訳されます。

原因

エラー 「"127.0.0.1" port 3000」が既に使われているため

参考

https://qiita.com/nagao_norihiro/items/aba40bd4e0eac9f9a92d
https://qiita.com/Shimba/items/1a234ebb646bb01d16cd

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

【Rails】定数は、config gemで管理しましょう

環境

$ rails -v
Rails 6.0.3.1
$ ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]

まずは、Gemのインストール

Gemfile
gem 'config'
$ bundle install --path vendor/bundle

configの初期設定を行う

configの初期設定のために関連ファイルをインストールする

$ bundle exec rails g config:install

定数定義と、使い方

config/settings.yml
service: 
  name: 'vdeep' 
  url: 'http://vdeep.net'

authentication_password: "foobarbaz"
$ rails c

> Settings.service.name
=> "vdeep"

> Settings.service[:name]
=> "vdeep"

> Settings[:service][:name]
=> "vdeep"

> Settings.authentication_password
=> "foobarbaz"

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

Ruby の paypal-sdk-rest gem で発生する OpenSSL::SSL::SSLError: SSL_connect の解決方法

詳しいことは後日、もう少し追記する予定。

経緯

2020年8月11日の夕方ごろ(日本時間)から paypal-sdk-rest gem を使った支払いで下記のエラーが発生するようになった。

OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)

対応方法

https://curl.haxx.se/docs/caextract.html から最新の cacert.pem をダウンロードして、 config/certs/cacert.pem に配置して、 config/paypal.ymlssl_optionsca_file の設定を追加する。

config/paypal.yml
development: &default
  mode: sandbox
  client_id: xxx
  client_secret: xxx
  ssl_options:
    ca_file: config/certs/cacert.pem
production:
  mode: live
  client_id: xxx
  client_secret: xxx

この設定で、ローカル開発環境、 production 環境ともに想定通り動作することを確認した。

別の解決方法

参考

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

独学半年の実務未経験がRails+Nuxt.jsでSPA作ったので見て欲しい

はじめに

アプリを作ったのはいいものの、フィードバックをくれる人がいなかったのでQiitaで紹介記事を書くことにしました。
独学で周りにアドバイスをもらえる人がいないので、改善点などどんどん指摘してくださると幸いです。

自己紹介

作者は今年の2月末ごろから独学でプログラミングを学習しています。
高校時代にほんの少しHTMLを触ったことがある程度で、前提知識はほぼありませんでした。
現在はアプリを作成しながら、10月の基本情報に向けて勉強しています。
アプリ制作は今回で2作目になります。
前作URL
前作リポジトリ

アプリ概要

これが作成したアプリです。

サイトURL
githubリポジトリ

PolPa(ポルパ)は、学習時間に応じてレベルが上がる学習記録アプリです。
全体像がわかると思うので先にERを貼っておきます。

polpa.png

機能紹介

主な機能を一部紹介します。

ゲストログイン

localhost_8080_signup.png

新規登録フォームの下からゲストアカウントでログインできます。
気軽に試すことができるので、見学しに来てください。

学習時間を記録する

time-report.gif

このアプリのメイン機能です。記録された時間に応じて経験値を獲得できます。
タグをつけてジャンル分けできます。
記録した日には草が生えます。
記録にはコメントやいいねができます。

ユーザーをフォローする

follow.gif

ユーザーをフォローすると、タイムラインにそのユーザーの記録が表示されるようになります。
他のユーザーと交流して、モチベーションを高め合いましょう!

ユーザーを検索する

search.gif

ユーザー名で検索できます。
リアルタイムに検索結果が変化します。

レスポンシブデザイン

スマホやタブレット用のデザインにも対応しているので、モバイル端末から手軽に利用できます。

他にも紹介してない機能がたくさんあるので、ゲストログインで体験してください。

作った理由

サービスとして

他の学習管理アプリを使っていて、今まで積み上げてきたものをはかる指標があればもっとモチベーションを維持しやすくなるのではないかと考え、「学習時間を記録するとレベルが上がる」という要素をプラスした学習管理アプリがあれば面白いのではないか、と開発を始めました。

個人として

個人的には、Vue.jsとRailsを使って何かを作りたかったから開発を始めたという理由もあります。
作る前はこんな程度のアイデアで開発を始めてもいいのだろうかと思っていましたが、開発を進めていくうちに少し愛着が湧いてきました。

技術周りの話

使用している主な技術やリソース

  • Ruby、Rails ... バックエンド
  • Vue.js、Nuxt.js ... フロントエンド
  • Vuetify ... UIフレームワーク
  • PostgreSQL ... データベース
  • Docker、Docker-compose ... コンテナ仮想化
  • Git、GitHub ... バージョン管理システム
  • Firebase ... ログイン認証・ホスティング
  • heroku ... API用サーバー

Rails

バックエンドにはRailsを使用しています。Railsは学習期間が最も長く、前作でも使用しています。
新しく作るアプリは新しい要素を追加したいと思ったので、バックとフロントで別のフレームワークを使用する手法を取ることにしました。

Vue.js、Nuxt.js

Vue.jsは以前から興味があり、Railsとの共存も容易だったため、学習を開始しました。
Vue.jsは書籍一冊学習したのみだったので、雰囲気しか理解していない状態からコードを書き始めました。
Nuxt.js自体は開発を始めてから初めて触りました。

Vuetify

フロントのデザインはほとんどVuetifyに頼っています。アプリに必要なデザインコンポーネントが一通り揃っているので、一から作るにはめんどくさいデザインも簡単に実装できました。
種類が豊富なので、Vuetifyの公式リファレンスを見るだけで楽しいです。

Firebase

ログイン認証にはFirebaseを用いています。初めての開発手法だったため、自力で安全な認証・認可を実装できないと判断し、Firebaseを使用することにしました。

一人で開発して感じたこと

個人で開発をしていく上で良かったことと、つらかったこと・反省点をいくつかまとめてみます。

良かったこと

前作を制作した時も感じていましたが、アプリ制作は本当に勉強になります。
特に独学だとすべてのエラーを自力で解決しなければならないので、デバック力や問題解決能力が磨かれます。
一人で開発するとWeb開発の技術が全般的に必要になるので、次に勉強したい分野が明確になるのもいい点だと思います。

つらかったこと・反省点

  • エラーの解決方法がわからないとストレスがたまる
  • 開発するときのルールを決めておかないと徐々に雑になる
  • あれもこれもと機能を追加しているとキリがない

コードが予想に反する動きをして半日潰れたなんてことは日常茶飯事だったので慣れはしましたが、目に見える成果が全く得られないというのはストレスがたまります。ネットで検索してみてもそれらしい情報が全く出てこなかった時は本当に絶望します。
ただ、良かった点にも書いているようにメリットとは表裏一体です。
なんとか解決してきたので、自分の力にもなっているのかなと思います。

最初に張り切って、「今回はこの方法にしたがってコーティングして、この手法を使って開発を進めるぞ!」 なんて思っても大体続きませんでした。だんだん雑になってきて、めんどくさいからいいか、一人だからいいかとなりがちでした。次回があれば、ルールの徹底を意識したいと思います。

これからについて

もっと追加したい機能があるので時間があればアップデートしたいと思っています。
10月中旬の基本情報に向けてJavaを勉強するつもりなので、しばらくは時間がないと思いますが、アプリの完成度を高ていきたいのでフィードバックなどよろしくお願いします。

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

[備忘録] ``expect``の後ろは``()``か``{}``か。 (Module: RSpec::Matchers)

本編

RSpecのマッチャの書式についての個人的な小メモです。

RSpecのバージョン

RSpec 3.9
  - rspec-core 3.9.2
  - rspec-expectations 3.9.2
  - rspec-mocks 3.9.1
  - rspec-rails 4.0.0.beta3
  - rspec-support 3.9.3

expectの後ろは(){}か?

結論

下記のgem(rspec-expectations (3.9.2))のドキュメントでMathersのページに各マッチャの記法が列挙されています。用例も多く掲載されています。(#changeなど)

Module: RSpec::Matchers — Documentation for rspec-expectations (3.9.2)

expect(..).to be_xxx{..}を誤用した例

実際にシステムスペックのファイル内で(..){..}と書いてテストを実行した場合のエラーメッセージです。
be successfulのマッチャを使用するには、ブロックではなく引数を渡さなければならないということは教えてくれています。

エラーメッセージ例
You must pass an argument rather than a block to `expect` to use the provided matcher (be successful), or the matcher must implement `supports_block_expectations?`.

# ./spec/system/doing_edit_spec.rb:11:in `block (2 levels) in <top (required)>'
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS I�oT ボタンとSlackを連携してみた

はじめに

AWS IoTボタンを使ってSlack通知ボタンをつくってみました。
※実は作ったのは半年以上前ですが、なかなか記事が公開できませんでした!

会社のウォーターサーバーなのですが、最後の1本を使用した人はSlackで総務へお知らせするフローがありまして、でもどうしても席に戻るとぽかんとお知らせすることを忘れちゃうんですよね。

そこで、うっかり忘れをしないようにIoTボタンを使ってSlackへのお知らせをその場でしよう、というアイデアではじめました。課題解決ドリブンですね。

あとはそこにAWS IoTボタンがあったからです。

それではやっていきましょう!

用意するもの

AWS IoT ボタン ✕ 1 (¥2,500)
https://aws.amazon.com/jp/iotbutton/
見るからにアマゾンダッシュボタンな、今回はこちらを使っていきます。
アマゾンダッシュボタンだとサーバーになるPCが必要そうです、簡単にセットアップできてこの値段も高くもない?ので、これをつかいます。

AWSアカウント ✕ 1 (USD$0.25/month)
月額27円くらいかかるみたいです。
https://aws.amazon.com/jp/iot-1-click/pricing/

IoTボタンの有効化

まずはAwS IoT ボタンを登録していきます。
コンソールから登録する方法とスマホで登録する方法があるみたいですが、スマホでやるのが簡単そうです。

Storeからアプリをダウンロード

iOSであればAppStoreから、AndroidであればGooglePlayからアプリをインストールします。私はiOSで登録しました。
iOS : https://apps.apple.com/us/app/aws-iot-button/id1178216626
Android : https://play.google.com/store/apps/details?id=com.amazonaws.iotbutton

AWSにログインして、デバイスの登録とWifiへの接続を定します。ポチポチ。ピッピ。
カメラで、AWS IoTボタンの側面のバーコードを読み取るだけで登録できます。
IMG_6601.PNG IMG_6602.PNG

PCからAWSコンソールへログインして、有効化をします。

設定してからスクリーンショットを撮ってしまったのですが、こちら最初は無効になってて、かつプロジェクトと配置は未設定となっていると思います。
スクリーンショット 2019-12-11 18.13.44.png

Slack連携の準備

SlackのAppディレクトリへIncoming Webhookを追加し、Webhook URLを発行します。
Incoming Webhookの名前とアイコンも設定し、メッセージをプレビューします。
▼こんな感じにしてみました
スクリーンショット 2019-12-16 16.41.19.png

Lambda関数を作成

AWSのLambdaを使って実行するスクリプトを準備します。
今回のスクリプトはこんな感じでした。

require "net/https"
require "uri"

def lambda_handler(event:, context:)
    uri = URI.parse('https://hooks.slack.com/services/XXXXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXX')
    res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == "https") { |http|
        http.request(Net::HTTP::Post.new(uri).tap { |req|
            req.body = {
                channel: '通知させたいSlackチャンネル名',
                username: 'Webhookのときに設定したSlack投稿ユーザー名',
                text: '<@メンション飛ばす相手のユーザー名> アクアクララ、最後の1本を設置しました。',
            }.to_json
        })
    }
    { statusCode: 200, body: res.to_s }
end

テストを作成してみます。なんでもいいようなので、今回はHelloWorldという既存テンプレートそのままの設定を使って作成し、実行してSlackへの投稿を確認します。
スクリーンショット 2019-12-16 16.55.33.png
Slackに投稿できればひとまずコードはOKですね。次はいよいよボタンとAWSの連携です。

AWS IoT1-Clickページでデバイスに連携

プロジェクトの作成

最後に、IoTボタンとLambda関数を連携させるプロジェクトをAWS IoT1-Clickのページから作成します。
コンソールにログインして、AWS IoT1-Clickのページを開きます。
スクリーンショット 2019-12-26 17.59.41.png
プロジェクト名をいれてすすめると、デバイステンプレート名とアクションを選べます。
作ったLambda関数を指定します。
スクリーンショット 2019-12-26 18.01.09.png

プレイスメントの作成

デバイスを指定してプレイスメントというものを作成していきます。
デバイスを指定し、属性の名前と値を入れます
スクリーンショット 2019-12-26 18.16.00.png

ボタンを押してSlack連携を確認

連携されていればOKです!

参考サイト

この記事は下記Qiita記事を参考にさせていただきました。
おかげさまで半年以上元気に稼働しています、便利ですよ!
https://qiita.com/cumet04/items/11bc8883ae9cc603b84d

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

【コードゴルフ】コードをDeflate圧縮して短くする【圧縮ゴルフ】

コードゴルフを知っていますか?僕は知っています。できるだけ少ない文字数でコードを書く競技です。

この度、新しく圧縮部門ができてしまったので紹介しようと思います。

コードを圧縮する

まず、次のコードを見てください。

#!ruby -Knrzlib
eval Zlib.inflate'x�=�Q
� D��OS�c

]r� �����ݳ�By�
              ����O{4�.��i�aQ(`}cB���I2e�ߣ��IeT�јL>������)u,�p�S�W��H~.�,�:
z:Ӊ��g�O7ʲ��vQ�1h�^<����=&�\u7'

ほとんど読めないですね。
ですが、最初の方は普通にRubyのコードです。

#!ruby -Knrzlib

これはShebangですが、コマンドラインオプション-Kn-rzlibを指定しています。
-Knは文字コードがないバイナリとして扱うことを示します。#coding:binaryと同じ意味です。
-rzlibはzlibライブラリをrequireしています。require "zlib"と同じ意味です。

次の行です。

eval Zlib.inflate'…

Zlib.inflateは圧縮したコードを解凍するメソッドです。'以降に圧縮された文字列が続いていることからも、このコードは圧縮されたコードを解凍してevalしていることがわかります。

やってみる

コードを圧縮してこのようなテンプレートに埋め込めばよいことがわかりました。
これを実際にするには、①コードを書く、②圧縮する、③提出する、の3つのステップが必要です。
特に、圧縮率を下げるためには①と②の間を反復することが必要になります。

1. コードを書く

まずはコードを書いてみましょう。(ここではコードの内容は問題ではないです)

agc047_e.rb
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|x|[a,x,3,x]+(0..29).map{v=x+4;u=x*60+9+_1;[a,v,v,v,a,v,3,6,*[a,6,6,6]*(29-_1),?<,6,x,u,a,v,u,v]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}

このコードの長さは216 Bytesです。
書けたので、圧縮してみましょう

2. 圧縮する

ここでは、 https://pastebin.com/TtNNhyND のスクリプトを使って圧縮していきます。

$ ruby deflate.rb agc047_e.rb > agc047_e.rb
194 B

194 Bytesに縮みました!

3. 提出する

圧縮したら、さあ提出といきたいところですが、ひとつ問題があります。
残念ながら、このコードをコピペしてそのまま提出というわけにはいきません。圧縮して生成されたコードはバイナリです。しかし、AtCoderの提出画面はUTF-8です。多くの場合、圧縮してできたコードはUTF-8として正しくないバイト列を含んでいるので、そのままコピペすると化けてしまいます。

そこで、DevToolsを使って、URIエンコードしたコード直接提出することにします。

提出画面を開いて、DevToolsを出します。ネットワークタブを開いておいてください。
スクリーンショット_2020-08-12_14-10-39.png

この状態で提出ボタンを押してください。DevToolsにリクエストが表示されます。
ここで、submitという名前のリクエストを選んで右クリックし、Copy▶Copy as fetchを押してください。fetchするコードがコピーされます。

rsz_スクリーンショット_2020-08-12_14-25-02.png

そのままConsoleタブを開いて、今コピーされたコードを貼り付けます。
スクリーンショット_2020-08-12_14-31-50.png

(画像には表示されていませんが)sourceCode=の後ろにURIエンコードされたソースを貼り付けていくことになります。

URIエンコードするために https://pastebin.com/TA35nsHZ を使います。(deflate-uriencode.rbとして保存しておいてください)

$ ruby deflate-uriencode.rb agc047_e.rb
194 B
%23%21ruby+-Knrzlib%0Aeval+Zlib.inflate%27x%DA-%8DQ%0A%830%10D%AF%D2Ou%B7A%13%5D%14%2B%1E%24%04%C9%01%0AB%13%094%B9%7Bwc%99%8F%81%99%E1%CD%19%C3%E7ai%9CG%F4%DB%0E%D8%E3%80%06%F7%17j6%E3%C0r%E0%D4%DB%9F%DF%9C%B2%F5%988N%0E%9A%5E%29%BD%B4%B5%B8%B6%04%E3%1A%B7%D4Q%0F%0B%1C%C3%CA%BB%ABJ%DC+a%C7%09%89%5C%D7%E8%E5y%0C%AD%5C%10%D3b%DDD%BC%5C%29%95%3A%FD%A99%C8%9D%16%DDw*%DC%05%A73%04f+%C9%19N%822l%84%B2%DE%97%F2%03%93%919%B0%DE%97%F2%03%93%919%B0%27

deflate-uriencode.rbでagc047_e.rbを変換します。
出力の2行目の%23から始まる文字列をコピーして、先程のsourceCode=の後ろに貼り付けてください。

スクリーンショット_2020-08-12_14-38-54.png

この状態で実行すると提出することができます。

1. コードを書く(さらに短くなるように)

コードを縮めましょう。圧縮後のコードが短くなるためには、2つの方法があります。

  1. 元のコードを短くする
  2. 圧縮率を上げる

ここでは主に2の方法をやっていきます。1は普通のゴルフの方法ですね。

圧縮率を上げる

どうすれば圧縮率が上がるでしょうか。今、Deflate圧縮を使っていますが、Deflate圧縮はランレングス圧縮とハフマン符号の組み合わせです。このハフマン符号の方に注目します。

ハフマン符号は、圧縮前のエントロピーが小さい程圧縮率が高くなる特徴があります。エントロピーは、符号の出現確率が偏っている程小さくなります。なので、符号の出現確率を偏らせれば偏らせる程圧縮率が上がるということになりそうです。

出現確率を偏らせるには、文字種を減らしたりするのが有効です。最も簡単な方法としては、変数名を変更するなどです。

最初のコードで、変数xvの変数名を変更してtpにしてみましょう。すると、関数名のputsmapと被るので、文字種を減らすことができます。

agc047_e.rb
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{p=t+4;u=t*60+9+_1;[a,p,p,p,a,p,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,p,u,p]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
275 B

あれ?増えてしまいました。
ではpはやめてsにしてみます。

agc047_e.rb
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{s=t+4;u=t*60+9+_1;[a,s,s,s,a,s,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,s,u,s]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
184 B

今度はちゃんと減っています。(なぜ増えたのかわからないので、詳しい方お願いします)

このように、書いて圧縮する試行錯誤を繰り返すことで、コードを縮めることができます。

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

【コードゴルフ】コードをDeflate圧縮してAtCoderに提出する【圧縮ゴルフ】

コードゴルフを知っていますか?僕は知っています。できるだけ少ない文字数でコードを書く競技です。

この度、AGC047 Eに提出された171 Bytesのコードが物議を醸しているので、コードの圧縮について解説しようと思います。

コードを圧縮する

まず、次のコードを見てください。

#!ruby -Knrzlib
eval Zlib.inflate'x�=�Q
� D��OS�c

]r� �����ݳ�By�
              ����O{4�.��i�aQ(`}cB���I2e�ߣ��IeT�јL>������)u,�p�S�W��H~.�,�:
z:Ӊ��g�O7ʲ��vQ�1h�^<����=&�\u7'

ほとんど読めないですね。
ですが、最初の方は普通にRubyのコードです。

#!ruby -Knrzlib

これはShebangですが、コマンドラインオプション-Kn-rzlibを指定しています。
-Knは文字コードがないバイナリとして扱うことを示します。#coding:binaryと同じ意味です。
-rzlibはzlibライブラリをrequireしています。require "zlib"と同じ意味です。

次の行です。

eval Zlib.inflate'…

Zlib.inflateは圧縮したコードを解凍するメソッドです。'以降に圧縮された文字列が続いていることからも、このコードは圧縮されたコードを解凍してevalしていることがわかります。

やってみる

コードを圧縮してこのようなテンプレートに埋め込めばよいことがわかりました。
これを実際にするには、①コードを書く、②圧縮する、③提出する、の3つのステップが必要です。
特に、圧縮率を下げるためには①と②の間を反復することが必要になります。

1. コードを書く

まずはコードを書いてみましょう。(ここではコードの内容は問題ではないです)

agc047_e.rb
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|x|[a,x,3,x]+(0..29).map{v=x+4;u=x*60+9+_1;[a,v,v,v,a,v,3,6,*[a,6,6,6]*(29-_1),?<,6,x,u,a,v,u,v]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}

このコードの長さは216 Bytesです。
書けたので、圧縮してみましょう

2. 圧縮する

ここでは、 https://pastebin.com/TtNNhyND のスクリプトを使って圧縮していきます。

$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
194 B

194 Bytesに縮みました!

3. 提出する

圧縮したら、さあ提出といきたいところですが、ひとつ問題があります。
残念ながら、このコードをコピペしてそのまま提出というわけにはいきません。圧縮して生成されたコードはバイナリです。しかし、AtCoderの提出画面はUTF-8です。多くの場合、圧縮してできたコードはUTF-8として正しくないバイト列を含んでいるので、そのままコピペすると化けてしまいます。

そこで、DevToolsを使って、URIエンコードしたコード直接提出することにします。

提出画面を開いて、DevToolsを出します。ネットワークタブを開いておいてください。
スクリーンショット_2020-08-12_14-10-39.png

この状態で提出ボタンを押してください。DevToolsにリクエストが表示されます。
ここで、submitという名前のリクエストを選んで右クリックし、Copy▶Copy as fetchを押してください。fetchするコードがコピーされます。

rsz_スクリーンショット_2020-08-12_14-25-02.png

そのままConsoleタブを開いて、今コピーされたコードを貼り付けます。
スクリーンショット_2020-08-12_14-31-50.png

(画像には表示されていませんが)sourceCode=の後ろにURIエンコードされたソースを貼り付けていくことになります。

URIエンコードするために https://pastebin.com/TA35nsHZ を使います。(deflate-uriencode.rbとして保存しておいてください)

$ ruby deflate-uriencode.rb agc047_e.rb
194 B
%23%21ruby+-Knrzlib%0Aeval+Zlib.inflate%27x%DA-%8DQ%0A%830%10D%AF%D2Ou%B7A%13%5D%14%2B%1E%24%04%C9%01%0AB%13%094%B9%7Bwc%99%8F%81%99%E1%CD%19%C3%E7ai%9CG%F4%DB%0E%D8%E3%80%06%F7%17j6%E3%C0r%E0%D4%DB%9F%DF%9C%B2%F5%988N%0E%9A%5E%29%BD%B4%B5%B8%B6%04%E3%1A%B7%D4Q%0F%0B%1C%C3%CA%BB%ABJ%DC+a%C7%09%89%5C%D7%E8%E5y%0C%AD%5C%10%D3b%DDD%BC%5C%29%95%3A%FD%A99%C8%9D%16%DDw*%DC%05%A73%04f+%C9%19N%822l%84%B2%DE%97%F2%03%93%919%B0%DE%97%F2%03%93%919%B0%27

deflate-uriencode.rbでagc047_e.rbを変換します。
出力の2行目の%23から始まる文字列をコピーして、先程のsourceCode=の後ろに貼り付けてください。

スクリーンショット_2020-08-12_14-38-54.png

この状態で実行すると提出することができます。

4. コードを修正する(さらに短くなるように)

コードを縮めましょう。圧縮後のコードが短くなるためには、2つの方法があります。

  1. 元のコードを短くする
  2. 圧縮率を上げる

ここでは主に2の方法をやっていきます。1は普通のゴルフの方法ですね。

圧縮率を上げる

どうすれば圧縮率が上がるでしょうか。今、Deflate圧縮を使っていますが、Deflate圧縮はランレングス圧縮とハフマン符号の組み合わせです。このハフマン符号の方に注目します。

ハフマン符号は、圧縮前のエントロピーが小さい程圧縮率が高くなる特徴があります。エントロピーは、符号の出現確率が偏っている程小さくなります。なので、符号の出現確率を偏らせれば偏らせる程圧縮率が上がるということになりそうです。

出現確率を偏らせるには、文字種を減らしたりするのが有効です。最も簡単な方法としては、変数名を変更するなどです。

最初のコードで、変数xvの変数名を変更してtpにしてみましょう。すると、関数名のputsmapと被るので、文字種を減らすことができます。

agc047_e.rb
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{p=t+4;u=t*60+9+_1;[a,p,p,p,a,p,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,p,u,p]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
275 B

あれ?増えてしまいました。
ではpはやめてsにしてみます。

agc047_e.rb
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{s=t+4;u=t*60+9+_1;[a,s,s,s,a,s,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,s,u,s]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
184 B

今度はちゃんと減っています。(なぜ増えたのかわからないので、詳しい方お願いします)

このように、書いて圧縮する試行錯誤を繰り返すことで、コードを縮めることができます。

細かい注意事項など

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

ruby におけるopensslバージョン情報 OPENSSL_VERSION

$ irb
irb(main):001:0> require 'openssl'
=> true
irb(main):002:0> puts OpenSSL::OPENSSL_VERSION
OpenSSL 1.1.1g 21 Apr 2020
=> nil
irb(main):003:0>

又は
$ ruby -ropenssl -e "p OpenSSL::OPENSSL_VERSION"
"OpenSSL 1.1.1g 21 Apr 2020"

Mac ruby 2.0.0におけるDEFAULT_CERT_FILEのディレクトリ情報 - Qiita
https://qiita.com/shiro_yone/items/311be28fa29da54d7f11

irb(main):002:0> require 'openssl'
=> true
irb(main):003:0> p OpenSSL::X509::DEFAULT_CERT_FILE
"/usr/local/stow/openssl-111g/ssl/cert.pem"
=> "/usr/local/stow/openssl-111g/ssl/cert.pem"
irb(main):004:0>

又は

$ ruby -ropenssl -e "p OpenSSL::X509::DEFAULT_CERT_FILE"
"/usr/local/stow/openssl-111g/ssl/cert.pem"

参考
RubyのOpenSSL::OPENSSL_VERSIONはなぜ定数? / マスタカの ChangeLog メモ
https://masutaka.net/chalow/2014-04-08-1.html

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

【Rails】もう迷いたくない。モデル、テーブル、コントローラ、ビューの新規作成。

はじめに

この記事はRailsアプリを立ち上げた後の作業をまとめたものです。
何らかの機能を作る際には、モデルを作ってコントローラ作ってルーティング書いて...といった作業が頻発します。
毎回構文を忘れてしまうので、一連の流れをまとめました。

コントローラの作成

まずはコントローラの作成です。
今回は画像を保存する機能を作るのでimagesとします。

rails g controller images

モデルの作成

下記のコマンドでimageモデルを作りましょう!

rails g model image

これでimageモデルが作成されたと思います。
必要であれば、モデルにバリデーションやアソシエーションを記述しましょう。

テーブル作成

モデルを作成した際にマイグレーションファイルも作成されたと思います。
このファイルを編集して主キーやnull制約などの設定を行います。
私の場合は、以下のようにして”filename”を主キーにし、null制約をかけています。
主キーにしたのでそんな制約要らないかもしれませんが...

class CreateImages < ActiveRecord::Migration[5.2]
  def change
    create_table :images, id: false, primary_key: :filename do |t|
      t.string :filename, null: false
      t.timestamps
    end
  end
end

それではマイグレートを実行し、正常終了すればテーブルが作成されます!

rails db:migrate

ビューの作成

画像の一覧を表示するページということで、index.html.hamlを作りましょう。
これまでの作業でimagesディレクトリが作成されているので、そこに作成します。
ビューの内容については、今回の記事で詰めるところではないので適当に"HelloWorld"を出しておきます。

%h1
  HelloWorld

ルーティング

ここまで来ればほぼ出来たようなものです。
routes.rbにimagesのルーティングを記載します。
今回はresourcesメソッドを使用してindexアクションのみを設定しました。

Rails.application.routes.draw do
  resources :images, only: [:index]
end

結果

出来ました!これで仕事が捗る...!

スクリーンショット 2020-08-12 4.25.04.png

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

Rails Tutorialを咀嚼する【第1章ゼロからデプロイまで】後半

1.4 Gitによるバージョン管理

■Git
バージョン管理ツール。Gitで都度都度作業を保存することで、やり直しができたりする。
addしてからcommitしてpushする。

■Bitbucket
git専門のホスティングサービス。GitHubの仲間。

1.5 デプロイする

■Heroku
Paas。FFFTPとか使わず、開発したものをサーバーにアップロードすることができる。SQLiteが使えないため、若干厄介。

【演習】
1も2も大したことないので省略。

■('a'..'z').to_a.shuffle[0..7].join
ランダムなアルファベット8文字を表示してくれる。
aからzのアルファベットを配列に格納。
配列の順番をシャッフルする。
0から7番目(8個)まで取り出す。
結合して文字列にする。

【演習】
1も2も省略。

分ける必要はなかった。後で結合する。

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

Ruby文字列操作いろいろ

はじめに

Rubyの文字列操作メソッドを勉強するために解いた問題とその回答を記録として残す。

問題1

"This" " is" " a" " pen"を"This is a pen"に変換しなさい。

回答1

"This" + " is" + " a" + " pen"

補足

「+」は文字列を連結することができる。

問題2

"BENZ, BMW, Audi"を["BENZ", " BMW", " Audi"]に変換しなさい。

回答2

"BENZ, BMW, Audi".split(",")

補足

[ ]は配列を表す。
splitメソッドは文字列を分割することができる。
回答のように使用するとカンマで区切ることができる。

問題3

"apple"を"Apple"に変換しなさい。

回答3

"apple".capitalize

補足

capitalizeメソッドは最初の文字を大文字にすることができる。

問題4

"qiita"を"atiiq"に変換しなさい。

回答4

"qiita".reverse

補足

reverseメソッドは文字列を反転することができる。

問題5

"Good morning"を"GOOD MORNING"に変換しなさい。

回答5

"Good morning".upcase

補足

upcaseメソッドは小文字を大文字に変換することができる。

引用

Ruby 2.7.0 リファレンスマニュアル

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