Rails - Namespace params ID not found - ruby-on-rails

I set up posts in a folder called 'contents' and then it fell over when I tried to delete the records. Why am I getting this error?
No route matches {:action=>"edit", :controller=>"content/stories", :id=>nil} missing required keys: [:id]
Routes.rb
namespace :content do
resources :posts
end
PostsController
def index
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = current_user.posts.new(post_params)
if #post.save
redirect_to content_posts_path
else
redirect_to root_path, notice: #post.errors.full_messages.first
end
end
def show
end
def delete
#post = Post.find(params[:id])
end
def destroy
post = Post.find(params[:id]).destroy
redirect_to :back
end
private
def post_params
params.require(:post).permit(:content)
end
end
show.html
<ol>
<% for p in #posts %>
<li>
<%= p.title %>
<%= link_to 'Edit', edit_content_post_path(#post) %>
<%= link_to 'Delete', content_post_path(#post), method: :delete %>
</li>
<% end %>
</ol>

#post is not defined, you probably need to use p in place of #post.
Also in your show.html which corresponds to show action, not sure how you are getting #posts.

Related

In Rails, show for nested resources not working

I am using nested resources. When I click on a goal that's been created, I keep getting this error:
param is missing or the value is empty: goal
And it directs me to the "params.require..." line:
private
def goal_params
params.require(:goal).permit(:text)
end
I'm not sure what's causing this. I can create and show the list. But when I click on a goal I get this error. I'm new to rails and I'm at my wit's end.
My view:
<h1>Listing goals</h1>
<table>
<tr>
<th>Text</th>
<th></th>
</tr>
<% #user.goals.each do |goal| %>
<tr>
<td><%= link_to goal.text, user_goals_path(#user, #goal)%></td>
</tr>
<% end %>
</table>
<h2>Add a comment:</h2>
<%= form_for([#user, #user.goals.build]) do |form| %>
<p>
<%= form.text_area :text %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
My controller:
class GoalsController < ApplicationController
def index
#user = User.find(params[:user_id])
#goal = #user.goals.find(goal_params)
end
def show
#user = User.find(params[:user_id])
#goal = #user.goals.find(:id)
#also tried goal_params and :goal_id instead of :id
end
def new
#user = User.find(params[:user_id])
#goal = #user.goals.new
end
def create
#user = User.find(params[:user_id])
#goal = #user.goals.build(goal_params)
#goal.user = current_user
if #goal.save
redirect_to new_user_goal_path, notice: "Success!~"
else
redirect_to new_user_goal_path, alert: "Failure!"
end
#to root_path
end
private
def goal_params
params.require(:goal).permit(:text)
end
end
My routes:
Rails.application.routes.draw do
devise_for :users
resources :user do
resources :goals
end
devise_scope :user do
authenticated :user do
root 'home#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
end
My show.html.erb:
<p>
<strong>Text:</strong>
<%= #goal.text %>
</p>
First thing, in the show
#goal = #user.goals.find(:id)
Should be
#goal = #user.goals.find(params[:id])
You said you tried with #user.goals.find(goal_params) in show action and I see it in your index action also. This will call the goal_params method, which require params[:goal] while your index or show request does not send to server, only when you submit the form, you will have that params. This is the cause of your error.
Second thing, your index should use
#goals = #user.goals
INSTEAD OF
#goal = #user.goals.find(goal_params)
Also, the strong parameters is used for create and update actions only to avoid mass assignment to our database. It's not used to find a record.

Get selected value from form.select

I have 2 models - project and todo, and the project contain many todos. I'm trying to write a form that would add a todo to a specific project, that's selected in the tray.
Unfortunately I get an error
Couldn't find Project with 'id'=
from todos_controller when i redirect to /todos
#project = Project.find(params[:project_id])
/projects/index.html.erb
<h1> Задачи </h1>
<% #projects.each do |project_name|%>
<h3><%= project_name.title %></h3>
<ul>
<% project_name.todos.each do |project_todo| %>
<li>
<p><%= project_todo.text %></p>
</li>
<% end %>
</ul>
<% end %>
<h1> Новая задача </h1>
<%= form_with scope: :todo, url: todos_path, local: true do |form| %>
<p>
<% form.label :text %><br>
<%= form.text_field :title, placeholder: "Название задачи" %>
</p>
<%= form.select( :project_id, options_from_collection_for_select(Project.all, :id, :title)) %>
<p>
ОТМЕНА
<%= link_to form.submit %>
</p>
<% end %>
projects_controller.rb
class ProjectsController < ApplicationController
def index
#projects = Project.all
respond_to do |format|
format.html
format.json {render json: #projects}
end
end
todos_controller.rb
class TodosController < ApplicationController
def index
#todos = Todo.all
respond_to do |format|
format.html
format.json {render json: #todos}
end
end
def update
end
def create
#project = Project.find(params[:project_id])
#todo = #project.todo.create(todo_params)
redirect_to projects_path
end
end
routes.rb
Rails.application.routes.draw do
resources :projects, :todos
root 'projects#index'
end
I also could not display the submit button as a text link.
modify create action as
def create
#project = Project.find(params[:todo][project_id])
#todo = #project.todo.create(todo_params)
redirect_to projects_path
end
if not works then check params hash from server log and check project_id is present in params or not.
Above will work but I think you do not need to find project if you modify create action as
def create
#todo = Todo.create(todo_params)
redirect_to projects_path
end
also define method as
def todo_params
params.require(:todo).permit(:project_id, :title)
end
Your controller expects a project_id parameter which is probably not passed! Try to add the project id to your params hash when you trigger the todos#create method
params[:project_id] is nil because the form you are submitting for todo, so you need to access project_id as
Project.find(params[:todo][project_id]) in create action.
So replace your create action as follow
def create
#project = Project.find(params[:todo][project_id])
#todo = #project.todo.create(todo_params)
redirect_to projects_path
end
Dont forget to include project_id in todo_params method.

Rails: Edit Comment without redirecting to the Edit View

I'm building simple web app where people can share their thought / pictures / so on. It has just two controllers Post, and nested in it Comments. Generally, at the moment all works perfectly, users can add, edit and delete posts the same way as comments. The thing I'm trying to do, and have big troubles with, is possibility to Edit comments without redirecting to the Edit Comment View - so to be able to do it from the "posts#show" level, the same way as comments actually are being created. I think it just would look much more nicer... Here are my:
posts_controller.rb
class PostsController < ApplicationController
before_action :find_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all.order(created_at: :desc)
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#comments = #post.comments
end
def edit
end
def update
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
def destroy
#post.destroy
redirect_to root_path
end
private
def find_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :description)
end
end
comments_controller.rb
class CommentsController < ApplicationController
before_action :find_post, only: [:create, :edit, :update, :destroy]
def create
#comment = #post.comments.create(comment_params)
if #comment.save
redirect_to #post
else
render 'new'
end
end
def edit
#comment = #post.comments.find(params[:id])
end
def update
#comment = #post.comments.find(params[:id])
#comment.update_attributes(comment_params)
if #comment.save
redirect_to #post
else
render 'edit'
end
end
def destroy
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to #post
end
private
def find_post
#post = Post.find(params[:post_id])
end
def comment_params
params.require(:comment).permit(:content)
end
end
View show.html.haml - for post
%h1 Show page
%h3= #post.title
%p= #post.description
=link_to "Edit memory", edit_post_path
=link_to "Delete memory", post_path, method: :delete
%h4 Share your thoughts about the memory
- #comments.each do |comment|
%p= comment.content
=link_to "Edit thought", edit_post_comment_path(#post, comment)
=link_to "Delete thought", post_comment_path(#post, comment), method: :delete
= simple_form_for([#post, #post.comments.build]) do |c|
= c.input :content
= c.submit "Share thought"
View edit.html.haml - for comments (the one I'd like to get rid of / nest somehow to the view shown above)
= simple_form_for([#post, #comment]) do |c|
= c.input :content
= c.submit "Update thought"
I believe there is a simple solution, however despite the fact that I've been reading a lot about possible solution, for a newbie like me it's still difficult to figure out how this should be programed.
The terminology you're looking for is in-place editing, or inline editing
You'll either need a form or JQuery plugin to make any comment written by current_user (assuming you're using Devise) editable.
I've done this a little (you can sign up for free here, click "profile" and then edit the description):
--
The way you'd want to do it is something like this:
#app/assets/javascripts/application.js
# include x-editable scripts
$(".editable).editable([..options..]);
#app/views/posts/index.html.erb
<% #posts.each do |post| %>
<%= post.body %>
<% post.comments.each do |comment| %>
<% if comment.author == current_user %>
<%= content_tag :div, comment.body, class: "editable" %>
<% end %>
<% end %>
<% end %>
I've forgotten how we implemented the provided example; x-editable seems to be the rage now.
Here's how it works:
Include X-Editable (or other plugin) in your app
X-Editable will check for the presence of a .class or #id on an element
Providing such an element will allow X-Editable to make it editable
X-Editable then sends the completed request to the server, acting as Ajax
Looks like there's an x-editable-rails gem you can use:
#Gemfile
gem `x-editable-rails`
#app/assets/javascripts/application.js
#= require editable/bootstrap-editable
#= require editable/rails
#app/views/posts/index.html.erb
<% #posts.each do |post| %>
<% post.comments.each do |comment| %>
<%= editable comment, :body if comment.author == current_user %>
<% end %>
<% end %>

Rails - Updating and deleting content?

EDIT: I managed to delete! i had to define teh instance variable #movies = Movie.find(params[:id]) to the delete method in the controller.
I still can't update though. I get "param is missing or the value is empty: movie"
I forgot to add my contrller! sorry!
I'm trying to replicate one of my in class exercises into another app, for practice.
The idea is to be able to add new movies into a database, and get the option to update their info, and delete them as well. I can add new content, but I can't update them or delete them.
Appreciate any inputs I can get.
Routes.rb
Rails.application.routes.draw do
root "movies#index"
get "/movies", to: "movies#index"
get "/movies/new", to: "movies#new", as: "new_movie"
get '/movies/:id', to: "movies#movie_page", as: "movie_page"
post "/movies", to: "movies#add"
get "/movies/:id/edit", to: "movies#edit", as: "movie_edit"
put "/movies/:id", to: "movies#update"
patch "/movies/:id", to: "movies#update", as: "update_movie"
delete "/movies/:id", to: "movies#delete", as: "delete_movie"
end
Controller
class MoviesController < ApplicationController
def index
#movies = Movie.all
end
def movie_page
#movies = Movie.find(params[:id])
end
def new
#movies = Movie.new
end
def add
#movies = Movie.create(movie_params)
redirect_to movies_path
end
def edit
#movies = Movie.find(params[:id])
end
def update
#movies.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
def delete
#movies = Movie.find(params[:id])
#movies.destroy
# flash[:notice] = "Shirt was deleted."
redirect_to root_path, notice: "Shirt was deleted."
end
def movie_params
params.require(:movie).permit(:title, :description, :year_released)
end
# def set_movie
# #movies = Movie.find(params[:id])
# end
end
Form partial
<%= form_for #movies do |m| %>
<p>
<%= m.label :title %><br>
<%= m.text_field :title %>
</p>
<p>
<%= m.label :description %><br>
<%= m.text_field :description %>
</p>
<p>
<%= m.label :year_released %><br>
<%= m.text_field :year_released %>
</p>
<p>
<%= m.submit %>
</p>
<% end %>
Movie page html (individual movies, labeled by IDs)**I can't update or Delete, no route matches Delete.
When I press Update - I get param is missing or the value is empty: movie
<h1><%= #movies.title %></h1>
<h2>Released on : <%= #movies.year_released %> </h2>
<p> <%= #movies.description %> </p>
<%= link_to "Update", movie_edit_path(#movies) %>
<%= link_to "Delete", movies_path, method: :delete %
Edit page *I cant access this link. the form is the problem
<h1>Edit <%= #movies.title %> Info </h1>
<%= render "form" %>
<%= link_to "Cancel Edit", movie_edit_path(#movies) %>
Many thanks guys
def update
#movie = Move.find(params[:id])
#movie.update(movie_params)
redirect_to movie_path(#movie)
end
on your routes. all you need is resources :movies
you are getting param is empty because you have to pass in the id of the movie to update.
The major issue is that you do not load the variable #movies from the DB before you use it.
def update
#movies.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
def update
#movies.find(params[:id])
#movie.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
Aside from that you have tons of duplication and quite a few idiosyncrasies.
Rails uses these naming conventions for actions:
index
show (not movie_page)
new
create (not add)
edit
update
destroy (not delete)
You should follow them unless you have a damn good reason not to.
class MoviesController < ApplicationController
# cuts the duplication
before_filter :set_movie, except: [:new, :index]
def index
#movies = Movie.all
end
# GET /movies/:id
def show
end
# GET /movies/new
def new
#movie = Movie.new
end
# POST /movies
def create
#movie = Movie.create(movie_params)
redirect_to movies_path
end
# GET /movies/edit
def edit
end
# PUT|PATCH /movies/:id
def update
#movie.update(movie_params)
redirect_to #movie, notice: "Shirt was updated."
end
# DELETE /movies/:id
def destroy
#movie.destroy
redirect_to action: :index
end
private
def movie_params
params.require(:movie).permit(:title, :description, :year_released)
end
def set_movie
# Use the singular form when naming a variable with a single record
# failure to do so may result in tarring and feathering
#movie = Movie.find(params[:id])
end
end

Nested attributes undefined user_comments_path error

I'm trying to follow Ryan Bates polymorphic models tutorial (Rails 3), to implement comments in my photo model. I'm having trouble when trying to create a new comment for photos since I'm in Rails 4 and I have to deal with :comment strong parameters.
Error: undefined method `user_comments_path' for #<#:0x00000107c8a200>
I have nested resources
#Nesting Resources
resources :users do
resources :photos do
resources :comments
resources :tags
end
end
So the route should be /users/friendly-id/photos/friendly-id/comments, but it's getting badly constructed, I have <%= form_for [#user, #commentable, #comment] do |f| %> in my form.
Photo Controller
#create
def show
#photo = Photo.friendly.find(params[:id])
#user = #photo.user
#tag = Tag.new
#tag.photo_id = #photo.id
#category = Category.all
#commentable = #photo
#comments = #commentable.comments
#comment = Comment.new
#zone = Zone.all
respond_to do |format|
format.html #show.html.erb
format.json {render json: #photo}
end
end
Form
<%= form_for [#user, #commentable, #comment] do |f| %>
<% if #comment.errors.any? %>
<div class="error_messages">
<h2>Please correct the following errors.</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Comments controller
class CommentsController < ApplicationController
before_filter :load_commentable
def index
#comments = #commentable.comments
end
def new
#comment = #commentable.comments.new
end
def create
#comment = #commentable.comments.new(comment_params)
if #comment.save
redirect_to #commentable, notice: "Comment created."
else
render :new
end
end
private
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
def comment_params
require(:comment).permit(:photo_id, :user_id, :content)
end
###Error 2: When I put friendly.id instead of only id in `load_commentable` method I get a Forbidden Attribute error.
end
Please someone help! Thank you

Resources