質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.45%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

8029閲覧

【rails】投稿者のIPアドレスを取得したいです。

yuta_tokyo

総合スコア35

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

2クリップ

投稿2017/01/19 00:52

編集2017/01/21 03:29

rails初心者です。

現在練習で簡単な掲示板を製作しています。
投稿者のIPアドレスを取得したいのですが、今風のおすすめの方法など教えて頂きたいです。

==========
<追記>
Postにcommentを紐づけた実装をしています。
・問題
Post投稿者のIDは取得でき、データーベースに保存できたのだが、
Comment投稿者のIDを取得することができない。
コメントはsaveされるのだが、ipカラムにコメント投稿者のipが入っていない状態。

以下が該当と予想されるコードです。
▼commnets_controller.rb

class CommentsController < ApplicationController def create @post = Post.find(params[:post_id]) @comment = @post.comments.create(comment_params) @comment.ip = request.remote_ip p request.remote_ip p @comment.ip respond_to do |format| if @comment.valid? format.html { redirect_to post_path(@post), notice: 'コメントが完了しました!!' } else format.html { redirect_to post_path(@post), notice: 'コメントに失敗しました。ニックネームとコメントを入れてください。' } end end end private def comment_params params.require(:comment).permit(:commenter, :body) end end

▼_form.html.erb(コメントの投稿フォームです。postのshow.html.erbに紐付けられています。)

<%= form_for( [@post, @post.comments.build] ) do |f| %> <div class="field"> <%= f.label :commenter, "ニックネーム" %> <%= f.text_field :commenter,placeholder: :"名無しさん" %> </div> <div class="field"> <%= f.label :body, "コメント" %> <%= f.text_area :body, cols: 60, rows: 3 %> </div> <div class="actions"> <%= f.submit "コメント投稿" %> </div> <% end %>

▼commentテーブルのカラムです

=> Comment(id: integer, commenter: string, body: text, post_id: integer, created_at: datetime, updated_at: datetime, ip: string)

<追記 2016.01.21>

以下のコードでmd5でハッシュ化したidの上8桁の取得が完了しました!!
文法ミスあれば教えていただきたいです!

▼投稿者のID

<%= Digest::MD5.hexdigest("request.remote_ip.to_s + #{@post.created_at.strftime("%Y%m%d")} + #{@post.id}")[0,8] %>

▼コメンターのID

名前:<%= comment.commenter %> <%= comment.created_at.strftime("%y/%m/%d(#{%w(日 月 火 水 木 金 土)[comment.created_at.wday]}) %H:%M:%S") %> ID:<%= Digest::MD5.hexdigest("request.remote_ip.to_s + #{comment.created_at.strftime("%Y%m%d")} + #{@post.id}")[0,8] %> <%= simple_format comment.body %>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

request.remote_ipで良いのではないでしょうか。

投稿2017/01/19 01:03

hn1

総合スコア303

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuta_tokyo

2017/01/19 01:05

モデルでIP用のカラムを製作する必要はないのでしょうか? 全体の流れを教えて頂きたいです! よろしくお願いします!
hn1

2017/01/19 01:18

掲示板を作られているとのことなので、 投稿内容を保存するモデルにIPアドレスのカラムは必要でしょうね。 書き込み時に呼ばれるアクションでrequest.remote_ipでIPアドレスを取得し、 掲示内容を保存するモデルにIPアドレスを設定すればよいです。
yuta_tokyo

2017/01/19 01:30

その際、IPアドレスのデータ型はなにがよろしいのでしょうか? よろしくお願いします!
hn1

2017/01/19 01:40

文字列型で良いと思いますよ
yuta_tokyo

2017/01/20 09:29

hn1様 丁寧かつ的確なご回答ありがとうございました! 今回は一番回答を早くしてくださったmingos様にベストアンサーをつけさせて頂きます! 今後ともよろしくおねがいします。
guest

0

ベストアンサー

追記

まずは、気になるところを抜き出しますね。

ruby

1# フォームの内容でコメントをデータベースへ保存 2# その結果をCommentのインスタンスとして@commentで受け取る 3@comment = @post.comments.create(comment_params) 4 5# @comment.ipにIPアドレスを代入 6# データベースには保存されず、メモリにあるだけ 7@comment.ip = request.remote_ip 8... 9 10# エラーチェックはするが、saveしていないので 11# @comment.ipはデータベースに入らない 12if @comment.valid? 13 ... 14end

コメントをつけたので、なんとなく原因が分かったかもしれませんが、
valid?を呼び出すならば、createはしないほうがいいです。
createの中でvalid?も読んでくれるのですが、流れとしておかしくなるので。

以下の流れに沿ったコードを記載します。

  • フォームの値を@commentにセット
  • @comment.ipにコメントを投稿した人のIPアドレスをセット
  • @comment.valid?でエラーチェックし、問題なければ、@comment.saveでデータベースに保存

ruby

