首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建直接到作用域的链接/路由?

如何创建直接到作用域的链接/路由?
EN

Stack Overflow用户
提问于 2014-10-27 04:39:31
回答 1查看 1.1K关注 0票数 0

所以我有一个Post模型,它有以下的作用域:

代码语言:javascript
复制
  scope :unconfirmed, -> { where( status: "unconfirmed") }    
  scope :corroborated, -> { where( status: "corroborated") }
  scope :confirmed, -> { where( status: "confirmed") }

我想做的是,当有人去posts/confirmed,它会显示所有的帖子范围为确认。

做这件事最优雅的方法是什么?此外,如何为routes.rb中的每个作用域创建路径

编辑1

我知道这样做的一种方法是在posts控制器中为每个可枚举范围(即unconfirmed等)创建一个操作。

但是我宁愿在我的索引操作中完成所有这些,所以我呈现并使用了我的index视图。

我在我的Post#Index里试过这样做

代码语言:javascript
复制
if params[:unconfirmed]
  @posts = Post.published.unconfirmed
end

但这只是给了我一个路由错误。

这是一个错误:

代码语言:javascript
复制
Started GET "/unconfirmed" for 127.0.0.1 at 2014-10-27 02:29:51 -0500
Processing by PostsController#show as HTML
  Parameters: {"id"=>"unconfirmed"}
  Post Load (3.0ms)  SELECT  "posts".* FROM "posts"  WHERE "posts"."publication_status" = 1 AND "posts"."slug" = 'unconfirmed'  ORDER BY "posts"."id" ASC LIMIT 1
  Post Load (1.7ms)  SELECT  "posts".* FROM "posts" INNER JOIN "friendly_id_slugs" ON "friendly_id_slugs"."sluggable_id" = "posts"."id" AND "friendly_id_slugs"."sluggable_type" = 'Post' WHERE "posts"."publication_status" = 1 AND ("friendly_id_slugs"."sluggable_type" = 'Post' AND "friendly_id_slugs"."slug" = 'unconfirmed')  ORDER BY "posts"."id" ASC LIMIT 1
Completed 404 Not Found in 28ms

ActiveRecord::RecordNotFound - ActiveRecord::RecordNotFound:
  friendly_id (5.0.4) lib/friendly_id/finder_methods.rb:23:in `find'
   () myapp/controllers/posts_controller.rb:78:in `set_post'

set_post方法是:

代码语言:javascript
复制
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.published.find(params[:id])      
    end

我使用friendly_id作为我的URL。

这是我的routes.rb

代码语言:javascript
复制
  get 'posts/:id' => redirect("/%{id}")
  get '/:friendly_id', to: 'posts#show'
  get 'posts/:friendly_id', to: 'posts#show'

编辑2

我还在犯这个错误。我认为是这样的,因为每当我尝试执行/confirmed或任何其他状态时,我的日志就是这样的:

