Rails 4/ ajax - NoMethodError - nil:NilClass 的未定义方法`id' - 将变量传递给 js 模态
Rails 4/ ajax - NoMethodError - undefined method `id' for nil:NilClass - Passing variable to js modal
我在 Rails 上有一个非常简单的 Ruby 应用程序,前端为 bootstrap 3:我有优惠,每个优惠 has_many 机会。
在每个交易页面上(交易页面的 url 例如 myapp.com/id=1),我想要一个文本 link,上面写着 "view deal's opportunities"单击时,它会在单击 Bootstrap 模态内的内容外观时触发。
我搞混了,因为在这个 Deal 页面上,我使用了名为 "showcase" 的 Deal 控制器操作。但是为了通过 ajax 生成模式,如下所示,我使用了另一个名为 "show_opportunities" 的操作,在其中,应用程序似乎不知道 @deal(因为@deal 是在不同的 Deal 操作中定义的). 我认为问题出在哪里,但我不太确定。
这是我遇到的错误和我的代码:
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'
这一行 70 错误是“@deal = Deal.friendly.find(params[:id])”(见下文)
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
这是通过 ajax 的模态触发器:views/deals/opportunity_modal。
请注意我在这里是如何尝试通过 Deal 但没有成功的,因此行
$('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
如何进行这项工作?
用 Pavan 反馈编辑了我的问题
解决方案
我终于找到了我的错误:
我做错了:事实上,当我悬停在 link 'view opportunities' 上方时,我可以看到 linking 指向的 url 是 localhost:3000/opportunity_modal。但这是不可能的!我无法将相同的 url 分配给将出现在所有不同交易页面(id=1、id=2、...)中的所有 links 'view opportunities'。
所以我把路线改为:
match '/deals/:id/opportunity_modal',
to: 'deals#show_opportunities',
via: 'get',
as: :deal_opportunities_modal
而且有效!!!
NoMethodError - undefined method `id' for nil:NilClass
@deal
为nil,需要在show_opportunities
方法中定义
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
更新:
首先,将showcase
方法中的deals = Deal.friendly.find(params[:id])
改为@deal = Deal.friendly.find(params[:id])
。
并将其作为 locals
在 <%= render 'deals/deal_info_zone' %>
中传递,例如
<%= render 'deals/deal_info_zone', locals:{deal: @deal} %>
,然后在_deal_info_zone.html.erb
中传给link_to
<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>
最后在 show_opportunities
方法中访问它,如 @deal = Deal.friendly.find(params[:deal])
我在 Rails 上有一个非常简单的 Ruby 应用程序,前端为 bootstrap 3:我有优惠,每个优惠 has_many 机会。
在每个交易页面上(交易页面的 url 例如 myapp.com/id=1),我想要一个文本 link,上面写着 "view deal's opportunities"单击时,它会在单击 Bootstrap 模态内的内容外观时触发。
我搞混了,因为在这个 Deal 页面上,我使用了名为 "showcase" 的 Deal 控制器操作。但是为了通过 ajax 生成模式,如下所示,我使用了另一个名为 "show_opportunities" 的操作,在其中,应用程序似乎不知道 @deal(因为@deal 是在不同的 Deal 操作中定义的). 我认为问题出在哪里,但我不太确定。
这是我遇到的错误和我的代码:
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'
这一行 70 错误是“@deal = Deal.friendly.find(params[:id])”(见下文)
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
这是通过 ajax 的模态触发器:views/deals/opportunity_modal。 请注意我在这里是如何尝试通过 Deal 但没有成功的,因此行
$('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
如何进行这项工作?
用 Pavan 反馈编辑了我的问题
解决方案
我终于找到了我的错误:
我做错了:事实上,当我悬停在 link 'view opportunities' 上方时,我可以看到 linking 指向的 url 是 localhost:3000/opportunity_modal。但这是不可能的!我无法将相同的 url 分配给将出现在所有不同交易页面(id=1、id=2、...)中的所有 links 'view opportunities'。
所以我把路线改为:
match '/deals/:id/opportunity_modal',
to: 'deals#show_opportunities',
via: 'get',
as: :deal_opportunities_modal
而且有效!!!
NoMethodError - undefined method `id' for nil:NilClass
@deal
为nil,需要在show_opportunities
方法中定义
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
更新:
首先,将showcase
方法中的deals = Deal.friendly.find(params[:id])
改为@deal = Deal.friendly.find(params[:id])
。
并将其作为 locals
在 <%= render 'deals/deal_info_zone' %>
中传递,例如
<%= render 'deals/deal_info_zone', locals:{deal: @deal} %>
,然后在_deal_info_zone.html.erb
link_to
<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>
最后在 show_opportunities
方法中访问它,如 @deal = Deal.friendly.find(params[:deal])