RailsのArelの使い方
RailsでArelを使うときは、下記サイトをいつも参照させていただいていましたが、自分メモ用として転載します。
メモ || Arelのwhere系メソッド一覧 User.w...
User.where(User.arel_table[:name].eq("aa")).to_sql # => SELECT "users".* FROM "users" WHERE "users"."name" = 'aa' User.where(User.arel_table[:name].eq(nil)).to_sql # => SELECT "users".* FROM "users" WHERE "users"."name" IS NULL User.where(User.arel_table[:name].eq_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" = 'aa' AND "users"."name" = 'bb')) User.where(User.arel_table[:name].eq_all(["aa",nil])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" = 'aa' AND "users"."name" IS NULL)) User.where(User.arel_table[:name].eq_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" = 'aa' OR "users"."name" = 'bb')) User.where(User.arel_table[:name].eq_any(["aa",nil])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" = 'aa' OR "users"."name" IS NULL)) User.where(User.arel_table[:name].not_eq("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" != 'aa') User.where(User.arel_table[:name].not_eq(nil)).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" IS NOT NULL) User.where(User.arel_table[:name].not_eq_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" != 'aa' AND "users"."name" != 'bb')) User.where(User.arel_table[:name].not_eq_all(["aa",nil])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" != 'aa' AND "users"."name" IS NOT NULL)) User.where(User.arel_table[:name].not_eq_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" != 'aa' OR "users"."name" != 'bb')) User.where(User.arel_table[:name].not_eq_any(["aa",nil])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" != 'aa' OR "users"."name" IS NOT NULL)) User.where(User.arel_table[:name].gt("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" > 'aa') User.where(User.arel_table[:name].gt_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" > 'aa' AND "users"."name" > 'bb')) User.where(User.arel_table[:name].gt_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" > 'aa' OR "users"."name" > 'bb')) User.where(User.arel_table[:name].gteq("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" >= 'aa') User.where(User.arel_table[:name].gteq_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" >= 'aa' AND "users"."name" >= 'bb')) User.where(User.arel_table[:name].gteq_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" >= 'aa' OR "users"."name" >= 'bb')) User.where(User.arel_table[:name].lt("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" < 'aa') User.where(User.arel_table[:name].lt_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" < 'aa' AND "users"."name" < 'bb')) User.where(User.arel_table[:name].lt_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" < 'aa' OR "users"."name" < 'bb')) User.where(User.arel_table[:name].lteq("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" <= 'aa') User.where(User.arel_table[:name].lteq_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" <= 'aa' AND "users"."name" <= 'bb')) User.where(User.arel_table[:name].lteq_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" <= 'aa' OR "users"."name" <= 'bb')) User.where(User.arel_table[:name].in(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE "users"."name" IN ('aa', 'bb') User.where(User.arel_table[:birthday].in('1980-01-01'.to_date..'1990-12-31'.to_date)).to_sql # => SELECT "users".* FROM "users" WHERE "users"."birthday" BETWEEN '1980-01-01' AND '1990-12-31' User.where(User.arel_table[:name].in_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" IN ('aa') AND "users"."name" IN ('bb'))) User.where(User.arel_table[:name].in_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" IN ('aa') OR "users"."name" IN ('bb'))) User.where(User.arel_table[:name].not_in(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" NOT IN ('aa', 'bb')) User.where(User.arel_table[:name].not_in_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" NOT IN ('aa') AND "users"."name" NOT IN ('bb'))) User.where(User.arel_table[:name].not_in_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" NOT IN ('aa') OR "users"."name" NOT IN ('bb'))) User.where(User.arel_table[:name].matches("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" LIKE 'aa') User.where(User.arel_table[:name].matches("%aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" LIKE '%aa') User.where(User.arel_table[:name].matches_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" LIKE 'aa' AND "users"."name" LIKE 'bb')) User.where(User.arel_table[:name].matches_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" LIKE 'aa' OR "users"."name" LIKE 'bb')) User.where(User.arel_table[:name].does_not_match("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" NOT LIKE 'aa') User.where(User.arel_table[:name].does_not_match_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" NOT LIKE 'aa' AND "users"."name" NOT LIKE 'bb')) User.where(User.arel_table[:name].does_not_match_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" NOT LIKE 'aa' OR "users"."name" NOT LIKE 'bb'))
受託開発で炎上しないためのチェックリスト
未来への自分の戒めとして「受託開発で炎上しないためのチェックリスト」を作成してみました。基本的なことばかりだけど、この基本をきちんと押さえておくことが大切だと思うのです。
・プロジェクトリーダーを立てているか
・リードエンジニア(技術責任者)を立てているか
・スケジュールを立てているか
・スケジュールに予備日を設けているか
・進捗状況を把握できているか
・遅れに対する対策を講じているか
・メンバーとスケジュール共有したか
・メンバーに担当タスクと期限日を認識させたか
・メンバーと定期的に状況共有しているか
・お客様とスケジュール共有したか
・お客様にお客様担当タスクと期限日を認識させたか
・定期的にお客様に状況を報告しているか
・仕様書/設計書を作成したか
・仕様書/設計書のレビューを行っているか
・仕様書の内容についてお客様と認識合わせしたか
・仕様/設計FIXしたか
・コードレビューを行っているか
(レビューポイントはリーダブルか/DRYか/再利用しやすいか/拡張しやすいか)
・テスト仕様書/テストコードを作成したか
・テスト仕様書/テストコードのレビューを行っているか
・検収時の指摘事項に対する対応として、やる/やらない/別見積を明確にお客様に提示しているか
・検収完了の連絡をいただいたか
minttyのカッコいい設定
minttyは設定次第でカッコいい見た目になるのでとても気に入っています。
僕の.minttyrcは↓のような感じです。
BoldAsFont=no FontHeight=11 Font=Inconsolata FontIsBold=no BackgroundColour=0,0,0 ForegroundColour=245,245,245 Transparency=medium Columns=160 Rows=40 Black=0,0,0 Red=255,204,153 Green=204,255,204 Yellow=255,255,153 Blue=153,204,255 Magenta=204,153,255 Cyan=204,255,255 White=255,255,255 BoldRed=255,204,153 BoldGreen=204,255,204 BoldYellow=255,255,153 BoldBlue=153,204,255 BoldMagenta=204,153,255 BoldCyan=204,255,255 BoldWhite=255,255,255 CopyOnSelect=no
見た目こんな感じになります。
設定はこちらを参考にさせていただきました。感謝です。
Cygwin Terminal (Mintty) の設定 - 計算物理屋の研究備忘録
フォントはこちらを使用しています。
Inconsolata
RubyでUTF-8変換時にUndefinedConversionが出た件
shift_jisで書かれたCSVをUTF-8に変換して取り込み処理をするところで、Encoding::UndefinedConversionError が吐かれてた。
str.encode('utf-8', 'shift_jis') # => Encoding::UndefinedConversionError: "\x87@" from Shift_JIS to UTF-8
なんでだと思って調べてたところ、shift_jisでは対応していない①とか㈱とかの機種依存文字を変換しようとしていたからエラー出ていたみたい。なのでCP932(Windows-31J)使えば解決。
str.encode('utf-8', 'CP932') # => ①㈱
対応しない文字を強制的に置き換えするときは
str.encode("Shift_JIS", "UTF-8", { :invalid => :replace, :undef => :replace, :replace => "〓"})
MySQLのユーザ管理コマンド
ユーザ管理
-- ユーザリスト SELECT Host, User, Password FROM mysql.user; -- ユーザ作成 CREATE USER 'kinosuke'@'localhost' IDENTIFIED BY 'some password'; -- ユーザ作成 -- GRANT使う&パスワードハッシュ使う版 GRANT USAGE ON *.* TO 'kinosuke'@'localhost' IDENTIFIED BY PASSWORD '*235FBD5A94312B29D808844FC68009764D01AD27'; -- ユーザ名、ホスト変更 RENAME USER 'kinosuke'@'localhost' TO 'new_name'@'new_host'; -- パスワード変更 SET PASSWORD FOR 'kinosuke'@'localhost' = PASSWORD('some password'); -- ユーザ削除 DROP USER 'kinosuke'@'localhost';
権限変更
-- 権限確認 SHOW GRANTS FOR 'kinosuke'@'localhost'; -- グローバルレベル: GRANT 権限 ON *.* TO 'kinosuke'@'localhost'; -- データベースレベル: GRANT 権限 ON db_name.* TO 'kinosuke'@'localhost'; -- テーブルレベル: GRANT 権限 ON db_name.table_name TO 'kinosuke'@'localhost'; -- カラムレベル: GRANT 権限 (カラム1, カラム2, ...) ON db_name.table_name TO 'kinosuke'@'localhost'; -- 例) 特定DBのREADのみ GRANT SELECT ON `mydb`.* TO 'kinosuke'@'localhost';
rbenvでRubyをインストール~gemsetの設定
Rubyインストール
# rbenv をインストール(clone)する git clone https://github.com/sstephenson/rbenv.git ~/.rbenv # bash_profile 設定追加 # vim ~/.bash_profile export PATH="$HOME/.rbenv/bin:$PATH" eval "$(rbenv init -)" # 上記設定の再読み込み exec $SHELL -l # rbenvの確認 rbenv --version # ruby-build を インストール(clone)する git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build # ruby の最新版を確認 rbenv install --list # ruby のインストール RUBY_BUILD_CURL_OPTS=--tlsv1.2 rbenv install -v 2.0.0-p451 # 再読み込み rbenv rehash # installed 確認 rbenv versions # デフォルト設定 rbenv global 2.0.0-p451 # カレントディレクトリで使う rbenv local 2.0.0-p451
参考にさせていただきました!感謝!
rbenv を使って ruby をインストールする(CentOS編) - Qiita
gemsetの設定
# ruby-gemset を インストール(clone)する cd ~/.rbenv/plugins/ git clone https://github.com/jf/rbenv-gemset.git # gemset 作成 rbnev gemset list rbenv gemset create 2.0.0-p451 redmine # 削除するとき rbenv gemset delete 2.0.0-p451 redmine # 指定dir以下で gemset使う cd /var/www/app/redmine/ echo redmine > .rbenv-gemsets rbenv rehash # カレントディレクトリで有効なgemset rbenv gemset active
参考にさせていただきました!感謝!
Redirecting...
Rails×SES バウンスメール(不達メール)対策
「SESで不達メールが多いから、対策してくれなかったらSES止めるよ」って過去にAWSから言われたことがあって、そのときの対応メモを書きだしてみた。
対応の基本的な流れ
SESは不達メールがあった場合に特定のURLに対してリクエストをjson付きで投げてくれるので、それを特定のURLでうけてJSONパースして、そのパースしたJSONの中にメールアドレスがあるので、それをブラックリストテーブルか何か作ってINSERTして、メール送信の時はそのブラックリストテーブルを見て、送っていいメールアドレスいいか判定するって感じ。
AWSの設定はここを参考に。
Amazon SESのBounce SNS通知をRailsで処理する|WEBデザイン Tips
Railsのソースはこんな感じ。
app/controllers/api/aws_controller.rb
# # AWSから飛んできたリクエストを受け取るAPI # require 'json' require 'open-uri' class Api::AwsController < ActionController::Base skip_before_filter :verify_authenticity_token # # SESからリクエストされる # 不達メールアドレスリストをブラックリストに登録する # def receive_bounce_notice # data = JSON.parse(dummy_raw_post) # debug用 data = JSON.parse(request.raw_post) # Subscription認証用URLを開いて認証を完了する if data['SubscribeURL'].present? open(data['SubscribeURL']) # ブラックリスト登録する else data2 = JSON.load(data['Message']) type = data2['notificationType'] if type=='Bounce' bounce = data2['bounce'] bouncerecps = bounce['bouncedRecipients'] bouncerecps.each do |recp| email = recp['emailAddress'] if BouncedEmailAddress.where(email: email).blank? BouncedEmailAddress.create(email: email) end end end end render text: "" end private def dummy_raw_post str =<<EOS { "Type" : "Notification", "MessageId" : "463fbb0b-63ea-4a6d-90c5-33c8686e3bd1", "TopicArn" : "arn:aws:sns:us-east-1:811118151095:suz-lab-ses", "Message" : { "notificationType":"Bounce", "bounce":{ "bounceType":"Permanent", "bounceSubType": "General", "bouncedRecipients":[ { "emailAddress":"recipient1@example.com" }, { "emailAddress":"recipient2@example.com" } ], "timestamp":"2012-05-25T14:59:38.237-07:00", "feedbackId":"00000137860315fd-869464a4-8680-4114-98d3-716fe35851f9-000000" }, "mail":{ "timestamp":"2012-05-25T14:59:38.237-07:00", "messageId":"00000137860315fd-34208509-5b74-41f3-95c5-22c1edc3c924-000000", "source":"email_1337983178237@amazon.com", "destination":[ "recipient1@example.com", "recipient2@example.com", "recipient3@example.com", "recipient4@example.com" ] } }, "Timestamp" : "2012-10-08T13:00:40.691Z", "SignatureVersion" : "1", "Signature" : "FDNBWbFhc5MXs+2tjw327zXhiKca3GLHbbVEN8vUmLAmnj60...", "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleN...", "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action..." } EOS return str end end
lib/mail/email_interceptor.rb
# # email_interceptor は、action mailer の # before action 的な動きをしてくれるヤツ(らしい。。) # class EmailInterceptor # # ブラックリスト宛には送らない # def self.delivering_email(message) _to = message.to message.to = probe_email(message.to) if message.to.present? message.cc = probe_email(message.cc) if message.cc.present? message.bcc = probe_email(message.bcc) if message.bcc.present? message = set_to(message, _to) # rescue => e # binding.pry # Rails.logger.error(e.to_s << "\n" << e.backtrace.join("\n")) end # # ブラックリストに載っていないアドレスだけにする # def self.probe_email(emails) bounced_email_addresses = BouncedEmailAddress.pluck(:email) list = [] emails = [emails] if emails.instance_of?(String) emails.each do |email| list << email if !(bounced_email_addresses.include?(email)) end return list end # # toがすべて空だった場合 # 送信処理するとエラーになるため、 # とりあえず仮で送信先を入れる # def self.set_to(message, _to) return message if message.to.present? # ブラックリストに送ろうとしたメールはここに送信する message.to = ["sample@gmail.com"] # message.subject = "Can not sent to bouced email address" return message end end
email_interceptor.rb は、lib/mail の配下とかにおいて、
config/application.rb で読みこむようにすればOK。
class Application < Rails::Application # 略 config.autoload_paths += %W(#{config.root}/lib/mail) # 略
※BouncedEmailAddressというモデルはブラックリスト用テーブル。
メールアドレスを格納しているだけなのでソースは割愛。