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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

2回答

990閲覧

[Rails] DBにデータを保存する方法は、パラメータを渡す以外にありますか?

anvinon

総合スコア38

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

1クリップ

投稿2017/07/03 03:29

編集2017/07/03 07:12

###開発環境

  • MacOS X 10.11 El Capitan
  • Ruby 2.3.1
  • Ruby on Rails 4.2.6

###発生している問題
Railsでデータベースにデータを保存する方法は、以下の流れの方法しかないのでしょうか?

  1. ビューにフォームを作る
  2. フォームに入力した内容(パラーメータ)をコントローラーで Hoge.create(パラメータ) を使ってデータベースに保存

他にデータベースへ保存する方法があればご教示ください。
よろしくお願いします。

※以下追記

現在ECサイトを開発しております。各商品(product)のページに複数のレビュー(review)を投稿して、複数のコメント(comment)が出来るようにアソシエーションを組みました。そして、commentsテーブルにreview_idカラムを作成し、reviewsテーブルのidをreview_idに保存したいのですが、コントローラーやビューで試行錯誤しても、うまくいかないため、質問をさせて頂きました。下記にソースコードを掲載致しました。

ビューは以下のとおりです。

Ruby

1# app/views/products/show.html.erb 2 3<h1>商品詳細</h1> 4 <%= @product.price %> 5 <%= @product.description %> 6 <%= image_tag @product.image.url %> 7 8 <%= form_tag(:controller => :products, :action => :add) do %> 9 <%= select_tag :item, options_for_select(["01","02","03","04","05"]) %> 10 <%= submit_tag "Add Cart" %> 11 <% end %> 12 13<%= link_to '編集', "/products/#{@product.id}/edit", method: :get %> 14<%= link_to '削除', "/products/#{@product.id}", method: :delete %> 15<% if session[:user_id] %> 16<h2>レビュー投稿</h2> 17 <%= form_for(@review_new, :url => {:controller => :reviews, :action => :create}) do |f| %> 18 <%= f.text_area :text %> 19 <%= f.hidden_field :user_id, :value => "#{session[:user_id]}" %> 20 <%= f.hidden_field :name, :value => "#{session[:name]}" %> 21 <%= f.hidden_field :product_id, :value => "#{@product.id}" %> 22 <%= f.submit %> 23 <% end %> 24<% end %> 25<h2>ユーザーレビュー</h2> 26<% if @reviews.nil? %> 27 まだユーザーレビューはありません。 28<% else %> 29<% @reviews.each do |r| %> 30 ユーザー名:<%= r.name %> 31 レビュー文:<%= r.text %> 32 <%= link_to 'コメントする', "/comments/new", method: :get %> 33 <% r.comments.each do |c| %> 34 コメント:<%= c.text %> 35 <% end %> 36<% end %> 37<% end %>

Ruby

1# app/views/comments/new.html.erb 2 3<h1>コメント投稿</h1> 4<%= form_for(@comment_new, :url => {:controller => :comments, :action => :create}) do |f| %> 5 <%= f.text_area :text %> 6 <%= f.hidden_field :user_id, :value => session[:user_id] %> 7 <%= f.hidden_field :name, :value => session[:name] %> 8 <%= f.hidden_field :product_id, :value => session[:product_show_id] %> 9 <%= f.submit %> 10<% end %>

コントローラーは以下のとおりです。

Ruby

1# app/controllers/products_controller.rb 2 3class ProductsController < ApplicationController 4 5 def index 6 @product_all = Product.all 7 end 8 9 def new 10 @product_new = Product.new 11 @review =Review.new 12 end 13 14 def create 15 Product.create(product_params_create) 16 redirect_to :action => "index" 17 end 18 19 def show 20 @product = Product.find(params[:id]) 21 session[:cart] ||= {} 22 session[:cart]["#{params[:id]}"] = Product.find(params[:id]) 23 @review_new = Review.new 24 session[:product_show_id] = params[:id] 25 @comment_all = Comment.all 26 @reviews = @product.reviews 27 end 28 29 def add 30 if session[:item] == nil then 31 session[:item] ||= {} 32 session[:item]["#{params[:id]}"] = params[:item] 33 else 34 session[:item]["#{params[:id]}"] = params[:item].to_i + session[:item]["#{params[:id]}"].to_i 35 end 36 end 37 38 39 def content 40 end 41 42 def destroy 43 product = Product.find(params[:id]) 44 product.destroy 45 end 46 47 def edit 48 @product_edit = Product.find(params[:id]) 49 end 50 51 def update 52 @product_update = Product.find(params[:id]) 53 @product_update.update(product_params_update) 54 redirect_to :action => "index" 55 end 56 57 def search 58 @products = Product.all 59 if params[:description].present? 60 @products = @products.get_by_description params[:description] 61 end 62 end 63 64private 65 def product_params_create 66 params.require(:product).permit(:price, :description, :image) 67 end 68 69 def product_params_update 70 params.permit(:price, :description, :image) 71 end 72 73end

