2015-10-27 4 views
0

В приложении Rails 4 область не работает для меня.Rails 4 scope не работает

Модель:

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 не должен выполняться!

ответ

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 отправляет ваш запрос на шоу.

Что вам нужно либо определить 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) 
1

Я не уверен, что области работают над сборником, созданным current_user.todos. Как видно из the docs, область действия - метод класса, который действует на модель.

Если вы отмените запрос, все должно быть хорошо.

Todo.completed.where(user_id: current_user.id)

+0

Хотя это, безусловно, верно, что было бы очень грязно и вводят в заблуждении часть действия контроллера. – ABMagil

+0

Получите ту же ошибку. – Reddirt

+0

У вас есть ассоциация «один-ко-многим», настроенная между пользователями и тодовыми моделями? также, если вы закомментируете код в 'set_todo', эта проблема исчезнет (т. е. вы уверены, что это вызвано здесь) @ABMagil, почему это? – PhilVarg

0

Попробуйте эту область:

scope :completed, proc{ |todo| where('completed = ?', true) } 
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 обдувает неправильно часть таблицы маршрутизации.

Наконец, вы можете просто создать «completed_todos» ассоциации по User, которая будет двигаться логику в модели (где я бы утверждать, что это принадлежит)

class User < ActiveRecord::Base 

    has_many :todos 
    has_many :completed_todos, -> { where(completed: true) } 
end 
+0

'has_many: completed_todos, -> {completed: true}' не работает. Мне не нужна ссылка на todos - например, self.todo.completed? – Reddirt

+0

Обновлено для изменения. Отсутствовал где. Вопрос о том, что поражает 'set_todo', - это вещь' routes.rb' в моем втором абзаце. – ABMagil

+0

'get 'todos/controller', to: 'todos/completed'' дает мне« Missing: action key on the definition definition », пожалуйста, проверьте свои маршруты.« – Reddirt

Смежные вопросы