Reputation: 1
I'm very very new to this, and I'm trying to implement a to-do-list which allows use of tags with user authentication. When updating the task, I get a routing error which states No route matches [PATCH] "/users/1/articles". I suspect it's because I didn't pass the article ID when updating the article. Could anyone please help guide me on how to solve this? Any advice will be greatly appreciated thank you!
Routes from the error page
user_article_path GET /users/:user_id/articles/:id(.:format)
articles#show
PATCH /users/:user_id/articles/:id(.:format)
articles#update
PUT /users/:user_id/articles/:id(.:format)
articles#update
DELETE /users/:user_id/articles/:id(.:format)
articles#destroy
Routes.rb
Rails.application.routes.draw do
get 'sessions/new'
get 'welcome/index'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users do
resources :articles
end
get 'tags/:tag', to: 'articles#index', as: :tag, :constraints => { :tag => /[^\/]+/ }
root 'welcome#index'
end
article.rb
class Article < ApplicationRecord
attr_accessor :content, :name, :tag_list
before_create :downcase_fields
has_many :taggings , dependent: :destroy
has_many :tags, through: :taggings, dependent: :destroy
belongs_to :user
validates :user_id, presence: true
validates :title, presence: true,
length: { minimum: 1}
def self.tagged_with(name)
Tag.find_by_name!(name).articles
end
def downcase_fields
self.title.downcase
end
def self.tag_counts
Tag.select("tags.*, count(taggings.tag_id) as count").
joins(:taggings).group("taggings.tag_id")
end
def tag_list
tags.map(&:name).join(", ")
end
def tag_list=(names)
self.tags = names.split(",").map do |n|
Tag.where(name: n.strip).first_or_create!
end
end
def self.search(term)
if term
where('title LIKE ?', "%#{term}%").order('id DESC')
else
order('id DESC')
end
end
end
articles_controller
class ArticlesController < ApplicationController
before_action :correct_user
def index
@user = User.find(params[:user_id])
@articles = @user.articles.search(params[:term])
# if params[:tag]
# @articles = @user.articles.tagged_with(params[:tag])
# else
# @articles = @user.articles.all
# end
end
def show
@user = User.find(params[:user_id])
@article = @user.articles.find(params[:id])
end
def new
@user = User.find(params[:user_id])
@article = @user.articles.new
end
def edit
@user = User.find(params[:user_id])
@article = @user.articles.find(params[:id])
end
def create
@user = User.find(params[:user_id])
@article = @user.articles.new(article_params)
if @article.save
redirect_to user_articles_url
else
render 'new'
end
end
def update
@user = User.find(params[:user_id])
@article = @user.articles.find(params[:id])
if @article.update(article_params)
redirect_to user_articles_path
else
render 'edit'
end
end
def destroy
@user = User.find(params[:user_id])
@article = @user.articles.find(params[:id])
@article.destroy
redirect_to user_articles_path
end
private
def article_params
params.require(:article).permit(:title, :text, :tag_list, :term)
end
# Confirms a logged_in user_
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user
def correct_user
@user = User.find(params[:user_id])
redirect_to(root_url) unless current_user?(@user)
end
end
db.schema.rb
ActiveRecord::Schema.define(version: 2019_01_27_093653) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "articles", force: :cascade do |t|
t.string "title"
t.text "text"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "user_id"
t.index ["user_id"], name: "index_articles_on_user_id"
end
create_table "taggings", force: :cascade do |t|
t.bigint "tag_id"
t.bigint "article_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "user_id"
t.index ["article_id"], name: "index_taggings_on_article_id"
t.index ["tag_id"], name: "index_taggings_on_tag_id"
t.index ["user_id"], name: "index_taggings_on_user_id"
end
create_table "tags", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.index ["email"], name: "index_users_on_email", unique: true
end
add_foreign_key "articles", "users"
add_foreign_key "taggings", "articles"
add_foreign_key "taggings", "tags"
add_foreign_key "taggings", "users"
end
User controller
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update]
before_action :correct_user, only: [:edit, :update]
def show
@user = User.find(params[:id])
redirect_to user_articles_path(@user)
end
def new
@user = User.new
end
def index
@users = User.paginate(page: params[:page])
end
def create
@user = User.new(user_params)
if @user.save
log_in @user
flash[:success] = "Welcome to the To-Do-Manager!"
redirect_to user_articles_path(@user)
else
render 'new'
end
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
if @user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to @user
else
render 'edit'
end
end
private
_form.html.erb(Create and update share the same form)
<%= form_with model: @article,url: user_articles_path(@user), local: true do |form| %>
<% if @article.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(@article.errors.count, "error") %> prohibited
this article from being saved:
</h2>
<ul>
<% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= form.label :Task %><br>
<%= form.text_field :title %>
</p>
<p>
<%= form.label :Deadline %><br>
<%= form.text_area :text %>
</p>
<p>
<%= form.label :tag_list, "Tags (separated by commas)" %><br />
<%= form.text_field :tag_list %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Upvotes: 0
Views: 1259
Reputation: 15838
You routes requires two parameters: the user (:user_id) and the article (:id), you are only passing the user user_articles_path(@user)
and also using the plural form, and that route does not exists with that HTTP method.
You have to use url: user_article_path(@user,@article)
(or you can use the shortcut version url: [@user, @article]
).
Upvotes: 0
Reputation: 5609
Your user article path should be singular according to your routes:
<%= form_with model: @article, url: user_article_path(@user), local: true do |form| %>
Upvotes: 1