Ruby

1# app/controllers/reviews_controller.rb 2 3class ReviewsController < ApplicationController 4 5 def index 6 @reviews = Review.all 7 end 8 9 def new 10 @review_new = Review.new 11 end 12 13 def create 14 review = Review.create(review_params_create) 15 redirect_to controller: "products", action: "show", id: "#{session[:product_show_id]}" 16 end 17 18 def edit 19 @review_edit = Review.find(params[:id]) 20 end 21 22 def update 23 @review_update = Review.find(params[:id]) 24 @review_update.update(review_params_update) 25 redirect_to controller: "products", action: "show", id: "#{session[:product_show_id]}" 26 end 27 28 def destroy 29 Review.find(params[:id]).destroy 30 redirect_to controller: "products", action: "show", id: "#{session[:product_show_id]}" 31 end 32 33 private 34 def review_params_create 35 params.require(:review).permit(:text, :user_id, :name, :product_id) 36 end 37 38 def review_params_update 39 params.require(:review).permit(:text) 40 end 41end

Ruby

1# app/controllers/comments_controller.rb 2 3class CommentsController < ApplicationController 4 5 def index 6 @comment_index = Comment.all 7 end 8 9 def new 10 @comment_new = Comment.new 11 end 12 13 def create 14 session[:comment] = Comment.create(comment_params_create) 15 email = User.find(session[:user_id]).email 16 name = session[:name] 17 url = "" 18 if ENV["RAILS_ENV"] == "development" 19 url = "http://localhost:3000/products/#{session[:product_id]}" 20 else 21 url = "https://slup-app.herokuapp.com/products/#{session[:product_id]}" 22 end 23 NoticeNewComment.notice_new_comment(name, url, email).deliver_now 24 redirect_to controller: "products", action: "show", id: "#{session[:product_show_id]}" 25 end 26 27 private 28 def comment_params_create 29 params.require(:comment).permit(:text, :user_id, :review_id) 30 end 31end

モデルは以下のとおりです。

Ruby

1# app/models/comment.rb 2 3class Comment < ActiveRecord::Base 4 belongs_to :user 5 belongs_to :review 6end

Ruby

1# app/models/product.rb 2 3class Product < ActiveRecord::Base 4 mount_uploader :image, ImageUploader 5 #ユーザー名による絞り込み 6 scope :get_by_description, ->(description) {where("description like ?", "%#{description}%")} 7 has_many :reviews 8end

Ruby

1# app/models/review.rb 2 3class Review < ActiveRecord::Base 4 belongs_to :user 5 belongs_to :product 6 has_many :comments 7end

Ruby

1# app/models/user.rb 2 3class User < ActiveRecord::Base 4 has_secure_password 5 validates :name, presence: true, :uniqueness => true 6 validates :email, presence: true, :uniqueness => true 7 has_many :reviews 8 has_many :comments 9end

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

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

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

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

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

guest

回答2

0

ベストアンサー

そんなことはありません。
ただ、Railsレールズの決まりに従うと
入力フォームの作成、ajax等非同期処理の設定、バリデーションとエラーメッセージ、種々のセキュリティ対策をほぼ自動でやってくれる。というだけです。
理由があって一部を置き換えるならいいと思いますが。
全部自作すると言うのならばapiモードを利用するか、いっそrails 以外を選ぶのも手だと思います

あなたの本当にやりたかったことと
何故そのような疑問が生じたかが分かれば
もっと適切な回答ができるかもしれません

追記確認しました。
問題の切り分けはエンジニアとして非常に正しい姿勢ですが。
質問の際は、初心忘るるべからず、必ず最初にやりたかった内容も書くといいと思います。

