与对象有关的form_for
form_for基本形态
#基本形态
#config/routes.rb
resources :articles
#views,省略url
<%= form_for @article do |f| %>
<%= f.text_field :title %>
<%= f.text_area :body, size: "60x12" %>
<%= f.submit "Create" %>
<% end %>
#省略url,智能识别@article
@article.new_record? #=>true, url: articles_path, method: :post 备注:articles_path, method: :post路径,就是创建新的记录
@article.new_record? #=>false, url: article_path(@article), method: :patch
#自己指定url和html
<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
#处理put,patch,delete
浏览器只能识别get和post请求,对于其他请求均以hidden字段提交
#示例
form_tag(search_path, method: "patch")
#html代码
<form accept-charset="UTF-8" action="/search" method="post">
<input name="_method" type="hidden" value="patch" />
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
...
</form>
#处理namespace
#config/routes.rb
namespace :admin do
resources :articles
end
#view
form_for [:admin, @article]
使用collection_select处理隐式单选
#使用collection_select进行单选
#示例
rails g scaffold tag name
rails g scaffold article name address tag:references
#tag.rb
class Tag < ApplicationRecord
has_many :articles, dependent: :destroy
end
#article.rb
class Article < ApplicationRecord
belongs_to :tag
end
#view中显示
<%= form_for @article do |f| %>
<%= f.label :tag %>
#最开始的值是tag_id, 第二个是Tag.all, 第三个是Tag.all的id值,最后一个是呈现在view中的name属性,也可以选择address属性
<%= f.collection_select :tag_id, Tag.all, :id, :name %>
#<%= f.collection_select :tag_id, Tag.all, :id, :address %>
#<%= f.collection_select :tag_id, Tag.all, :id, :name, prompt: "请选择" %>
<% end %>
使用collection_radio_boxes处理显式单选
#使用collection_radio_buttons处理单选显示形式
<%= form.collection_radio_buttons :tag_id, Tag.all, :id, :name %>
使用collection_check_boxes处理多选
#示例代码
rails g scaffold product name:string
rails g scaffold category name:string
rails g scaffold categorization product:references category:references
#model
class Categorization < ApplicationRecord
belongs_to :product
belongs_to :category
end
class Category < ApplicationRecord
#注意,次序不能变,has_many必须在has_many: through之前
has_many :categorizations, dependent: :destroy
has_many :products, through: :categorizations, dependent: :destroy
end
class Product < ApplicationRecord
has_many :categorizations, dependent: :destroy
has_many :categories, through: :categorizations, dependent: :destroy
end
#controller
def product_params
params.require(:product).permit(:name, {category_ids: []})
end
#view中使用collection_check_boxes
<div class="field">
<%= form.label :categories%>
<%= form.collection_check_boxes :category_ids, Category.all, :id, :name %>
</div>
选择tag的过程中创建tag
#辅助代码如上所示
#创建虚拟属性,定义方法
class Product < ApplicationRecord
attr_accessor :new_category_name
validates :new_category_name,
format: { with: /\A[\u4e00-\u9fa5\w,,]+\z/, message: "只接受数字,中文,英文和逗号" },
allow_blank: true
#必须product创建之后才创建,所以使用after_save
after_save :create_category_from_name,
unless: Proc.new { |product| product.new_category_name.blank? }
private
def create_category_from_name
if new_category_name.include?(",") && new_category_name.include?(",")
new_category_name.split(",").each do |category|
unless category.include?(",")
unless Category.exists?(name: category.strip)
categories.create(name: category.strip)
else
categories << Category.find_by(name: category.strip)
end
else
category.split(",").each do |category|
unless Category.exists?(name: category.strip)
categories.create(name: category.strip)
else
categories << Category.find_by(name: category.strip)
end
end
end
end
elsif new_category_name.include?(",")
new_category_name.split(",").each do |category|
categories.create(name: category.strip)
unless Category.exists?(name: category.strip)
categories.create(name: category.strip)
else
categories << Category.find_by(name: category.strip)
end
end
elsif new_category_name.include?(",")
new_category_name.split(",").each do |category|
unless Category.exists?(name: category.strip)
categories.create(name: category.strip)
else
categories << Category.find_by(name: category.strip)
end
end
else
unless Category.exists?(name: new_category_name.strip)
categories.create(name: new_category_name.strip)
else
categories << Category.find_by(name: new_category_name.strip)
end
end
end
end
#controller
def product_params
params.require(:product).permit(:name, :new_category_name, {category_ids: []})
end
#view中
<div class="field">
<%= form.label "创建tags" %>
<%= form.text_field :new_category_name %>
</div>