0

In my ruby on Rails 4 app, a user clicks on a link on a Deal page (see above the code. link is 'view infos of the latest Opportunity').

Once he clicks the link on the page, an ajax call is then made to show him some info about one of latest Opportunity via Rails UJS (link remote=> true).

I would like to update the 'opportunity_status' attribute of the Opportunity row that is read as SOON as POSSIBLE after the row has been read by postgresql. but how to know the row has been "read"?

Is there a reliable way to know the postgresql query has been done, i.e the READ query on the table/row has been performed and finished, and then if the READ query has been performed then straight away trigger an update on the 'opportunity status' column changing it from 'available' to 'not available anymore' of the row that has been read inside the READ query?

I'm quite rookie on postgresql so I don't know how to do this.

controller/deals_controller.rb

def showcase    
    @deal = Deal.friendly.find(params[:id])   

    respond_to do |format|
      format.html # showcase.html.erb
      format.json { render json: @deal }
    end
end 

def show_opportunities
    @deal = Deal.friendly.find(params[:id])
    @opportunity = Opportunity.where('deal_id = ? AND deal_type = ?',
                             @deal.id, "high tech").first

    respond_to do |format|
      format.js
    end
end

app/views/deals/showcase.html.erb

<% if @deal.present? %>
   this is the beginning
   <%= render 'deals/deal_info_zone' %>
   this is the end
<% end %>

views/deals/_deal_info_zone.html.erb

<div id="zoneA">      
  <div style="color:red;padding-top: 150px;">
    <%= link_to "view infos of the latest Opportunity", deal_opportunities_modal_path, remote: true %>
  </div>
</div>

views/deals/deal_opportunities_modal.js.erb

Here is the modal trigger via Ajax: views/deals/opportunity_modal. Note here how I tried here to pass Deal but without success so that the line

$('body').append('<%= j render partial: "deals/deal_opportunities_modal" %>');
$('#myModal').modal('show');

/app/views/deals/_deal_opportunities_modal.html.erb

Here is the modal view/content now:

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">

      <div class="modal-body"> 

          this the the latest opportunity: <%= @latest_opportunity.name %> <br/>     

      </div>

    </div>
  </div>
</div>

@opportunity comes from this controller

def deal_opportunities_modal
    @deal = Deal.friendly.find(params[:id])   

    @latest_opportunity = Opportunity.where('deal_id = ? AND opportunity_status = ?', @deal.id, 'available').first      

    respond_to do |format|
      format.js 
    end
  end

So inside the modal, the latest opportunity is shown. It comes form this controller's @shown_opportunity = Opportunity.where('deal_id = ? AND opportunity_status = ?', @deal.id, 'available').first

I want to update the attribute 'opportunity_status' of this opportunity as SOON as possible, but reliably, when this query @latest_opportunity = Opportunity.where('deal_id = ? AND opportunity_status = ?', @deal.id, true).first had been COMPLETED inside the Opportunity table (it's a read, I need to know when the READ is finished).

How to do that?

Mathieu
  • 4,587
  • 11
  • 57
  • 112
  • I don't get your problem. You want to know how you can update your view if you had a change in your server info? Like notification mechanisms? – Ali Sepehri.Kh Oct 01 '15 at 21:24

1 Answers1

0

You can set and save the new status directly in the controller in your show_opportunities method, after the record is read, but before the data is send to the user.

If you want to make sure that at the same time no other is getting the same opportunity, you need to lock the database row when you read it. See "pessimistic locking"

Meier
  • 3,858
  • 1
  • 17
  • 46
  • thanks, quite logical I'll put the update between the @latest_opportunity and the respond do |format|.right? – Mathieu Oct 02 '15 at 06:29
  • yes. Even better if you create a method in the Opportunity model that retrieves the opportunity, saves the opportunity_status back and returns the retrieved status to the controller. – Meier Oct 02 '15 at 07:34
  • is it better for speed or code readability/declutter controller? actually you might be right i'm thinking to take the whole @latest_opportunity block in the controller and move it along the update inside the model.would that be a good idea? – Mathieu Oct 02 '15 at 10:52
  • Because this is how the Model-View-Controller-Pattern structures the application. the details of storing this status is something that belongs into the model layer. the controller is to control the user interface, and the less it knows about the models the better. – Meier Oct 02 '15 at 21:53
  • thanks, would you also move '@latest_opportunity = Opportunity.where('deal_id = ? AND opportunity_status = ?', @deal.id, 'available').first ' to the model? – Mathieu Oct 03 '15 at 09:52
  • Trying to understand the scope/limits/orbder of the skin controller MVC:) – Mathieu Oct 03 '15 at 09:53
  • moved to using pessimistic locking as you adviced. New questions arose: http://stackoverflow.com/questions/33128531/put-pg-try-advisory-xact-lock-inside-or-outside-the-where-clause-rails-4-postg and http://stackoverflow.com/questions/33129132/pg-try-advisory-xact-lock-vs-nowait-in-order-not-to-wait-release-of-lock-rails – Mathieu Oct 14 '15 at 15:34