Rails:如何在posts_helper中使用post_path?

时间:2017-05-29 16:47:29

标签: ruby-on-rails

我有一个帖子视图,其中包含指向相邻帖子的链接。我在posts_helper中添加了一个类来决定链接应该是什么。

show.html.erb:

<ul>
  <% links = PostsHelper::Links.new(@post) %>
  <li><%= links.older %></li>
  <li><%= links.newer %></li>
  <li><%= link_to 'show all', posts_path %></li>
</ul>

posts_helper.rb:

module PostsHelper
  class Links
    def initialize(post)
      @post = post
    end

    def newer
      link_to 'newer', post_path(newer_post)
    end

    def older
      link_to 'older', post_path(older_post)
    end

    private

    attr_reader :post

    def newer_post
      Post.where(['id > ?', post.id]).last
    end

    def older_post
      Post.where(['id < ?', post.id]).first
    end
  end
end

路线:

Prefix Verb URI Pattern          Controller#Action
 posts GET  /posts(.:format)     posts#index
  post GET  /posts/:id(.:format) posts#show

但我无法访问助手类中的post_path。我收到一个错误:

undefined method `post_path' for #<PostsHelper::Links:0x007fb884ad10d0>

这让我觉得我不会采用“轨道”的方式。

如何使用posts_path助手?或者我是否偏离了理想的方法?

3 个答案:

答案 0 :(得分:1)

你比你想象的更近!但是,在我看来,你正朝着Presenter模式前进 - 而不是Helper模式。查看RailsCast以获得更好的讨论。

所以,假设你有类似的东西:

app/presenters/posts/show_presenter.rb

class Posts::ShowPresenter

    def initialize(controller)
      @controller = controller
    end

    def newer_link
      link_to 'newer', post_path(newer_post)
    end

    def older_link
      link_to 'older', post_path(older_post)
    end

  private

    def controller()          @controller                             end
    def params()              controller.params                       end
    def view_context()        controller.view_context                 end

    def newer_post
      Post.where(['id > ?', post.id]).last
    end

    def older_post
      Post.where(['id < ?', post.id]).first
    end    

    def post
      get_controller_variable(:post)
    end

    def get_controller_variable(sym)
      controller.instance_variable_get("@#{sym}")
    end

    def method_missing(*args, &block)
      view_context.send(*args, &block)
    end

end

现在,让我们在你的PostsController中说,你可以这样做:

class PostsController < ApplicationController

  def show
    @post = Post.find_some_clever_way
    @presenter = Posts::ShowPresenter.new(self)
    ...
  end

end

在你的部分内容中,你现在应该能够做到这样的事情:

<ul>
  <li><%= @presenter.older_link %></li>
  <li><%= @presenter.newer %></li>
  <li><%= link_to 'show all', posts_path %></li>
</ul>

大部分神奇之处在于method_missing定义。它基本上允许您的演示者使用控制器中的view_context来执行渲染link_to和生成post_path等内容。

答案 1 :(得分:0)

您应该将路径传递给助手:

# View
PostsHelper::Links.new(@post, posts_path)

# Helper
module PostsHelper
  class Links
    def initialize(post, path)
      @post = post
      @path = path
    end

或者,正如this SO answer所述,您可以像这样访问路线助手:

Rails.application.routes.url_helpers.posts_path
Rails.application.routes.url_helpers.posts_url(:host => "example.com")

答案 2 :(得分:0)

您需要在自定义帮助程序中包含ActionView::Helpers::UrlHelper视图助手link_to,并为路径生成Rails.application.routes提供include ActionView::Helpers::UrlHelper module PostsHelper class Links delegate :url_helpers, to: 'Rails.application.routes' def initialize(post) @post = post end def newer link_to 'newer', url_helpers.post_path(newer_post) end def older link_to 'older', url_helpers.post_path(older_post) end private attr_reader :post def newer_post Post.where(['id > ?', post.id]).last end def older_post Post.where(['id < ?', post.id]).first end end end

试试这个:

import curses

from curses.wrapper import wrapper


def main(scr):
    scr.box()
    scr.refresh()
    c = scr.getch()


wrapper(main)