1class CommentsController < ApplicationController 2 def create 3 @post = Post.find(params[:post_id]) 4 5 # データベースに保存せずにインスタンスを作るだけ 6 @comment = @post.comments.new(comment_params) 7 @comment.ip = request.remote_ip 8 p request.remote_ip 9 p @comment.ip 10 11 respond_to do |format| 12 # エラーチェック&保存 13 if @comment.valid? && @comment.save 14 format.html { redirect_to post_path(@post), notice: 'コメントが完了しました!!' } 15 else 16 format.html { redirect_to post_path(@post), notice: 'コメントに失敗しました。ニックネームとコメントを入れてください。' } 17 end 18 end 19 end

以前の回答

コントローラ内でrequest.remote_ipを呼べば取得する事が出来ます。

マイグレーションは予想がついたという事ですが、一応書いておくこんな感じです。
モデル名は仮なのでそちらの環境に合わせてください。
必要そうなところだけを書くとこうなるかと。

ruby

1class CreatePosts < ActiveRecord::Migration 2 def change 3 create_table :posts do |t| 4 ... 5 t.string :remote_ip, null: false 6 ... 7 end 8 end 9end 10 11class XxxController < ApplicationController 12 def xxxx 13 post = Post.new(params[:post].permit!) 14 post.remote_ip = request.remote_ip 15 ... 16 post.save 17 end 18end

投稿2017/01/19 00:56

編集2017/01/20 08:35
mingos

総合スコア4032

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuta_tokyo

2017/01/19 01:02

モデルでIP用のカラムを製作する必要はないのでしょうか? 全体の流れを教えて頂きたいです! よろしくお願いします!
mingos

2017/01/19 01:12

「投稿者のIPアドレスを取得したい」という質問なので、request.remote_ipで取得できます。 という回答にしかならないんですね。 「投稿者のIPアドレスを取得して、データベースに保存したい」 というような質問の仕方ならもう少し違う回答になります。 データベースに保存する必要があるのであれば、モデルにIP用のカラムを追加する必要が出てきます。 rake db:migrateの実行も必要です。 それができれば、コントローラでIPを取得してモデルにセットして、saveすれば良いです。
yuta_tokyo

2017/01/19 01:20

表現に語弊がありましたこと、申し訳ありません。 今回のIP取得は"投稿者のIPアドレス開示"を想定して実装しようと考えています。 後に投稿者のIPを確認するには、データーベースに保存されていなければならないのでしょうか? 初歩的な質問かとおもいますが、よろしくお願いします。
mingos

2017/01/19 01:31 編集

yuta_tokyoさんが何がしたいのかが明確になっていないので、あやふやになっているところがありそうです。 そこから整理しましょう。 投稿者のIPは、スパムや規約違反などの理由での連続投稿の禁止で使うことはないという事で良いでしょうか。 後で、投稿者のIPを使って何か作業をする必要がない。 投稿前に「あなたのIPはこれですよ」という表示をするだけ。 データベースに保存はしない。 これでよければ、ビューに<%= request.remote_ip %>と書けばOKです。 投稿者のIPは、投稿されたその時にしか取得できません。 従って、後で管理者であるyuta_tokyoさんが投稿者のIPを確認したい場合は、 どこかに保存しておかなければなりません。 投稿者のIPは、投稿内容のモデルとセットになっているのが自然なので、 投稿内容のモデルにIP用のカラムを追加する必要があるというわけです。
yuta_tokyo

2017/01/19 01:39

なるほど、IPを取得するとスパム行為の排除など様々なことできるんですね!! 自分が今回行いたかったことは、投稿者のIPアドレスを後に確認できるようにすることです。 ↑に関しては大体予想がつきました! 2つ質問です。 ・IPのデータ型は何が望ましいですか? ・IP取得にかんして注意すべき点を教えていただきたいです(webサイトの公開を前提に) 先月からコーディングを勉強し始めてて初心者なので、実践的なコーディング手法や一般的な考え、また脆弱性についてもっと知りたいです!!
mingos

2017/01/19 01:53

・IPのデータ型は文字列で良いと思います。 ・IP取得をする事自体は法令違反とかにはならないので、問題ありません。 分析する時に考えておきたいのは、ネットカフェやフリーWifi、会社などからアクセスされた時は別のPCでも同じIPとなるため、IPだけでは個人を特定できないという事ですね。 なので、スパムなどの理由で投稿をIPで禁止しようとしたときは、個人 or 組織となってしまいます。 それでいいのですが、この調子でIPでどんどん投稿禁止すると利用者が減ってしまい廃れてしまうので、 禁止するにしても24時間投稿を禁止するとか期限付きで解除してもいいかもしれないです。
yuta_tokyo

2017/01/20 08:07

mingos様 詳しいご返信ありがとうございます。 自分でipアドレスの取得を試みました。 結果としては、post投稿者のipは取得できたのですが、comment(postの子要素)投稿者のipが取得できない状態でいます。 一番上の質問欄に追記しましたので、ご指導いただきたいです!
mingos

