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

匿名 (未验证) 提交于 2019-12-03 01:26:01

问题:

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:

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 `show_opportunities' 

This line where 70 with the error is "@deal = Deal.friendly.find(params[:id])" (see below)

controller/deals_controller.rb (using @Pavan feedback)     # used so that old urls created for deals redirects to the new ones created     # indeed with friendly_id, the url is taken from the title :/deals/title     # but if we edit the deal title to deal/title2, the old url was still    working     # we need to redirect the old url     # source - github.com/norman/friendly_id/issues/385     before_filter :find_deal,        :only => [  :showcase ]     before_filter :ensure_canonical_deal_path!,       :only => [  :showcase ]   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[:deal])     @opportunity = Opportunity.where('deal_id = ? AND deal_type = ?',                              @deal.id, "high tech").first      respond_to do |format|       format.js     end end  protected  def find_deal    @deal = Deal.friendly.find params[:id] end def ensure_canonical_deal_path!    if request.path != deal_page_path(@deal)         redirect_to deal_page_path(@deal, :format => params[:format]), :status => :moved_permanently         return false    end end 

app/views/deals/showcase.html.erb

<% if @deal.present? %>    this is the beginning    <%= render 'deals/deal_info_zone', locals:{deal: @deal} %>    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 Opportunities", deal_opportunities_modal_path, deal: @deal, 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 ?

EDITED my question with Pavan feedback

SOLUTION

I finally found my error:

What I did was wrong: indeed when I hovered above the link 'view opportunities' I could see the url that the linking was pointing at was localhost:3000/opportunity_modal. but how impossible! I can't give the same url to all the links 'view opportunities' that would appear in all the diffreent Deal pages(id=1, id=2,...).

So I changed the route to:

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

and it works!!!

回答1:

NoMethodError - undefined method `id' for nil:NilClass

@deal is nil, you need to define it in the show_opportunities method.

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 

Update:

Firstly, change deals = Deal.friendly.find(params[:id]) to @deal = Deal.friendly.find(params[:id]) in showcase method.

And pass it as a locals in <%= render 'deals/deal_info_zone' %> like

<%= render 'deals/deal_info_zone', locals:{deal: @deal} %>, then pass it to link_to in _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, deal: @deal, remote: true %>   </div> </div> 

And finally access it in the show_opportunities method like @deal = Deal.friendly.find(params[:deal])



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!