Это мой первый проект на Rails, и я пытаюсь создать форму для добавления продуктов, которые могут иметь несколько пар свойств и значений свойств. Я ознакомился с несколькими учебными пособиями и просмотрел несколько ответов, касающихся вложенных форм, но я застрял на том, действительно ли информация сохраняет и отображает информацию. Я использовал самоцвет Cocoon для динамического создания дополнительных пар имени и значения свойства. Я попытался использовать простую вложенную форму, чтобы убедиться, что я правильно структурировал модели - это код ниже. Я включил соответствующий код из моего проекта ниже. Любая помощь с благодарностью!
controllers / products_controller.erb
class ProductsController < ApplicationController
def index
@products = Product.all
gon.products = Product.all
end
def show
@product = Product.find(params[:id])
@properties = Product.find(params[:id])
end
def new
@product = Product.new
@properties = @product.properties.build
@product_properties = @properties.product_properties.build
end
def create
@product = Product.new(product_params)
if @product.save
redirect_to products_path,
notice: 'The product was successfully created.'
else
render 'new'
end
end
private
def product_params
params.require(:product).permit(:name, :upc, :available_on,
:properties_attributes => [:property_name,
:product_properties_attributes => [:value]
])
end
def get_property
@property = Property.find(params[:property_id])
end
end
models / product.rb
class Product < ApplicationRecord
has_many :properties
has_many :product_properties,
:through => :properties
accepts_nested_attributes_for :properties
accepts_nested_attributes_for :product_properties
attr_accessor :properties_attributes,
:product_properties_attributes
validates :name, :upc, :available_on, presence: true
validates :name, :upc, uniqueness: true
validates :upc, numericality: { only_integer: true }
validates :name, length: { maximum: 1024,
too_long: "%{count} characters is the maximum allowed" }
validate :check_length
def check_length
unless upc.size == 10 or upc.size == 12 or upc.size == 13
errors.add(:upc, "length must be 10, 12, or 13 characters")
end
end
validate :expiration_date_cannot_be_in_the_past
def expiration_date_cannot_be_in_the_past
errors.add(:available_on, "must be a future date") if
!available_on.blank? and available_on < Date.today
end
end
models / property.rb
class Property < ApplicationRecord
belongs_to :product
has_many :product_properties
accepts_nested_attributes_for :product_properties
attr_accessor :property_name,
:value,
:product_properties_attributes
validates :property_name, presence: true
validates :property_name, uniqueness: true
validates :property_name, length: { maximum: 255,
too_long: "%{count} characters is the maximum allowed" }
end
models / product_property.rb
class ProductProperty < ApplicationRecord
belongs_to :property
belongs_to :product
attr_accessor :value
validates :value, presence: true
validates :value, length: { maximum: 255,
too_long: "%{count} characters is the maximum allowed" }
end
views / products / new.html.erb
<h1>New Product</h1>
<%= form_with scope: @product, url: products_path, local: true do |f| %>
<% if @product.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(@product.errors.count, "error") %> prohibited
this product from being saved:
</h2>
<ul>
<% @product.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<strong>Name</strong><br>
<%= f.text_field :name %>
</p>
<p>
<strong>UPC</strong><br>
<%= f.text_field :upc %>
</p>
<p>
<strong>Available On</strong><br>
<%= f.date_field :available_on %>
</p>
<h3>Properties</h3>
<div id='properties'>
<%= f.fields_for (:properties) do |property| %>
<%= property.fields_for (:product_properties) do |product_property| %>
<p>
<strong>Property Name</strong><br>
<%= property.text_field :property_name %>
</p>
<p>
<strong>Property Value</strong><br>
<%= product_property.text_field :value %>
</p>
<% end %>
<% end %>
</div>
<p>
<%= f.submit "Add Product" %>
</p>
<% end %>
views / products / index.html.erb
<h1>Products</h1>
<%= link_to 'New Product', new_product_path %>
<div id="search"></div>
<table>
<tr>
<th>Name</th>
<th>UPC</th>
<th>Available On</th>
<th></th>
</tr>
<% @products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= product.upc %></td>
<td><%= product.available_on %></td>
<% product.properties.each do |property| %>
<td><%= property.property_name %></td>
<% end %>
<td><%= link_to 'Details', product_path(product) %></td>
</tr>
<% end %>
</table>