I am new to ruby on rails and coding in general. I wrote a nested form_for where the Price class belongs to an Item class. The values :amount, :timeframe, and :item_id are to be stored through the controller. After the action ends only the :timeframe and :item_id are stored but not the :amount value.
Does this have to do with:
The nested form?
The datatype, and or precision & scale details for :amount?
Could it also be an issue with my controller method?
Any clarification would be greatly appreciated!
Here is the form:
<%= form_for @item, html: {multipart: true} do |f| %>
<div class="main-form">
<div class="new-item-form">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="new-item-form">
<%= f.label :description %>
<%= f.text_field :description %>
</div>
<div class="new-item-form">
<%= f.label :deposit %>
<%= f.text_field :deposit %>
</div>
<div class="new-item-form">
<%= f.label :tags %>
<%= f.text_field :tags %>
</div>
<div class="new-item-form">
<%= f.label :image %>
<%= f.file_field :image %>
</div>
<%= fields_for :price do |f| %>
<div class="new-item-form">
<%=f.label :timeframe %>
<%= select_tag(:timeframe, options_for_select([["Hour"],["Day"],["Week"]])) %>
</div>
<div class="new-item-form">
<%=f.label :amount %>
<%=f.number_field :amount %>
</div>
<% end %>
<%= f.submit %>
<%end%>
This is the controller:
class ItemsController < ApplicationController
def show
@item = Item.find(params[:id])
@price = Price.where(item_id: @item.id).first
end
def new
@item = Item.new
end
def create
@item = Item.new(item_params)
if @item.save
@price = Price.create(:timeframe => params[:timeframe], :amount => params[:amount], :item_id => @item.id)
@price.save
redirect_to @item, notice: "Item Successfully Added!"
else
flash[:message] = "Something did not validate"
render 'new'
end
end
private
def item_params
params.require(:item).permit(:title, :description, :image, :user_id, :deposit, :tags)
end
end
Additional documents include the Item model and Price model:
class Item < ActiveRecord::Base
validates :title, :description, :deposit, :tags, presence: true
belongs_to :user
has_many :prices, :dependent => :destroy
has_many :reviews, :dependent => :destroy
has_many :ratings, :dependent => :destroy
has_many :users_that_reviewed_this, through: :reviews, source: :user
has_many :users_that_rated_this, through: :ratings, source: :user
end
class Price < ActiveRecord::Base
belongs_to :item end
As well as the database schema for these classes:
create_table "items", force: :cascade do |t|
t.string "title"
t.string "description"
t.string "image"
t.integer "user_id"
t.integer "deposit"
t.string "type"
t.string "tags"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "prices", force: :cascade do |t|
t.string "timeframe"
t.decimal "amount"
t.integer "item_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The problem in your code is in params[:amount]
. No params are there, it should be params[:price][:amount]
. It will work this way!
Though the approach is not the most "conventional"
Here is the correct approach using accepts_nested_attributes
, adding prices_attributes
to strong_parameters
and using
In your model
class Item < ActiveRecord::Base
validates :title, :description, :deposit, :tags, presence: true
belongs_to :user
has_many :prices, dependent: :destroy
has_many :reviews, dependent: :destroy
has_many :ratings, dependent: :destroy
has_many :users_that_reviewed_this, through: :reviews, source: :user
has_many :users_that_rated_this, through: :ratings, source: :user
accepts_nested_attributes_for :prices, reject_if: :all_blank, allow_destroy: true
end
In your controller
def create
@item = Item.new(item_params)
@item.prices.build
if @item.save
redirect_to @item, notice: "Item Successfully Added!"
else
flash[:message] = "Something did not validate"
render 'new'
end
end
private
def item_params
params.require(:item).permit(:title, :description, :image, :user_id, :deposit, :tags, prices_attributes: [:timeframe, :amount])
end
In your view
<%= form_for @item, html: {multipart: true} do |f| %>
<div class="main-form">
<div class="new-item-form">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="new-item-form">
<%= f.label :description %>
<%= f.text_field :description %>
</div>
<div class="new-item-form">
<%= f.label :deposit %>
<%= f.text_field :deposit %>
</div>
<div class="new-item-form">
<%= f.label :tags %>
<%= f.text_field :tags %>
</div>
<div class="new-item-form">
<%= f.label :image %>
<%= f.file_field :image %>
</div>
<%= f.fields_for :prices, Price.new do |p| %>
<div class="new-item-form">
<%=p.label :timeframe %>
<%= p.select(:timeframe, [["Hour"],["Day"],["Week"]], :prompt => 'Select') %>
</div>
<div class="new-item-form">
<%=p.label :amount %>
<%=p.number_field :amount %>
</div>
<% end %>
<%= f.submit %>
<%end%>