代码语言:javascript
复制
Started GET "/confirmed" for 127.0.0.1 at 2014-10-31 18:28:55 -0500
  ActiveRecord::SchemaMigration Load (2.2ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by PostsController#show as HTML
  Parameters: {"friendly_id"=>"confirmed"}
Completed 404 Not Found in 58ms

它遵守此路由规则:

代码语言:javascript
复制
  get '/:friendly_id', to: 'posts#show'
  get 'posts/:friendly_id', to: 'posts#show'

即使我将推荐的resources post路由规则放在路由文件的末尾,它仍然会这样做,例如:

代码语言:javascript
复制
  resources :posts do
    collection do
      get 'confirmed' => 'posts#index', status: 'confirmed'
      get 'unconfirmed' => 'posts#index', status: 'unconfirmed'
      get 'corroborated' => 'posts#index', status: 'corroborated'
    end
  end

  root to: "posts#index"

如何使状态路由不被重定向到posts#index操作?

编辑3

看我的完整routes.rb

代码语言:javascript
复制
Rails.application.routes.draw do

  %w[privacy terms].each do |page|
    get page, controller: 'info', action: page
  end

  resources :locations      
  devise_for :users, :path_names => { :sign_up => "register", 
                                      :sign_in => "login", 
                                      :sign_out => "logout",
                                                                            :settings => "settings" },
                    :controllers => { :confirmations => "confirmations" }

  devise_scope :user do
    get "login", :to => "devise/sessions#new"
    get "register", :to => "devise/registrations#new"
        get "settings", :to => "devise/registrations#edit"
    delete "logout",   :to => "devise/sessions#destroy"    
  end

  resources :posts do
    collection do
      get 'confirmed' => 'posts#status', status: 'confirmed'
      get 'unconfirmed' => 'posts#status', status: 'unconfirmed'
      get 'corroborated' => 'posts#status', status: 'corroborated'
    end
  end

  get 'posts/:id' => redirect("/%{id}")
  get '/:friendly_id', to: 'posts#show'
  get 'posts/:friendly_id', to: 'posts#show'

  # This supports legacy URLs e.g:
  # http://www.example.com/rbt/26766-algaj-pays-tribute-to-the-honourable-roger-clarke.html   

  get '/rbt/:name', to: redirect {|path_params, _| "/#{path_params[:name].gsub(/^\d+\-/, '')}" } 
  get ':name',      to: 'posts#show'

  root to: "posts#index"

end

编辑4

谜题的最后一点是这个问题的最初前提,我如何创建一个链接到新创建的路径。

棘手的一点是,我希望基于状态动态创建link_path。

例如,由于新的路由规则,我现在有了confirmed_path, corroborated_path, unconfirmed_path

不过,在我看来,我的看法如下:

代码语言:javascript
复制
<span class="post-status status label<%=render partial: "shared/color", locals: {post: post.status }%>"><%= post.status.try(:upcase) %></span>

我试过这样做:

代码语言:javascript
复制
<span class="post-status status label<%=render partial: "shared/color", locals: {post: post.status }%>"><%= link_to post.status.try(:upcase), post.status.path %></span>

但这给了我一个undefined method path错误。

在正常情况下,我只需进行字符串内插,而Ruby将呈现当前字符串。考虑到Ruby应该解析这条路径,我怀疑这是否可行。

那么,我如何让这个视图根据confirmed_path, corroborated_path, unconfirmed_path是什么来动态地生成post.status呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-27 07:55:48

正如你所看到的,你迷失在路线上。这里,调用posts/confirmed将改为posts#show,而不是posts#index方法。原因是动作包从上到下优先分配路由,并且由于您的路由定义如下:

代码语言:javascript
复制
resources 'posts'
get 'posts/:id' => redirect("/%{id}")
get '/:friendly_id', to: 'posts#show'
get 'posts/:friendly_id', to: 'posts#show'

所有posts/unconfirmedposts/confirmed等都不会使用索引方法,因为它将与posts#show匹配,然后与get 'posts/:friendly_id', to: 'posts#show'匹配。

现在,即使您将您的所有get路由移到顶部,它也永远不会到达您以后可能想要定义的其他方法,因为所有posts/unconfirmedposts/confirmed等都将与get 'posts/:id' => redirect("/%{id}")匹配,并将被重定向为/confirmed/unconfirmed等。

推荐的方法是为单独的路由使用不同的方法,因为在将来,您可能还希望对确认的帖子有一种与确证的帖子不同的行为。为此,您的路线如下所示:

代码语言:javascript
复制
resources :posts do
  collection do
    get 'confirmed'
    get 'unconfirmed'
    get 'corroborated'
  end
end

运行$ rake routes|grep posts将提供:

代码语言:javascript
复制
            confirmed_posts GET    /posts/confirmed(.:format)                          posts#confirmed
          unconfirmed_posts GET    /posts/unconfirmed(.:format)                        posts#unconfirmed
         corroborated_posts GET    /posts/corroborated(.:format)                       posts#corroborated
                      posts GET    /posts(.:format)                                    posts#index
                            POST   /posts(.:format)                                    posts#create
                   new_post GET    /posts/new(.:format)                                posts#new
                  edit_post GET    /posts/:id/edit(.:format)                           posts#edit
                       post GET    /posts/:id(.:format)                                posts#show
                            PATCH  /posts/:id(.:format)                                posts#update
                            PUT    /posts/:id(.:format)                                posts#update
                            DELETE /posts/:id(.:format)                                posts#destroy

然后创建单独的方法,即confirmedunconfirmedcorroborated等。

但是,您始终可以将所有这些路线指向这样的路线(不建议这样做):

代码语言:javascript
复制
resources :posts do
  collection do
    get 'confirmed' => 'posts#status', status: 'confirmed'
    get 'unconfirmed' => 'posts#status', status: 'unconfirmed'
    get 'corroborated' => 'posts#status', status: 'corroborated'
  end
end

然后在你的PostsController

代码语言:javascript
复制
def status
  @posts = Post.published.where(status: params[:status])
end

UPDATE:将routes.rb改为-

代码语言:javascript
复制
Rails.application.routes.draw do

  %w[privacy terms].each do |page|
    get page, controller: 'info', action: page
  end

  resources :locations      
  devise_for :users, :path_names => { :sign_up => "register", 
                                      :sign_in => "login", 
                                      :sign_out => "logout",
                                                                            :settings => "settings" },
                    :controllers => { :confirmations => "confirmations" }

  devise_scope :user do
    get "login", :to => "devise/sessions#new"
    get "register", :to => "devise/registrations#new"
        get "settings", :to => "devise/registrations#edit"
    delete "logout",   :to => "devise/sessions#destroy"    
  end

  resources :posts
  get '/confirmed' => 'posts#status', status: 'confirmed', as: :confirmed
  get '/unconfirmed' => 'posts#status', status: 'unconfirmed', as: :unconfirmed
  get '/corroborated' => 'posts#status', status: 'corroborated', as: :corroborated
  get 'posts/:id' => redirect("/%{id}")
  get '/:friendly_id', to: 'posts#show'
  get 'posts/:friendly_id', to: 'posts#show'

  # This supports legacy URLs e.g:
  # http://www.example.com/rbt/26766-algaj-pays-tribute-to-the-honourable-roger-clarke.html   

  get '/rbt/:name', to: redirect {|path_params, _| "/#{path_params[:name].gsub(/^\d+\-/, '')}" } 
  get ':name',      to: 'posts#show'

  root to: "posts#index"

end

并确保在您的status中有PostsController方法

代码语言:javascript
复制
def status
  # your code for fetching posts goes here!
  render text: params[:status] # this is to show an example that `status` is set properly
end
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26581269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档