所以我有一个Post模型,它有以下的作用域:
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里试过这样做
if params[:unconfirmed]
@posts = Post.published.unconfirmed
end但这只是给了我一个路由错误。
这是一个错误:
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方法是:
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
get 'posts/:id' => redirect("/%{id}")
get '/:friendly_id', to: 'posts#show'
get 'posts/:friendly_id', to: 'posts#show'编辑2
我还在犯这个错误。我认为是这样的,因为每当我尝试执行/confirmed或任何其他状态时,我的日志就是这样的:
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它遵守此路由规则:
get '/:friendly_id', to: 'posts#show'
get 'posts/:friendly_id', to: 'posts#show'即使我将推荐的resources post路由规则放在路由文件的末尾,它仍然会这样做,例如:
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
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。
不过,在我看来,我的看法如下:
<span class="post-status status label<%=render partial: "shared/color", locals: {post: post.status }%>"><%= post.status.try(:upcase) %></span>我试过这样做:
<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呢?
发布于 2014-10-27 07:55:48
正如你所看到的,你迷失在路线上。这里,调用posts/confirmed将改为posts#show,而不是posts#index方法。原因是动作包从上到下优先分配路由,并且由于您的路由定义如下:
resources 'posts'
get 'posts/:id' => redirect("/%{id}")
get '/:friendly_id', to: 'posts#show'
get 'posts/:friendly_id', to: 'posts#show'所有posts/unconfirmed、posts/confirmed等都不会使用索引方法,因为它将与posts#show匹配,然后与get 'posts/:friendly_id', to: 'posts#show'匹配。
现在,即使您将您的所有get路由移到顶部,它也永远不会到达您以后可能想要定义的其他方法,因为所有posts/unconfirmed、posts/confirmed等都将与get 'posts/:id' => redirect("/%{id}")匹配,并将被重定向为/confirmed、/unconfirmed等。
推荐的方法是为单独的路由使用不同的方法,因为在将来,您可能还希望对确认的帖子有一种与确证的帖子不同的行为。为此,您的路线如下所示:
resources :posts do
collection do
get 'confirmed'
get 'unconfirmed'
get 'corroborated'
end
end运行$ rake routes|grep posts将提供:
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然后创建单独的方法,即confirmed、unconfirmed、corroborated等。
但是,您始终可以将所有这些路线指向这样的路线(不建议这样做):
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
def status
@posts = Post.published.where(status: params[:status])
endUPDATE:将routes.rb改为-
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方法
def status
# your code for fetching posts goes here!
render text: params[:status] # this is to show an example that `status` is set properly
endhttps://stackoverflow.com/questions/26581269
复制相似问题