Rails中的Helper方法

tag类的Helper

form_tag

<%= form_tag("/search", method: "get") do %>
  <%= label_tag(:q, "Search for:") %>
  <%= text_field_tag(:q) %>
  <%= submit_tag("Search") %>
<% end %>
#生成HTML如下
#生成的表单的每个input属性都有ID属性,其值和name属性的值是一样的 form_tag({controller: "people", action: "search"}, method: "get", class: "nifty_form") #第二个hash参数为html属性

复选框

<%= check_box_tag(:pet_dog, "12") %>


单选框

<%= radio_button_tag(:age, "child") %>


处理模型对象

#如果控制器定义了@person实例变量,有属性name ="Henry"
<%= text_field(:person, :name) %>
#生成如下

#params获取的值为
{'person' => {'name' => 'Henry'}}
#可以使用params[:person][:name]获取提交的值
#如果@person实例是数据库表nurse_aid_person,那么产生的代码如下

Hash

#Hash可以随意嵌套

#获取的params为
{'person'=>{'address'=>{'city'=>'New York'}}}
params[:person][:address][:city]

数组

#一般情况下Rails回忽略重复的参数名



#params[:person][:phone_number]是一个数组

Hash和数组结合




#params[:addresses]值是一个由Hash组成的数组

form_for表单绑定对象

<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :body, size: "60x12" %>
  <%= f.submit "Create" %>
<% end %>


  
  
  

fields_for方法

#同一表单中编辑多个模型对象时经常使用fields_for方法。
#eg、有个Person模型,和ContactDetail模型关联
<%= form_for @person, url: {action: "create"} do |person_form| %>
  <%= person_form.text_field :name %>
  <%= fields_for @person.contact_detail do |contact_details_form| %>
    <%= contact_details_form.text_field :phone_number %>
  <% end %>
<% end %>

#生成的HTML代码如下

命名空间

#admin命名空间
form_for [:admin, @article] #admin_article_path(@article)

form_for[:admin, :management, @article]

文件处理

上传文件

#params[:picture]
<%= form_tag({action: :upload}, multipart: true) do %>
  <%= file_field_tag 'picture' %>
<% end %>

#params[:person][:picture]
<%= form_for @person do |f| %>
  <%= f.file_field :picture %>
<% end %>

处理上传

#可以使用CarrierWave和Paperclip等第三方库
def upload
  upload_io = params[:person][:picture]
  File.open(Rails.root.join('public', uploads, upload_io.original_filename), 'wb') do |file|
    file.write(uploaded_io.read)
  end
end

使用Ajax上传文件

<%= form_for @person, builder: LabellingFormBuilder do |f| %>
  <%= f.text_field :first_name %>
<% end %>
#定制表单构造器
class LabellingFormBuilder < ActionView::Helpers::FormBuilder
  def text_field(attribute, options=[])
    label(attribute) + super
  end
end

外部资源

#如果不需要access_token的话,可以关闭,如果需要,设置authenticity_token的值
<%= form_tag 'http://www.baidu.com', authenticity_token:  false do %>
...
<% end %>

复杂的表单

class Person < ActiveRecord::Base
  has_many :addresses
  accepts_nested_attributes_for :addresses, allow_destroy: true,
    reject_if: lambda{|attributes| attributes['kind'].blank?}
#自动为Person对象创建address_attributes=方法,用于创建、更新、删除地址操作
end

class Address < ActiveRecord::Base
  belongs_to :person
end

嵌套表单

<%= form_for @person do |f| %>
  Addresses:
  
    <%= fields_for @person.addresses do |addresses_form| %>
  • <%= addresses_form.label :kind %> <%= addresses_form.text_field :kind %> <%= addresses_form.label :street %> <%= addresses_form.text_field :street %>
  • <% end %>
<% end %>

如果关联支持嵌套属性,fields_for方法会为关联中的每个元素执行一遍代码块,如果没有Address,就不执行,一般做法是在控制器中构建一个或者多个空的子属性。这样至少会有一组字段显示出来。

def new
  @person = Person.new
  2.times { @person.addresses.build }
end

如果用户提交了两个地址,提交的参数如下

{
  'person' => {
    'name' => 'John Doe',
    'addresses_attributes' => {
      '0' => {
        'kind' => 'Home',
        'street' => '221b Baker Street'
      },
      '1' => {
        'kind' => 'Office',
        'street' => '31 Spooner Street'
      }
    }
  }
}

控制器端

def create
  @person = Person.new(person_params)
end

private
  def person_params
    params.require(:person).permit(:name, addresses_attributes:[:id, :kind, :street])
  end

删除属性

#表单
<%= form_for @person do |f| %>
  Addresses:
  
    <%= f.fields_for :addresses do |addresses_form| %>
  • #如果属性组成的hash中包含_destroy键,且值为1或true,就会删除对象 <%= addresses_form.check_box :_destroy%> <%= addresses_form.label :kind %> <%= addresses_form.text_field :kind %> ...
  • <% end %>
<% end %>

修改控制器中的参数白名单

def person_params
  params.require(:person).
    permit(:name, addresses_attributes: [:id, :kind, :street, :_destroy])
end

你可能感兴趣的:(Rails中的Helper方法)