I try to create comments for post, it gives me this error
ActiveModel::ForbiddenAttributesError in CommentsController#create
ActiveModel::ForbiddenAttributesError
Extracted source (around line #6):
This is my comments_controller.rb
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to #pin, notice: 'Comment was successfully created.' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
end
This is my comment model
class Comment < ActiveRecord::Base
belongs_to :post
end
This is my comment create table migration
class CreateComments < ActiveRecord::Migration
drop_table :comments
def change
create_table :comments do |t|
t.integer :post_id
t.integer :user_id
t.text :content
t.timestamps null: false
end
end
end
I hope you will help me.
Your comments_controller should look somewhat like this:
def new
#comment = Comment.new
end
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to #pin, notice: 'Comment was successfully created.' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
private
def comment_params
params.require(:comment).permit(:post_id, :user_id, :content)
end
And, I highly recommend you to read the Rails Official documentation for Strong Parameters.
It seems like you didn't register your strong parameter of comments.
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to #pin, notice: 'Comment was successfully created.' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
private
def comment_params
params.require(:comment).permit(:post_id, :user_id, :content)
end
end
Do you have the params set in the file, it looks like you did not post the whole thing but if not, try something like this.
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.new(comment_params)
Then down at the bottom of the file make a private method
private
def comment_params
params.require(:comment).permit(:post_id,:user_id,:content)
end
Related
I'm new to Ruby on Rails and would appreciate any support!
Users can create a case and select a specific diagnosis via dropdown. The Admin (called 'rki') can see a list of all diagnoses in the database. Now I'm trying to implement that the admin can choose a specific diagnosis und get a list of all cases, with that diagnosis.
This is my RkisController
class RkisController < ApplicationController
before_action :authenticate_user!
before_action :current_user_rki?
def current_user_rki?
return if current_user.role == 'rki'
redirect_to root_path
end
def index
#diagnoses = Diagnosis.all
end
def all_cases
#show all cases with a certain diagnosis
end
end
And this is my Model for Case
class Case < ApplicationRecord
belongs_to :user
belongs_to :diagnosis
belongs_to :district
end
Diagnosis
class Diagnosis < ApplicationRecord
has_many :cases
end
CasesController
class CasesController < ApplicationController
before_action :set_case, only: [:show, :edit, :update, :destroy, :confirm]
def index
#cases = current_user.cases
end
def show
end
def new
#case = Case.new
#case.user_id = current_user.id
end
def edit
end
def create
#case = Case.new(case_params) do |c|
c.user_id = current_user.id
end
#case.district = current_user.district
respond_to do |format|
if #case.save
format.html { redirect_to #case, notice: 'Case was successfully created.' }
format.json { render :show, status: :created, location: #case }
else
format.html { render :new }
format.json { render json: #case.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #case.update(case_params)
format.html { redirect_to #case, notice: 'Case was successfully updated.' }
format.json { render :show, status: :ok, location: #case }
else
format.html { render :edit }
format.json { render json: #case.errors, status: :unprocessable_entity }
end
end
end
def destroy
#case.destroy
respond_to do |format|
format.html { redirect_to cases_url, notice: 'Case was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def allowed_to_create
redirect_to root_path unless current_user.role.in?(['arzt', 'labor'])
end
def set_case
#case = Case.find(params[:id])
end
def case_params
params.require(:case).permit(:first_name, :last_name, :gender,:birthdate, :place_of_residence,
:diagnosis_id, :user_id, :case_id, :confirmed_at, :district_id)
end
end
DiagnosisController
class DiagnosesController < ApplicationController
before_action :set_diagnosis, only: [:show, :edit, :update, :destroy]
def index
#diagnoses = Diagnosis.all
end
def show
end
def new
#diagnosis = Diagnosis.new
end
def edit
end
def create
#diagnosis = Diagnosis.new(diagnosis_params)
respond_to do |format|
if #diagnosis.save
format.html { redirect_to #diagnosis, notice: 'Diagnosis was successfully created.' }
format.json { render :show, status: :created, location: #diagnosis }
else
format.html { render :new }
format.json { render json: #diagnosis.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #diagnosis.update(diagnosis_params)
format.html { redirect_to #diagnosis, notice: 'Diagnosis was successfully updated.' }
format.json { render :show, status: :ok, location: #diagnosis }
else
format.html { render :edit }
format.json { render json: #diagnosis.errors, status: :unprocessable_entity }
end
end
end
def destroy
#diagnosis.destroy
respond_to do |format|
format.html { redirect_to diagnoses_url, notice: 'Diagnosis was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_diagnosis
#diagnosis = Diagnosis.find(params[:id])
end
def diagnosis_params
params.require(:diagnosis).permit(:illness)
end
end
Thank you very much in advance.
Are you wanting to go to a show page from the index of diagnosis? If so you can just use the id from the index, passed to the show, ie normal flow. And then in your diagnosis show action you can have
def show
#diagnosis = Diagnosis.includes(:cases).find_by(id: params[:id])
end
And then if using erb you can iterate through the cases
<% #diagnosis.cases.each do |case| %>
<%= case.name %>
<% end %>
I get for what is this error, but I can't see a mistake in my code.
A controller is plural, a model is singular and the table name is plural.
Error on visiting index:
NameError at /admin/custom_communities uninitialized constant
Admin::CustomCommunitiesController::CustomCommunity
Generated controller: (file: controllers/admin/custom_communities_controller.rb)
# frozen_string_literal: true
class Admin::CustomCommunitiesController < Admin::BaseController
before_action :set_custom_community, only: [:show, :edit, :update, :destroy]
def index
#custom_communities = CustomCommunity.page(params[:page])
end
def show; end
def new
#custom_community = CustomCommunity.new
end
def edit; end
def create
#custom_community = CustomCommunity.new(custom_community_params)
respond_to do |format|
if #custom_community.save
format.html { redirect_to #custom_community, notice: "Custom community was successfully created." }
format.json { render :show, status: :created, location: #custom_community }
else
format.html { render :new }
format.json { render json: #custom_community.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #custom_community.update(custom_community_params)
format.html { redirect_to #custom_community, notice: "Custom community was successfully updated." }
format.json { render :show, status: :ok, location: #custom_community }
else
format.html { render :edit }
format.json { render json: #custom_community.errors, status: :unprocessable_entity }
end
end
end
def destroy
#custom_community.destroy
respond_to do |format|
format.html { redirect_to admin_custom_communities_url, notice: "Custom community was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_custom_community
#custom_community = CustomCommunity.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def custom_community_params
params.require(:custom_community).permit(:name, :description, :picture, :should_delete_picture)
end
end
Model: (file: models/custom_community.rb)
# frozen_string_literal: true
class CustomCommunity < ApplicationRecord
end
Migration:
class CreateCustomCommunities < ActiveRecord::Migration[5.2]
def change
create_table :custom_communities do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
Routes:
in admin routes:
resources :custom_communities
I'm sure someone else can explain why, but there are times rails will think that the following class in the index method:
class Admin::CustomCommunitiesController < Admin::BaseController
def index
CustomCommunity.all
end
end
Is referencing a class defined within the Admin::CustomCommunitiesController, i.e. it thinks you're trying to call Admin::CustomCommunitiesController::CustomCommunity.all. To 'unnamespace' the class, try:
# frozen_string_literal: true
class Admin::CustomCommunitiesController < Admin::BaseController
before_action :set_custom_community, only: [:show, :edit, :update, :destroy]
def index
#custom_communities = ::CustomCommunity.page(params[:page])
end
def show; end
def new
#custom_community = ::CustomCommunity.new
end
def edit; end
def create
#custom_community = ::CustomCommunity.new(custom_community_params)
respond_to do |format|
if #custom_community.save
format.html { redirect_to #custom_community, notice: "Custom community was successfully created." }
format.json { render :show, status: :created, location: #custom_community }
else
format.html { render :new }
format.json { render json: #custom_community.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #custom_community.update(custom_community_params)
format.html { redirect_to #custom_community, notice: "Custom community was successfully updated." }
format.json { render :show, status: :ok, location: #custom_community }
else
format.html { render :edit }
format.json { render json: #custom_community.errors, status: :unprocessable_entity }
end
end
end
def destroy
#custom_community.destroy
respond_to do |format|
format.html { redirect_to admin_custom_communities_url, notice: "Custom community was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_custom_community
#custom_community = ::CustomCommunity.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def custom_community_params
params.require(:custom_community).permit(:name, :description, :picture, :should_delete_picture)
end
end
I think that's all of them. Basically switch every CustomCommunity class call to ::CustomCommunity to unnamespace it.
I'm trying to create a form that allow called submits. I've got all the appropriate MVC created. I've then created a model called questions that works and am using active admin to allow admin users to add new questions to the form as they see fit. When I test submitting the form I get this error
undefined method `each' for nil:NilClass
#submit = Submit.new(submit_params)
#submit.save
params[:submit][:question_ids].each do |question_id|
#question = Question.find(question_id)
#submit.questions << #question
end
Here's my submits controller:
class SubmitsController < ApplicationController
before_action :set_submit, only: [:show, :edit, :update, :destroy]
def index
#submits = Submit.all
end
def show
end
def new
#submit = Submit.new
#questions = Question.all
end
def edit
end
def create
#submit = Submit.new(submit_params)
#submit.save
params[:submit][:question_ids].each do |question_id|
#question = Question.find(question_id)
#submit.questions << #question
end
respond_to do |format|
if #submit.save
format.html { redirect_to #submit, notice: 'Application was successfully created.' }
format.json { render :show, status: :created, location: #submit }
else
format.html { render :new }
format.json { render json: #submit.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #submit.update(submit_params)
format.html { redirect_to #submit, notice: 'Application was successfully updated.' }
format.json { render :show, status: :ok, location: #submit }
else
format.html { render :edit }
format.json { render json: #submit.errors, status: :unprocessable_entity }
end
end
end
def destroy
#submit.destroy
respond_to do |format|
format.html { redirect_to submits_url, notice: 'Submit was successfully destroyed.' }
format.json { head :no_content }
end
end
Here's my Submit and Question model:
Submit:
class Submit < ActiveRecord::Base
has_and_belongs_to_many :questions
belongs_to :user
end
Question:
class Question < ActiveRecord::Base
has_and_belongs_to_many :submits
end
I'm sure it's some kind of syntax error in my controller but I don't know what. Still pretty new to using join tables. Any help/explanation would be very appreciated.
Thanks!
You don't need this
params[:submit][:question_ids].each do |question_id|
#question = Question.find(question_id)
#submit.questions << #question
end
I don't see your submit params but if you add question ids to the permitted parameters then rails will build the entry in the join table on it's own.
def submit_params
params.require(:submit).permit(:user_id, question_ids: [])
end
Post embeds many Comments.
_id is an Integer type field for Posts, but a String one - for Comments.
post.rb:
class Post
include Mongoid::Document
include Mongoid::Attributes::Dynamic
field :_id, type: Integer
field :title, type: String
field :content, type: String
embeds_many :comments
accepts_nested_attributes_for :comments
end
comment.rb:
class Comment
include Mongoid::Document
include Mongoid::Attributes::Dynamic
field :_id, type: String
field :content, type: String
embedded_in :post
end
posts_controller.rb:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:_id, :title, :content)
end
end
comments_controller.rb:
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
def index
#post = Post.find(params[:post_id])
#comments = #post.comments
end
def show
end
def new
#post = Post.find(params[:post_id])
#comment = #post.comments.new
end
def edit
#comment = #post.comments.find(params[:id])
end
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to post_path(#post), notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, post: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
def update
end
def destroy
end
private
def set_comment
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
end
def comment_params
params.require(:comment).permit(:_id, :content)
end
end
When I add comments it saves only the value for the content field for the comment but not its _id which is entered by me. Though this works for the post model:
> db.posts.findOne()
{
"_id" : 23,
"title" : "First Post",
"content" : "Text of the 1st post",
"comments" : [
{
"content" : "Comment for the 1st post"
},
{
"content" : "2nd comment"
},
{
"content" : "asdfagzcbzcv"
}
]
}
I have this app on github which is publicly available at https://github.com/tenzan/blog.git
Let _id field clean :)
From your post object you got by Post.find( params[:post_id] ), you can do post.comments.find( params[:comment_id] ).
There is no optimisation do to with post.comments[ params[:comment_id] ] (if I correctly understand what you were trying to do).
If you realy want to show a cleaner comment id to you users, you can implement yourself a field like custom_id or use the gem acts_as_list.
I'm getting the following ActiveModel::ForbiddenAttributesError when creating a comment on my app.
The error message precise that the problem comes from line 7 in my Comments Controller file: #comment = #pin.comments.create(params[:comment])
app/controllers/comments_controller.rb
class CommentsController < ApplicationController
before_filter :authenticate_user!
def create
#pin = Pin.find(params[:pin_id])
#comment = #pin.comments.create(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to #pin, notice: 'Comment was successfully created.' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
private
def comment_params
params.require(:comment).permit(:body, :pin_id)
end
end
here is the comment model
class Comment < ActiveRecord::Base
belongs_to :pin
end
Any help with this error message?
You should replace this line with
#comment = #pin.comments.create(comment_params)
Also, putting pin_id in permitted parameters is unnecessary (since you create comment through #pin.comments association) and possibly unsafe (user could associate comment with other Pin).