さて、本題に移りますRailsはこのような場合
accepts_nested_attributes_for

fields_for
さらに
nested_form
というgemを使うというのが定石でした。Rails4までは

が、Rails5.1が出てしまい、状況が変わってきました。
上述のnested_formはRails5をサポートしておらず、同様の働きをするgem cocoonは導入に一手間必要

で、使いやすい仮装DOM,react,vueなどが簡単にRailsに組み込めるようになってしまったからさあ大変
なので、選択肢は4つあります。
0. Railsのバージョンに関係なくcreate等のmethodをremoteにして、js.erbでjavascriptを生成しjquery等のRealDomでhtmlに埋め込む
0. Rails5へのアップデートは考えずnested_form gemを使って簡単に済ます。
0. Rails5へのアップデートを考えて、gem cocoonを使いイベントをjavascriptでゴリゴリ書く
0. Rails5.1にアップデートしてreact.jsやvue.jsの仮装DOMを使い華麗に書く
ちなみに上記4つはRailsを改造?する必要がないレールに乗った方法たちです。
全部書くのも面倒なので、リンク先の記事を読んでみて、方針が決まったら、質問を立て直してください

投稿2017/07/03 03:46

編集2017/07/03 08:19
moke

総合スコア2241

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

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

anvinon

2017/07/03 03:51

ご回答ありがとうございます。 ということは、「Rubyでは出来るが、Rails上では出来ない。ただし、Railsを改造(とでも言うのでしょうか)した場合は、出来る」ということでしょうか?
moke

2017/07/03 07:24 編集

その通りです。 ただ何がしたいかがわからないと 何処まで改造すればいいかわからないですし、もしかしたら改造しなくていいかもしれないしですしね。 もちろんそれをするメリットもわからないです。
anvinon

2017/07/03 07:14

質問を編集して、追記しました。恐れ入りますが、ご覧いただけないでしょうか? よろしくお願いします。
moke

2017/07/03 07:25

少々お待ちを
moke

2017/07/03 08:20

回答を編集しました
anvinon

2017/07/03 08:27

ありがとうございました。とても丁寧に教えてくださり、大変ありがたいです。 リンク先、拝見致します。また何かあれば質問を立て直したいと思います。 ありがとうございました。ベストアンサーに選ばせて頂きます。
maisumakun

2017/07/03 12:00

nested_formの開発が止まっているという情報、ありがとうございます。 Rails 5ではどうしたものかなあ…
moke

2017/07/03 12:37 編集

maisumakun様のお役に立てて嬉しいです。 私もnested_formのが好きです。cocoonはなんだかなぁって感じです。 確かにnested_formは対応してないですが、単純な構造なのでちょっといじれば動くとは思いますが…。 そもそも、accepts_nested_attributes_for自体が最近あまり尊重されていない気がします。 それに、vueがなかなかいいですからねー。最後発だけあって洗練されてますし まだ存在は確認できていませんが、railsのbuilderで直接書き下せる構造ですし。 VueDataScooperというjsライブラリと"vue-rails-form-builder"というgemにもう少し 手を加えればscaffoldのコードそのままで、仮装DOMになんていうのも可能かもしれません。 とりあえず、情報提供までに
guest

0

何を目的としてフォームを介さずにデータを保存したいのかを質問にはっきり書いてください。
そのほうが正確な回答が得られます。

とりあえず、DBのデータを操作する方法としては以下の3通りあります。

  • rails consoleを使う
  • rails runnerでバッチを実行
  • rails dbconsoleでSQLを直接実行する

投稿2017/07/03 04:01

mingos

総合スコア4025

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

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

maisumakun

2017/07/03 04:09 編集

イレギュラーなデータ修正など定型的に発生する作業でない場合は、rails cなどで直接手作業で変換してしまう、のもじゅうぶん実用的です。
anvinon

2017/07/03 07:26 編集

質問文を編集して追記をしました。恐れ入りますが、ご覧いただけないでしょうか? よろしくお願いします。 > maisumakun様 なるほど、コンソールからのほうがいい場合もあるのですね。ありがとうございます。
anvinon

2017/07/03 11:56

mingos様 moke様から頂いたご回答で解決しました。mingos様もありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問