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

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

ただいまの
回答率

90.50%

  • Ruby

    9425questions

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

  • Ruby on Rails

    8849questions

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

  • Ruby on Rails 4

    2542questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,316

anvinon

score 30

開発環境

  • 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に保存したいのですが、コントローラーやビューで試行錯誤しても、うまくいかないため、質問をさせて頂きました。下記にソースコードを掲載致しました。

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

# app/views/products/show.html.erb

<h1>商品詳細</h1>
  <%= @product.price %>
  <%= @product.description %>
  <%= image_tag @product.image.url %>

  <%= form_tag(:controller => :products, :action => :add) do %>
    <%= select_tag :item, options_for_select(["01","02","03","04","05"]) %>
    <%= submit_tag "Add Cart" %>
  <% end %>

<%= link_to '編集', "/products/#{@product.id}/edit", method: :get %>
<%= link_to '削除', "/products/#{@product.id}", method: :delete %>
<% if session[:user_id] %>
<h2>レビュー投稿</h2>
  <%= form_for(@review_new, :url => {:controller => :reviews, :action => :create}) do |f| %>
    <%= f.text_area :text %>
    <%= f.hidden_field :user_id, :value => "#{session[:user_id]}" %>
    <%= f.hidden_field :name, :value => "#{session[:name]}" %>
    <%= f.hidden_field :product_id, :value => "#{@product.id}" %>
    <%= f.submit %>
  <% end %>
<% end %>
<h2>ユーザーレビュー</h2>
<% if @reviews.nil? %>
  まだユーザーレビューはありません。
<% else %>
<% @reviews.each do |r| %>
  ユーザー名:<%= r.name %>
  レビュー文:<%= r.text %>
  <%= link_to 'コメントする', "/comments/new", method: :get %>
  <% r.comments.each do |c| %>
  コメント:<%= c.text %>
  <% end %>
<% end %>
<% end %>
# app/views/comments/new.html.erb

<h1>コメント投稿</h1>
<%= form_for(@comment_new, :url => {:controller => :comments, :action => :create}) do |f| %>
  <%= f.text_area :text %>
  <%= f.hidden_field :user_id, :value => session[:user_id] %>
  <%= f.hidden_field :name, :value => session[:name] %>
  <%= f.hidden_field :product_id, :value => session[:product_show_id] %>
  <%= f.submit %>
<% end %>


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

# app/controllers/products_controller.rb

class ProductsController < ApplicationController

  def index
    @product_all = Product.all
  end

  def new
    @product_new = Product.new
    @review =Review.new
   end

  def create
    Product.create(product_params_create)
    redirect_to :action => "index"
  end

  def show
    @product = Product.find(params[:id])
    session[:cart] ||= {}
    session[:cart]["#{params[:id]}"] = Product.find(params[:id])
    @review_new = Review.new
    session[:product_show_id] = params[:id]
    @comment_all = Comment.all
    @reviews = @product.reviews
  end

  def add
    if session[:item] == nil then
      session[:item] ||= {}
      session[:item]["#{params[:id]}"] = params[:item]
    else
      session[:item]["#{params[:id]}"] = params[:item].to_i + session[:item]["#{params[:id]}"].to_i
    end
  end


  def content
  end

  def destroy
    product = Product.find(params[:id])
    product.destroy
  end

  def edit
    @product_edit = Product.find(params[:id])
  end

  def update
    @product_update = Product.find(params[:id])
    @product_update.update(product_params_update)
    redirect_to :action => "index"
  end

  def search
    @products = Product.all
    if params[:description].present?
      @products = @products.get_by_description params[:description]
    end
  end

private
  def product_params_create
    params.require(:product).permit(:price, :description, :image)
  end

  def product_params_update
    params.permit(:price, :description, :image)
  end

end
# app/controllers/reviews_controller.rb

class ReviewsController < ApplicationController

  def index
    @reviews = Review.all
  end

  def new
    @review_new = Review.new
  end

  def create
    review  =  Review.create(review_params_create)
    redirect_to controller: "products", action: "show", id: "#{session[:product_show_id]}"
  end

  def edit
    @review_edit = Review.find(params[:id])
  end

  def update
    @review_update = Review.find(params[:id])
    @review_update.update(review_params_update)
    redirect_to controller: "products", action: "show", id: "#{session[:product_show_id]}"
  end

  def destroy
    Review.find(params[:id]).destroy
    redirect_to controller: "products", action: "show", id: "#{session[:product_show_id]}"
  end

  private
    def review_params_create
      params.require(:review).permit(:text, :user_id, :name, :product_id)
    end

    def review_params_update
      params.require(:review).permit(:text)
    end
end
# app/controllers/comments_controller.rb

class CommentsController < ApplicationController

    def index
      @comment_index = Comment.all
    end

    def new
      @comment_new = Comment.new
    end

    def create
      session[:comment] = Comment.create(comment_params_create)
      email = User.find(session[:user_id]).email
      name = session[:name]
      url = ""
      if  ENV["RAILS_ENV"] == "development"
        url = "http://localhost:3000/products/#{session[:product_id]}"
      else
        url = "https://slup-app.herokuapp.com/products/#{session[:product_id]}"
      end
      NoticeNewComment.notice_new_comment(name, url, email).deliver_now
      redirect_to controller: "products", action: "show", id: "#{session[:product_show_id]}"
    end

    private
      def comment_params_create
        params.require(:comment).permit(:text, :user_id, :review_id)
      end
end

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

# app/models/comment.rb

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :review
end
# app/models/product.rb

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

class Review < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
  has_many :comments
end
# app/models/user.rb

class User < ActiveRecord::Base
  has_secure_password
  validates :name, presence: true, :uniqueness => true
  validates :email, presence: true, :uniqueness => true
  has_many :reviews 
  has_many :comments
end
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

そんなことはありません。
ただ、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つあります。

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/03 12:51

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

    キャンセル

  • 2017/07/03 12:57 編集

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

    キャンセル

  • 2017/07/03 16:14

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

    キャンセル

  • 2017/07/03 16:25

    少々お待ちを

    キャンセル

  • 2017/07/03 17:20

    回答を編集しました

    キャンセル

  • 2017/07/03 17:27

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

    ありがとうございました。ベストアンサーに選ばせて頂きます。

    キャンセル

  • 2017/07/03 21:00

    nested_formの開発が止まっているという情報、ありがとうございます。

    Rails 5ではどうしたものかなあ…

    キャンセル

  • 2017/07/03 21:22 編集

    maisumakun様のお役に立てて嬉しいです。

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

    キャンセル

+1

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/03 13:09 編集

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

    キャンセル

  • 2017/07/03 16:16 編集

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

    > maisumakun様
    なるほど、コンソールからのほうがいい場合もあるのですね。ありがとうございます。

    キャンセル

  • 2017/07/03 20:56

    mingos様

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

    キャンセル

同じタグがついた質問を見る

  • Ruby

    9425questions

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

  • Ruby on Rails

    8849questions

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

  • Ruby on Rails 4

    2542questions

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