`
CaiDeHen
  • 浏览: 94317 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

#75 Complex Forms Part 3

阅读更多
In this third and final episode on complex forms I will show you how to edit a project and multiple tasks all in one form. This includes removing and adding tasks dynamically as well. See the show notes for updated code.
<!-- projects/edit.rhtml -->
<% form_for :project, :url => project_path(@project), :html => { :method => 'put' } do |f| %>
  <%= render :partial => 'fields', :locals => { :f => f } %>
  <p><%= submit_tag "Update Project" %></p>
<% end %>

<!-- projects/new.rhtml -->
<% form_for :project, :url => projects_path do |f| %>
  <%= render :partial => 'fields', :locals => { :f => f } %>
  <p><%= submit_tag "Create Project" %></p>
<% end %>

<!-- projects/_fields.rhtml -->
<p>
  Name: <%= f.text_field :name %>
</p>
<div id="tasks">
  <%= render :partial => 'task', :collection => @project.tasks %>
</div>
<p><%= add_task_link "Add a task" %></p>


<!-- projects/_task.rhtml -->
<div class="task">
  <% fields_for_task(task) do |task_form| %>
  <p>
    Task: <%= task_form.text_field :name %>
    <%= link_to_function "remove", "$(this).up('.task').remove()" %>
  </p>
  <% end %>
</div>

# models/project.rb
class Project < ActiveRecord::Base
  has_many :tasks, :dependent => :destroy

  validates_presence_of :name
  validates_associated :tasks
  
  after_update :save_tasks

  def new_task_attributes=(task_attributes)
    task_attributes.each do |attributes|
      tasks.build(attributes)
    end
  end
  
  def existing_task_attributes=(task_attributes)
    tasks.reject(&:new_record?).each do |task|
      attributes = task_attributes[task.id.to_s]
      if attributes
        task.attributes = attributes
      else
        tasks.delete(task)
      end
    end
  end
  
  def save_tasks
    tasks.each do |task|
      task.save(false)
    end
  end
end


# models/task.rb
class Task < ActiveRecord::Base
  belongs_to :project
  validates_presence_of :name
end


# projects_controller.rb
def new
  @project = Project.new
  @project.tasks.build
end

def create
  @project = Project.new(params[:project])
  if @project.save
    flash[:notice] = "Successfully created project and tasks."
    redirect_to projects_path
  else
    render :action => 'new'
  end
end

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

def update
  params[:project][:existing_task_attributes] ||= {}
  
  @project = Project.find(params[:id])
  if @project.update_attributes(params[:project])
    flash[:notice] = "Successfully updated project and tasks."
    redirect_to project_path(@project)
  else
    render :action => 'edit'
  end
end


# projects_helper.rb
def fields_for_task(task, &block)
  prefix = task.new_record? ? 'new' : 'existing'
  fields_for("project[#{prefix}_task_attributes][]", task, &block)
end

def add_task_link(name) 
  link_to_function name do |page| 
    page.insert_html :bottom, :tasks, :partial => 'task', :object => Task.new 
  end 
end 

Validation
Displaying the validation errors can be tricky depending on your needs. It may be as simple as displaying the project validations:

<!-- projects/_fields.rhtml -->
<%= error_messages_for :project %>

This will mention if there are task validation errors, however it will not state exactly what the errors are because these are stored in each task model.

If you need to display the task error messages. One way is to do this:

<!-- projects/_task.rhtml -->
<% @task = task %>
<%= error_messages_for :task %>

The error_messages_for method requires an instance variable with the same name, so that is why it needs to be set right there. This is an ugly work around.
分享到:
评论

相关推荐

    PROFESSIONAL F# 2.0

    - **Primitive Types (Chapter 3):** Here, students learn about the basic data types available in F#, such as integers, floats, and characters. Understanding these types is crucial for performing ...

    sympy-docs-pdf-1.0.pdf

    The printing system is a crucial part of SymPy. It allows users to format expressions in various styles, such as LaTeX, MathML, and plain text. ##### 5.18 Plotting Module Visualization is an ...

    Cours-VB-NET-2010-Developpez-com

    The course follows a structured approach, starting with fundamental concepts and gradually moving towards more complex topics. The sequence ensures that learners build a solid foundation before ...

    考研英语单词

    - **例句**:Social media has become an integral part of our daily lives. ##### 2. Rate 速率,比率,等级,价格,费用,估价 - **应用场景**:统计学、经济学等。 - **例句**:The unemployment rate is ...

    modeling algorithm

    It provides a visual programming interface that simplifies the process of creating complex forms and structures through a series of connected components and parameters. The tool is primarily used in ...

    GWT in Action

    It provides a comprehensive set of tools and libraries that facilitate the creation of complex user interfaces and robust back-end services. **GWT in Action** is a comprehensive guide that covers all...

    软件开发技术基础:第一章 C#.NET程序设计基础3.ppt

    复数由实部(real part)和虚部(imaginary part)组成。在C#中,我们通过定义私有成员变量`re`和`im`来存储这两个部分。在类的声明中,我们有以下代码: ```csharp class Complex { private double re, im; ``` ...

    Advanced Engineering Mathematics

    Review of Prerequisites 3 CHAPTER 1.1 Real Numbers, Mathematical Induction, and Mathematical Conventions 4 1.2 Complex Numbers 10 1.3 The Complex Plane 15 1.4 Modulus and Argument Representation of ...

    Pattern Recogintion and Machine Learning

    The book is part of the *Information Science and Statistics* series, edited by notable figures such as M. Jordan, J. Kleinberg, and B. Schölkopf. ### Key Knowledge Points #### 1. **Overview of ...

    Machine Learning for Audio, Image and Video Analysis 2nd

    The third part Applications shows how the abstract problems defined in the second part underlie technologies capable to perform complex tasks such as the recognition of hand gestures or the ...

    Beginning PHP 5.3

    - **Complex Queries:** Techniques for building complex queries, including joins and subqueries. **Chapter 15: Making Your Job Easier with PEAR** - **PEAR Overview:** Explanation of what PEAR ...

    Quick Time File Format

    QTFF also supports interactive features, enabling the creation of multimedia content with clickable links, forms, and other interactive elements. This feature is particularly useful for educational ...

    Pro AngularJS

    Part 3 – AngularJS Modules and Services 18. Working with Modules and Services 19. Services for Global Objects, Errors and Expressions 20. Services for Ajax and Promises 21. Services for REST 22. ...

    Practical Machine Learning with Python(pdf书+sourcecode)

    Part 3 explores multiple real-world case studies spanning diverse domains and industries like retail, transportation, movies, music, marketing, computer vision and finance. For each case study, you ...

Global site tag (gtag.js) - Google Analytics