Ruby on Rails:如何为关联模型创建表单(嵌套)

时间:2017-04-11 16:45:07

标签: ruby-on-rails ruby forms nested models

首先我有这个:

https://polar-scrubland-30279.herokuapp.com/ - 我的项目部署在heroku上(Captain Obvious)

我在其中有项目和待办事项。 在这一刻,我用这种方式展示所有项目:

------index.html.erb------

<%= render @projects %>

------_project.html.erb-----

<div class="project">
  <div class="project-header">
    <h2><%= project.title %></h2>
  </div>
  <div class="project-todos">
    <% project.todos.all.each do |todo| %>
      <p><%= check_box('tag', todo.__id__, {class: 'icheckbox_square-blue', checked: todo.isCompleted}) %> <%= content_tag :todotext, todo.text %></p>
    <% end %>
  </div>
</div>

根据您的理解,当复选框被选中时,它不允许我更改我的待办事项状态。这就是为什么我需要一个允许我跟踪所有复选框的表单。我也想在按下复选框时text-decoration: line-through,但不知道怎么做。

有没有办法创建一个满足我需求的表格?请帮助我,我们将不胜感激。

其他信息:

GitHub - https://github.com/NanoBreaker/taskmanager

project.rb

class Project < ActiveRecord::Base
  has_many :todos
end

todo.rb

class Todo < ActiveRecord::Base
  belongs_to :project
end

1 个答案:

答案 0 :(得分:0)

让我们从模型开始:

class Project < ApplicationRecord
  has_many :todos
  accepts_nested_attributes_for :todos
end

class Todo < ApplicationRecord
  belongs_to :project
end

accepts_nested_attributes_for允许您在创建或更新项目时一次创建或修改多个嵌套的Todo记录。

# will update 2 todos at once
@project.update(
 todos_attributes: [ { id: 1, isComplete: true }, { id: 2, isComplete: false }]
)

我们可以使用fields_for为待办事项创建嵌套输入:

<%= f.form_for(@project) do |f| %>
  <%= f.fields_for(:todos) do |tf| %>
    <%= tf.check_box :isCompleted %>
  <% end %>
<% end %>

这会为嵌套在密钥todos_attributes下的待办事项生成字段。我们可以使用包含允许属性数组的哈希键将它们列入白名单。

class ProjectsController < ApplicationController
  before_action :set_project, only: [:show, :edit, :update, :destroy]

  def new
    @project = Project.new
    # this seeds the project with 3 empty tasks
    # otherwise we don't have any inputs.
    3.times { @project.todos.new }
  end

  def create
    @project = Project.new(project_params)
    if @project.save
      # ...
    else
      # ...
    end
  end

  def update
    if @project.update(project_params)
      # ...
    else
      # ...
    end
  end

  private 

  def set_project
    @project = Project.find(params[:id])
  end

  def project_params
    params.require(:project)
      .permit(:foo, :bar, 
        todos_attributes: [:isCompleted, :text]
      )
  end
end

您可以创建使用a partial代替实例变量的local来为每个项目创建表单:

# app/views/projects/_form.html.erb
<%= f.form_for(local_assigns[:project] || @project) do |f| %>
  <%= f.fields_for(:todos) do |tf| %>
    <%= tf.check_box :isCompleted %>
  <% end %>
<% end %>

# app/views/projects/index.html.erb
<% @projects.each do |project| %>
  <%= render partial: 'projects/form', project: project %> 
<% end %>

您也可以为其他视图重复使用相同的部分:

# app/views/projects/new.html.erb
<%= render partial: 'projects/form' %> 

# app/views/projects/edit.html.erb
<%= render partial: 'projects/form' %>