vendredi 25 septembre 2015

Rails 4/ ajax - NoMethodError - undefined method `id' for nil:NilClass - Passing variable to js modal

I have a pretty simple Ruby On Rails app with bootstrap 3 for the front end: I have Deals, and each Deal has_many Opportunities.

On each Deal page (url of deal page is for example myapp.com/id=1), I want to have a textual link that says "view deal's opportunities" and when clicked, it trigger when clicked the appearance of content inside a Bootstrap modal.

I'm getting all mixed up because on this Deal Page, I use Deal's controller action called "showcase". BUT to generate the modal via ajax,as you see below, I use another action called "show_opportunities" and inside it, the app seems not to know @deal (because@deal is defined in a different Deal's action). I think that where the problem comes form but I am not totally sure.

Here is the error I am getting and my code:

Processing by DealsController#show_opportunities as JS
Completed 500 Internal Server Error in 3ms

NoMethodError - undefined method `id' for nil:NilClass:
  app/controllers/deals_controller.rb:72:in `show_opportunities'

This line where 72 with the error is "@deal.id, "high tech").first" (see below)

controller/deals_controller.rb

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

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

def show_opportunities
    @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

this is the beginning
<%= render 'deals/deal_info_zone' %>
this is the end

views/deals/_deal_info_zone.html.erb

<div id="zoneA">      
  <div style="color:red;padding-top: 150px;">
    <%= link_to "view infos of Opportunities", 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", locals:{deal: @deal} %>'); 
$('#myModal').modal('show');

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

<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"> 

          <%= @opportunity.name %> <br/>     

      </div>

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

routes.rb

match '/deals/:id', # this is the Deal page
    to:   'deals#showcase',
    via:  'get',
    as:   :deal_page

match '/opportunity_modal',
    to:   'deals#show_opportunities',
    via:  'get',
    as:   :deal_opportunities_modal

How to make this work ?

EDIT with Pavan feedback

Pavan suggested putting @deal inside #show_opportunities

Si I tried to change controller/deals_controller.rb:

def showcase    
    deals = 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

but I get the error:

Completed 404 Not Found in 3ms

ActiveRecord::RecordNotFound - Couldn't find Deal without an ID:
 activerecord (4.2.0) lib/active_record/relation/finder_methods.rb:433:in `find_with_ids'
  activerecord (4.2.0) lib/active_record/relation/finder_methods.rb:71:in `find'
  friendly_id (5.1.0) lib/friendly_id/finder_methods.rb:20:in `find'
  app/controllers/deals_controller.rb:70:in `winalert'

I thought I'd just remove the "friendly" (comes from friendly_id gem) from the code above but am still getting an error:

Started GET "/opportunity_modal" for 127.0.0.1 at 2015-09-25 15:15:40 +0200
Processing by DealsController#show_opportunities as JS
  Deal Load (0.5ms)  SELECT  "deals".* FROM "deals" WHERE "deals"."id" = $1 LIMIT 1  [["id", nil]]
Completed 404 Not Found in 5ms

ActiveRecord::RecordNotFound - Couldn't find Deal with 'id'=:
activerecord (4.2.0) lib/active_record/core.rb:154:in `find'

Aucun commentaire:

Enregistrer un commentaire