Search code examples
ruby-on-railsrubyformsruby-on-rails-3models

Creating form for an object which has an association


I have two models: project and todo. Project has many todos.

So I wanna create a form, where I select project category from the combobox and then I add a todo to it.

For instance: I have following categories: family, work, study.

In form in the combobox I select 'study', and then in textfield I spell a todo like 'make homework for monday' and press submit button.

project.rb

class Project < ActiveRecord::Base
  has_many :todos
end

todo.rb

class Todo < ActiveRecord::Base

  belongs_to :project

end

my data schema:

  create_table "projects", force: :cascade do |t|
    t.string   "title"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "todos", force: :cascade do |t|
    t.string   "text"
    t.boolean  "isCompleted"
    t.integer  "project_id"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

_form.html.erb

<%= form_for @project do |f| %>

  <div class="form_control">
    <%= f.select :title, options_for_select([["Work", "w"],
                                            ["Family", "f"],
                                           ["Study", "f"],
                                           ["TheRest", "t"]]) %>
  </div>

  <div class="form_control">
    *** HERE I NEED TO FIGURE OUT HOW TO ADD SOME DATA TO todo.text ***
  </div>  

  <div class="form_control">
    <%= f.submit 'Add' %>
  </div>
<% end %>

this is how I show all the projects with their todos:

<% @projects.each do |project| %>
    <h2> <%= project.title %> </h2>
    <% project.todos.all.each do |todo| %>
      <p><%= todo.text %> <%= check_box('tag', todo.__id__, {checked: todo.isCompleted}) %></p>
    <% end %>
<% end %>

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


Solution

  • In your todo form, you could have a select box to choose the project the todo belongs to:

    # todos/_todo_form.html.erb
      <%= select_tag "project_id", options_for_select(Project.pluck(:title, :id)) %>
    

    And in your todos_controller create action:

    def create
      @project = Project.find(params[:project_id])
      @todo = @project.todos.new(todo_params)
      if @todo.save
        # success
      else 
        # error 
      end
    end 
    

    finally, permit the project_id in todo_params:

    def todo_params
      params.require(:todo).permit(:text, :project_id) # add any other attributes you want
    end