简体   繁体   中英

validating nested model when user selects foreign key value - rails

I have a nested model, Task which belongs to Project so in my model:

class Task < ActiveRecord::Base
  belongs_to :project
  validates :project_id, :presence => true

In my projects model, I have:

class Project < ActiveRecord::Base
  has_many :tasks, :dependent => :destroy

Now, I have a form to create a new task where the user can specify project_id ie which project the task belongs to. So my form looks something like this:

    <%= form_for [@project, @task], :remote => true do |f| %>
        <%= f.label :title, "Title" %>
        <%= f.text_field :title %>
        <%= label_tag("Project") %>
        <%= select(nil, :project_id, (get_active_projects).collect {|p| [p.title, p.id]  }, {:prompt => 'Select Project'}) %>

        <%= f.label :description %>
        <%= f.text_area :description %>

       <div class="actions">
       <%= f.submit 'Save' %>
       </div>
    <% end %>

The problem I'm having with validation is that if the user didn't select a project (project_id) in the form, I get an error saying that a project can't be found before any validation can be done right? I want my validation enforcing the presence of a project_id to happen before there is an attempt to find the project.

def create
    @project = Project.find(params[:project_id])

    @task = @project.tasks.new(params[:task])
    @task.update_attributes(:status_id => 2)
    @task.save!

In your way you trying to find project in your method and if project_id is nil it will give that error. As it is has_many and belongs_to relationship it enough to save the project_id in Task you don't have to create task through projects. As you are creating a task not many you dont need project object in form_for you can go like this

<%= form_for @task, :remote => true do |f| %>
    <%= error_messages_for(@task) %>
    <%= f.label :title, "Title" %>
    <%= f.text_field :title %>
    <%= f.label :project_id %>
    <%= f.select(nil, :project_id, (get_active_projects).collect {|p| [p.title, p.id]  }, {:prompt => 'Select Project'}) %>  (just check the select syntax if i did something wrong)

    <%= f.label :description %>
    <%= f.text_area :description %>

    <div class="actions">
        <%= f.submit 'Save' %>
    </div>
<% end %>

then in your controller method should be as simple as this

def create
    params[:task][:status_id] = 2
    @task = Task.new(params[:task])
    if @task.save!
       what you want to do if valid
    else
       go back to same page with errors
    end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM