在Rails 4应用程序中,范围对我来说并不适合。
型号:
class Todo < ActiveRecord::Base
...
scope :completed, -> { where(completed: true) }
scope :notcompleted, -> { where(completed: false) }
end
路线:
get 'todos/completed'
控制器:
class TodosController < ApplicationController
before_action :set_todo, only: [:show, :edit, :update, :destroy]
def completed
@todos = current_user.todos.completed
end
...
def set_todo
@todo = Todo.find(params[:id])
end
查看:
...
<% @todos.each do |todo| %>
...
我得到了:
Couldn't find Todo with 'id'=completed
in the set_todo logic
我不明白为什么它会达到set_todo
逻辑。即使我使用set_todo
before_action :set_todo, except: [:index, :create, :completed]
不知何故,代码set_todo
不需要执行!
答案 0 :(得分:1)
我不确定范围是否适用于current_user.todos
生成的集合。如the docs中所示,作用域是一种作用于模型的类方法。
如果您反转查询,那应该没问题。
Todo.completed.where(user_id: current_user.id)
答案 1 :(得分:1)
#config/routes.rb
resources :todos do
get :completed, on: :collection #-> url.com/todos/completed
end
<强>解释强>
您的旧路线可能看起来像这样:
#config/routes.rb
resources :todos
get "todos/complete"
当您向Rails发送请求时,它会查看路线并匹配您要求的路线。
使用resources :todos
,您可以获得路线/todos/:id
。
这意味着每当您请求网址url.com/todos/x
时,Rails都会调用由todos#show
填充的set_todo
操作。
这就是您收到Couldn't find Todo with 'id'=completed
错误的原因 - Rails正在将您的请求发送到 show 操作。
您需要 来定义上面的get 'todos/complete'
resources :todos
:
#config/routes.rb
get "todos/complete"
resources :todos
......或(推荐),create an extra route:
#config/routes.rb
resources :todos do
get :completed, on: :collection
end
另外,您的范围可以稍微清理一下:
#app/models/todo.rb
class Todo < ActiveRecord::Base
scope :completed, ->(trigger = true) { where completed: trigger }
end
这将允许您使用带有传递参数的单个completed
范围:
@todos.completed
@todos.completed(false)
答案 2 :(得分:0)
使用类方法
def self.completed
where(completed: true)
end
http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html
答案 3 :(得分:0)
试试这个范围:
scope :completed, proc{ |todo| where('completed = ?', true) }
答案 4 :(得分:0)
您所获得的错误不在范围内,而在您的.find
逻辑中。您的set_todo
运行Todo.find(params[:id])
。 没有理由为completed
控制器操作执行此操作,因为它具有所需的所有信息而不使用params哈希(不需要用户输入来查找哪些记录已完成)。击>
另一个问题是,在这种情况下,您的params[:id]
可能不会被填充,因为看起来/todos/completed
看起来像收集路线。
我会将其嵌套在get todos/complete
资源:
todo
resources :todos do
collection do
get 'completed'
end
end
或明确指示路线映射
get '/todos/completed', to: 'todos#completed'
实际上,看起来get todos/completed
正在击中路由表的错误部分。
最后,你可能想要创建一个&#34; completed_todos&#34; User
上的关联,它将把逻辑移到模型中(我认为它属于该模型)
class User < ActiveRecord::Base
has_many :todos
has_many :completed_todos, -> { where(completed: true) }
end