Search code examples
ruby-on-railsnested-formsruby-on-rails-4.2

How to Update a model while creating another model using one form in rails


Pls i need help here. i have 2 models:- due_job and outgoing_job due_job has_many outgoing_jobs outgoing_job belongs_to due_job. Im trying to update a user's outgoing_job as done while at the same time create a due_job for another user. My models:

class DueJob < ActiveRecord::Base
    belongs_to :user
    has_many :outgoing_jobs
    accepts_nested_attributes_for :outgoing_jobs
end

class OutgoingJob < ActiveRecord::Base
    belongs_to :user
    belongs_to :outgoing_jobs
    accepts_nested_attributes_for :outgoing_jobs
end

Controllers:

class OutgoingJobsController < ApplicationController

    def index
        @outgoing_job = OutgoingJob.new
        @outgoing_jobs = OutgoingJob.all
    end

    def new 
        @outgoing_job = OutgoingJob.new 
    end 

    def create
        @outgoing_job = OutgoingJob.new(outgoing_job_params)
        respond_to do |format|
        
            if @outgoing_job.save   
                flash.now[:success] = "saved"
                format.html {redirect_to current_user}
                format.json {render json: @outgoing_job, status: :created, location: @outgoing_job}
            else 
                flash[:danger] = "not saved"
                format.html {redirect_to root_path}
                format.json {render json: @outgoing_job.errors, status: :unprocessable_entity }
            end
        end
    end

    def show
        @outgoing_job = OutgoingJob.find(params[:id])
    end 

    def update 
        @outgoing_job = OutgoingJob.find(params[:id])
        respond_to do |format|
            if @outgoing_job.update(outgoing_job_params)
                format.html { redirect_to '/users/outgoing_job_dashboard', notice: 'job updated' }
                format.json {render action: 'show', status: :ok, location: @outgoing_job }
            else
                format.html { render action: 'edit'}
                format.json { render json: @outgoing_job.errors, status: :unprocessable_entity}
            end
        end  
    end

    def destroy
        @outgoing_job.destroy
        respond_to do |format|
            format.html {redirect_to current_user}
            format.json { head :no_content}
        end
    end



    private
    def outgoing_job_params
        params.require(:outgoing_job).permit(:outgoing_job_value, 
            :sent,
            :confirmed,
            :done,
            :due_job_id,
            :user_id )
    end
 end

the controller for due_jobs is essentially same.

However, when i do this in my view:

<% OutgoingJob.all.each do |od| %>
    <table class="table table-striped table-responsive">
        <thead>
            <tr>
                <th>ID</th>
                <th>Done By</th>
                <th>Done for</th>
                <th>Beneficiary</th>
                <th>Amount proposed</th>
                <th>Amount to paid</th>
                <th>Create due job</th>
                <th>Actions</th>
            </tr>
        </thead>

        <% if (od.confirmed == true) && (od.done== false) %>
            <tbody>
                <tr>
                    <td><%= od.id %></td>
                    <td><%= od.user.first_name %> <%= od.user.last_name %></td>
                    <td><%= od.due_job.user.first_name %> <%= od.due_job.user.last_name %></td>
                    <td><%= od.due_job.user.user_detail %></td>
                    <td>$ <%= number_with_delimiter(od.outgoing_job_value, delimiter: ',') %> </td>
                    <td> <%= --- %> </td>

                    <td>
                        <%= simple_form_for (DueJob.new) do |u| %>
                            <%= u.hidden_field :due_job_value, value: od.outgoing_job_value  %>
                            <%= u.hidden_field :user_id, value: od.user.id %>
                            <%= u.fields_for od  do |f| %>
                            <%= f.hidden_field :done, value: true %>
                        <%end%>
                        <%= u.submit "create", class: "btn btn-success" %>
                      <%end%>
                   </td>
                   <td><%= link_to "View", od %></td>
                </tr>
            </tbody>
        <%end%>
    </table>
    .....

Using nested form i am able to create a new record for DueJob tho, but it doesnt update outgoing_job. What am i missing pls?


Solution

  • I suggest you make use of ActiveRecord callbacks to relegate some of the code to your models (I doubt that trying to do everything from one view is the way to go).

    In your model for DueJob add something like:

    class DueJob < ActiveRecord::Base
      # Register a callback to execute every time you create a new DueJob
      after_create :update_done_flag_on_outgoing_job
    
      # ... and add some code for that callback.
      def update_done_flag_on_outgoing_job
        outgoing_job.update_attribute :done, true
      end
    

    Just from reading your source code, I was struggling to understand how you identify the connections between the newly created DueJob and the specific OutgoingJob record that you want to update. Like @coreyward pointed out, it would be helpful if you could present your code a bit more neatly. If you can't use my example snippet as is, I guess you can always adapt the update_done_flag_on_outgoing_job method to your needs.

    Hope you find that helpful.