I'm in the process of building an edit form. I have completed the form and it renders as it should. When I go to submit the update to the form I get a no route error. The path to my edit page is for example '/topics/1/bookmarks/1/edit'. This page loads perfectly fine. That page contains a partial of the form that will be used to edit the record. When I select the submit button however it re-routes to '/topics/1/bookmarks/1' and gives me the following:
Routing Error
No route matches [PATCH] "/topics/1/bookmarks/1"
Below are the files that should be of importance let me know if there is something I did not share. That would be important to view.
bookmarks_controller.rb
def edit
#topic = Topic.find(params[:topic_id])
#bookmark = Bookmark.find(params[:id])
end
def update
#topic = Topic.find(params[:topic_id])
#bookmark = Bookmark.find(params[:id])
if #bookmark.update_attributes(params.require(:bookmark).permit(:url, :topic_id, :description))
flash[:notice] = "Bookmark was updated"
redirect_to [#topic, #bookmark]
else
flash[:error] = "There was an error saving the Bookmark. Please try again."
render :edit
end
end
config/routes.rb
resources :topics do
resources :bookmarks, only: [:show, :new, :edit]
end
bookmarks/_form.html.erb
<%= form_for [topic, bookmark] do |f| %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.label :url %>
<%= f.text_field :url %>
<%= f.submit %>
<% end %>
bookmarks/edit.html.erb
<%= render partial: 'form', locals: {topic: #topic, bookmark: #bookmark} %>
You don't have an update route, which is what actually updates the database. Just change
resources :bookmarks, only: [:show, :new, :edit]
to
resources :bookmarks, only: [:show, :new, :edit, :update]
OR better yet,
resources :bookmarks, except: [:index, :create, :destroy]
If you have a new action, then you should want a create action too. So, finally:
resources :bookmarks, except: [:index, :destroy]
Related
I've got a one to many relationship with one movie per list entry, where a movie can be used in a list entry. My list_entries table has a movie_id and a list_id.
database schema
I've nested list_entries in lists so I can pass the list_id directly when creating a new instance.
Rails.application.routes.draw do
devise_for :users
root to: 'pages#home'
resources :movies, only: [:new, :index, :create, :show, :destroy, :edit, :update]
resources :users, only: [:show, :edit, :update]
resources :lists, only: [:new, :create, :show, :index, :destroy] do
resources :list_entries
end
end
Right now I can create and destroy list entries but I have to specify the movie id manually.
The UX I want to achieve is for the user to be able to search for movies from themy list_entries/new form but I don't even know where to begin.
The form as it is now:
<%= simple_form_for #list_entry, url: list_list_entries_path do |f| %>
<%= f.input :comment %>
<%= f.input :movie_id %>
<%= f.submit "Add", class: "btn devise-button" %>
<% end %>
My list entries controller:
class ListEntriesController < ApplicationController
before_action :find_list, only: [:index, :create, :show, :new, :destroy]
def new
#list_entry = ListEntry.new
end
def index
#list_entries = ListEntry.where(list: #list)
end
def show
#list_entry = ListEntry.find(params[:id])
end
def destroy
#list_entry = ListEntry.find(params[:id])
#list_entry.destroy
redirect_to list_list_entries_path
end
def create
#list_entry = ListEntry.new(entry_params)
#list_entry.list_id = params[:list_id]
if #list_entry.save
redirect_to list_list_entries_path
else
render 'new'
end
end
private
def find_list
#list = List.find(params[:list_id])
end
def entry_params
params.require(:list_entry).permit(:comment, :movie_id)
end
end
If you don't want to manually specify a movie_id in the form, you can use the simple_form_for association helper:
<%= f.input :comment %>
<%= f.association :movie %>
I believe it should be labeled based off of the movie title, but if not, you may have to specify a #to_label method in your Movie model.
Alternatively, you could query for the movies in your #new action and use them to do whatever you like in your view:
def new
#list_entry = ListEntry.new
#movies = Movie.all # or whatever query you think is relevant
end
The #collection_select documentation might be useful here:
https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select
I am trying to access an "edit" link to edit an object, but I'm getting this error:
Param is missing or the value is empty: preview
Basically, I have 2 models that I linked through association:
Game model
Review model
I'm rendering reviews in the Game's show page. When I try to edit a review, it's saying I'm missing params or the value is empty in the Reviews controller.
The routes are also nested. How can I fix this?
Thanks in advance :)
routes.rb
Rails.application.routes.draw do
devise_for :users
root "games#index"
resources :games do
resources :news
resources :reviews, except: [:show, :index]
resources :previews, except: [:show, :index]
end
resources :platforms
resources :genres
end
show.html.erb (Linked to Games controller)
<% if #news.last.created_at > preview.updated_at %>
<p><%= link_to "edit", edit_game_preview_path(#game.id, preview.id) %></p>
<% end %>
<p><%= link_to "delete", game_preview_path(#game.id, preview.id), method: :delete %></p>
<% end %>
Reviews partial (Form)
<%= form_for [#game, #previews.new] do |r| %>
<h3 class="post_review">Preview this game</h3>
<p><%= flash[:notice_submit] %></p>
<p><%= r.text_field :title, placeholder: "Enter your tagline" %></p>
<p><%= r.text_area :content, placeholder: "Enter your review here" %></p>
<p><%= r.text_area :vote %></p>
<p><%= r.hidden_field :game_id, value: #game.id %></p>
<%= r.submit %>
<% end %>
Reviews controller
class PreviewsController < ApplicationController
before_action :authenticate_user!
before_action :set_preview, only: [:show, :edit, :update, :destroy]
before_action :set_game
def new
#preview = Preview.new
end
def create
#preview = Preview.new(preview_params)
#preview.user_id = current_user.id
#preview.game_id = #game.id
#preview.username = current_user.username
if #preview.save
redirect_to :back
flash[:notice_submit] = "Thanks for you comment!"
else
redirect_to :back
flash[:notice_submit] = "Either you've already voted, or you're not filling in all forms."
end
end
def edit
#preview.update(preview_params)
redirect_to #game
end
def destroy
#preview.destroy
redirect_to #game
end
private
def set_preview
#preview = Preview.find(params[:id])
end
def set_game
#game = Game.find(params[:game_id])
end
def set_user
#user = User.find(params[:user_id])
end
def preview_params
params.require(:preview).permit(:title, :content, :vote)
end
end
You are getting this error because in your preview_params you are requiring a preview object.
I think your controller logic for the edit action is invalid. For the edit action, you just need to set_preview and then render the edit template. The current logic in your edit action should go in an update action.
def edit
end
def update
#preview.update(preview_params)
redirect_to #game
end
Also the first line of your form should be:
<%= form_for [#game, #preview] do |r| %>
I can't manage to get my destroy action in my controller to work. I've read that you have to include default javascript libraries to delete, but I've done that (at least I think I have), and it still doesn't work. Background on my app: articles are "recipes", so my controller is called recipes_controller. Here's the code from my recipes_controller:
class RecipesController < ApplicationController
before_action :authenticate, except: [:index, :show]
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
#recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
end
# DELETE /recipes/1
# DELETE /recipes/1.json
def destroy
#recipe.destroy
respond_to do |format|
format.html { redirect_to recipes_url, notice: 'Recipe was
successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_recipe
#recipe = Recipe.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def recipe_params
params.require(:recipe).permit(:title, :body, :published_at, :category_ids => [])
end
end
Then, here's the code for my application.html.erb file, where I thought i had included the default javascript libraries:
<html>
<head>
<title>inherentlydope</title>
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>d
<%= csrf_meta_tag %>
</head>
<body>
<%= content_tag :p, notice, :class => 'notice' if notice.present? %>
<%= content_tag :p, alert, :class => 'alert' if alert.present? %>
<%= yield %>
</body>
</html>
Then, here's my routes.rb file:
Rails.application.routes.draw do
root to: "recipes#index"
#resources :comments
resources :recipes do
resources :comments
end
resources :users
resource :session, only: [:new, :create, :destroy] #always deal with session, not sessionS
get '/login' => "sessions#new",as: "login"
get '/logout' => "sessions#destroy", as: "logout"
end
Im getting this weird error when i want to update my model (model name carts).
Error : The action 'update' could not be found for CartsController
this is my carts_controller.rb :
class CartsController < ApplicationController
include CartForcable
before_action :scoped_cart, only: [:show, :update]
def show
end
private
def scoped_cart
force_cart! lambda {|r| r.includes(:entries => {:sign => [:dimensions, :substrates]})}
end
def update
#cart = #cart.find(params[:id])
if #cart.update_attributes(cart_params)
flash[:notice] = translate 'flash.notice'
else
flash[:error] = translate 'flash.error'
end
support_ajax_flashes!
respond_to do |format|
format.html # renders view
format.json { render json: #entry }
end
end
end
and these are my routes.rb :
resources :categories, only: [:index] do
resources :signs, shallow: true, only: [:index]
end
resources :carts, only: [:show, :update]#, param: :cart_permalink
resource :cart, as: :user_cart, only: [:show, :update], param: :cart_permalink do
resources :cart_entries, only: [:index, :create, :update, :destroy], as: 'entries', path: 'entries'
end
resource :user, only: [:edit, :show, :update], as: 'current_user', path: 'profile'
resources :signs, only: [:show]
resources :pages, only: [:show], param: :permalink
and my show.html.erb has this form :
<%= form_for #cart, :url => {:controller => "carts", :action => "update" } do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :regnum %>
<%= f.text_field :regnum %></br>
<%= button_to "Order/update", {:controller => "carts",:action =>
'update', :id => #cart.id }, :method => :update %>
<% end %>
After i enter name or number (for example), and click update button or something, it doesnt upload any data into model carts(which has the right columns).
Thanks,
Michael
Your update method is private; controller actions need to be public. Move
def update
#cart = Cart.find(params[:id])
...
end
to be above the
private
line. You need to do the find on the Cart model, not a #cart instance.
You can use a show action although edit would be more standard and fits right in with the RESTful routes without the need to override convention. The Rails routing guide should help here: http://guides.rubyonrails.org/routing.html
Additionally, you need to define the value of #cart in your edit action:
def edit
#cart = Cart.find(params[:id])
end
This will ensure it has a value on the edit form and so comes back into your update action through the parameters.
So if you try to edit a cart with something like /carts/12345/edit (where 12345 is the id of the cart you want to update) it should all hang together.
This looks wrong:
#cart = #cart.find...
don't you mean...?:
#cart = Cart.find...
And it seems you are using "cart_permalink" instead of "id" on your routes
resource :cart, as: :user_cart, only: [:show, :update], param: :cart_permalink do
Check the server log and see the name of the parameter that holds the ID, also run "bundle exec rake routes" to double check.
I am new to rails and am trying create a forum. The forum has many topics, topics belong to a forum and have many microposts, and microposts belong to both topics and users. However, no matter what I try, the posts will not be created. Currently when I try to post, I get the routing error "No route matches [GET] "/topics""
My routes.rb file:
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :microposts, only: [:create, :destroy]
resources :forums, only: [:index, :show]
resources :topics, only: [:show]
_micropost_form.html.erb
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.hidden_field :topic_id, value: #topic.id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.text_field :summary, placeholder: "One-line summary..." %>
<%= f.text_area :content, placeholder: "Compose a new post..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
microposts_controller.rb
class MicropostsController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
##topic = Topic.find_by_id(params[:topic_id])
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
flash[:success] = "Your solution has been posted!"
redirect_to topic_path(#topic)
else
redirect_to topic_path(#topic)
end
end
def destroy
#micropost.destroy
redirect_to root_url
end
private
def micropost_params
params.require(:micropost).permit(:summary, :content, :user_id)
end
def correct_user
#micropost = current_user.microposts.find_by(id: params[:id])
redirect_to root_url if #micropost.nil?
end
end
As you can see, I commented out the first line in my create function because I've tried posting based on the the micropost's relationship to the topic to no avail. Thanks in advance and let me know if it would help if I posted more code!
In your :topics resource, you didn't defined the index method, that's why you won't be able to get to topic's list or index page. Try to change your route like this:
resources :topics, only: [:index, :show]
or remove only attribute from resources, it will automatically include all your methods by default.
resources :topics
Also if you have relationship between models, you should define nested routes in your routes
file, For example, you can define them like this, you can change them accordingly:
try to change your route file like this:
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :forums do
resources :topics do
resources :microposts, only: [:new, :create, :destroy]
end
end
In above case, you can access your forums like this:
http://localhost:3000/forums
you can access your topics like this:
http://localhost:3000/forums/id/topics
you can access your microposts like this:
http://localhost:3000/forums/id/topics/id/microposts
If you want to access /microposts directly you have to put it outside any resource.
resources :microposts, only: [:index]
now you will be able to access it:
http://localhost:3000/microposts
Hope it will help. Thanks.