Rails 4范围无效

时间:2015-10-27 20:25:47

标签: ruby-on-rails

在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不需要执行!

5 个答案:

答案 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