【问题标题】:Rails 4/ UJS - ActionController::UnknownFormat - provide user with a way to directly open page with modal already openedRails 4/ UJS - ActionController::UnknownFormat - 为用户提供一种直接打开已打开模式的页面的方法
【发布时间】:2025-11-21 13:55:02
【问题描述】:

在我的 Ruby on Rails 应用程序中,我通过 Rails 的 UJS(不显眼的 JavaScript)使用 Ajax。

这是完美的工作:当用户在交易页面上,然后当他点击某个文本链接时,会进行 Ajax 调用并加载带有远程内容的模式。

但我想为用户提供一种方式,让他们直接到达已经打开模式的页面,而无需他加载交易页面然后点击文本链接。 例如,用户可能会收到一封电子邮件并单击它,他会立即到达已打开模式的交易页面。

但它不起作用,当我采取模式的路线(见下面的代码)并在浏览器中输入 http://myapp.com/deals/:id/deal_opportunities_modal 时,它会给出以下错误:

在 29 毫秒内完成 406 不可接受

ActionController::UnknownFormat - ActionController::UnknownFormat: actionpack (4.2.0) lib/action_controller/metal/mime_responds.rb:218:in respond_to' app/controllers/deals_controller.rb:70:inshow_opportunities'

这是我的文件:

controller/deals_controller.rb

# 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[:id])
    @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' %>
   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

这里是通过 Ajax 触发的模式:views/deals/opportunity_modal。请注意我在这里如何尝试通过 Deal 但没有成功,因此该行

$('body').append('<%= j render partial: "deals/deal_opportunities_modal" %>');
$('#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"> 

          this the the latest opportunity: <%= @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 '/deals/:id/opportunity_modal',
  to: 'deals#show_opportunities',
  via: 'get',
  as: :deal_opportunities_modal

如何实现这一点,即如何创建一种路由/URL,当用户使用该路由/URL 时,他会在模式“show_opportunites”已经打开的情况下到达交易页面。

我听说过 js-routes,但它似乎对其他用途很有用(即在 javascript 文件中使用 Rails 路由)。

如果我让用户使用已经打开的模态访问页面,还会存在安全问题吗?

【问题讨论】:

    标签: javascript ruby-on-rails ruby-on-rails-3 ujs


    【解决方案1】:

    你不能让浏览器打开一个只能作为 JS 使用的控制器动作。

    在我看来,因为您已经在交易页面上有一个打开模式的按钮,如果他们点击正确的 URL 就触发它

    使用带有单独控制器动作的路由调用相同的视图,存储一个变量来告诉视图使用模态

    像这样:

    • 给定链接 "/deals/24/opportunities" 或任何其他命名约定创建一个路由:

    get '/deals/:id/opportunities', to: "deals#opportunities", as: deal_opportunities
    
    • 在您的控制器中,创建一个使用与showcase 相同的视图但将变量传递给视图以检查参数@show_modal = true 的操作

    def opportunities
        @show_modal = true
        @deal = Deal.friendly.find(params[:id])
        respond_to do |format|
          format.html { render action: "/deals/show" }
        end
    end
    
    • 在您的 showcase 视图中,如果 show_modal 存在,则使用 javascript 触发视图中已有的按钮以手动调用模态

    <%= if @show_modal %>  
      <script type="text/javascript">
         $(window).load(function(){
            $("a.deals-button").trigger("click");
        });
      </script>
    <% end %>
    

    【讨论】:

      最近更新 更多