2017/01/20 08:36

追記しましたので、お試しください。
yuta_tokyo

2017/01/20 09:28

mingos様 いつも、早急なご返信そして丁寧なご返信ありがとうございます! データーベースにipを挿入することができました。 インスタンスについてより理解がましました! 今回のようなコミュニティーがあることに感服しました! 本当にありがとうございました。
yuta_tokyo

2017/01/21 00:06 編集

mingos様 脆弱性について質問させてください。 IPアドレスをデーターベースに保存するのは危なくないのでしょうか? 現在2chのようなIPアドレスと日付、スレのurl_id、1日ごとの乱数を元にハッシュ化された値を各ユーザーにIDとして付与しようとかんがえています。 そして、今回ハッシュ化に不可逆なmd5を使用するので、もしIPをデーターベースに保存しなかった場合、IP開示の際に確認できなくなるだろうと考えています。 以上を踏まえてIPをデーターベースに保存することは危険性を伴わないのかという質問をさせてください(なお、ユーザーのログイン機能はありません)
mingos

2017/01/21 00:34

管理者がIPアドレスを保存する事と、 IPアドレスを不特定多数の利用者に公開する事、 これはまったく別の話になるので、分けて考えてください。 管理者側の視点として、IPアドレスをDBに保存する事自体には何の問題もありません。 これが問題になるのであれば、Webサービスを公開する際には必ずWebサーバ(ApacheやNginx)が必要となります。 これのソフトはDBではありませんが、アクセスログをサーバ上に保存します。 そして、アクセスログにはIPアドレスが記載されます。 railsでIPを保存しようしまいが、Webサービスとして公開する段階でアクセスログという形でファイル形式でIPは保存されてしまうのです。 また、問題のある書き込みがされた際に、借りているサーバの管理会社やプロバイダからIPアドレスの開示を求められるケースもありえますので、IPと書き込みの紐づけをしておき、いつでも協力できるようにしておくのも管理者の義務です。 一方、利用者側の視点として、IPアドレスが公開される事は問題があるケースがあります。 固定IPを除けば、一定時間が過ぎればIPは変化するのですが、 短期間であれば、IPは変化しないので個人というかアクセス元の場所を特定できますので、何らかの悪用がされる可能性もあるでしょう。 なので、掲示板の表示内容にIPアドレスを含めるのは良くありません。 なので、掲示板の公開画面ではIPではなく、一時的なIDを付与してそれを表示するという形が望ましいと思います。
mingos

2017/01/21 00:50

脆弱性の話でいうと、プログラムのミス以外ではサーバにsshで直接ログインされてしまうケースがありえます。 これはrailsとは関係なく、Linuxなどのサーバ管理のセキュリティの話になって来ますが、インターネット上でサービスを提供する以上、そちらも学ぶ必要が出てきます。 サーバに侵入されれば、DBもrailsのソースも全部見られてしまうのでどうしようもありません。
yuta_tokyo

2017/01/21 01:31

mingos様 毎回丁寧かつ分かりやすい説明ありがとうございます。 ipとapacheについて理解が深まりました。 サーバーはレンタルサーバーを利用する予定です。 "IPと書き込みの紐づけ"はデーターベースで行うということでよろしいでしょうか?
mingos

2017/01/21 01:33

はい、投稿モデルにIPを保存する今の形で紐づけはOKです。
yuta_tokyo

2017/01/21 01:41

投稿モデルにハッシュ化されたIPや日付などで製作されたIDを追加するIDカラムを追加するというのも”一般的"なのでしょうか?
mingos

2017/01/21 02:02

別の質問の回答にも書きましたが、IPはそこまで心配するようなものではないので、そのままの形で保存するのが一般的でしょう。 ハッシュ化したら、あとで開示を求められた時にどうやって元のIPを作ればいいんでしょうか? md5はsha1は一方通行なので、生成された文字列から元の文字列は分かりませんので、アクセスログに記載されているIPの一覧を取り出し、DBのハッシュ値と比較するようなプログラムを自作して、長時間動かさないといけません。 そこまでやるのは割りに合いませんので、そのまま保存します。 IDについては、投稿モデルにある情報から生成できるので、DBにカラムとして保存はせず、ビューで Digest::MD5.hexdigest("#{IP}#{日付(yyyymmd)}#{スレッドID}"); と毎回表示すればいいと思います。 md5は同じ文字列を渡せば毎回同じ値が返ってくるわけですから、 IDを生成する材料だけを投稿モデルに入れておき、生成される結果のハッシュ値は保存する必要がないです。 日付を8桁にしておけば、同じ日付内であれば同じIP、同じスレッドからは同じIDが生成されるので、ある程度同じユーザからの書き込みである事を担保できるのではないでしょうか。
yuta_tokyo

2017/01/21 03:30

mingos様 ご回答ありがとうございます! 質問本文に追記として新しく追加したコードをのせましたので確認していただきたいです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.45%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問