Can't modify frozen hash - ruby-on-rails

I keep getting the above error everytime i try to run this code below. I am trying to delete information from a form. can you look at the "destroy" method?
class ArticlesController < ApplicationController
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def create
#article = Article.new(params[:article])
#article.save
redirect_to article_path(#article)
end
def destroy
#article = Article.new(params[:article])
#article.delete
#article.save
redirect_to article_path(#article)
end
def edit
#article = Article.find(params[:id])
end
end

You cannot update or save a model after it has been deleted or destroyed. Just remove the #article.save line.
Also, in your destroy method, why would you create a new instance of Article only to delete it on the next line? Your destroy method should have only this
def destroy
#article.delete
redirect_to article_path(#article)
end
You could also define the destroy method in the model instead of the controller and simply say
def destroy
self.delete
end

I experienced the can't modify frozen hash issue and this is the workaround/hack I used to fix it. This is a workaround not final solution.
Drop the table:
- From rails console: ActiveRecord::Migration.drop_table(:table_name)
Increment the model file number by 1, rename the file:
- db/migrate/1234_create_table_name.rb -> 1235_create_table_name.rb
rake db:migrate

Related

Ruby on Rails #article.id and#article.category_id keep getting switched

Can someone tell me why id and category_id keep getting switched in Rails?? im losing my mind! the console says its correctly but when i get an error it shows that params switches it around. This my controller below:
class ArticlesController < ApplicationController
def new
#article = Article.new
#category = Category.find(params[:category_id])
end
def create
#article = Article.new(articles_params)
#category = Category.find(params[:category_id])
# binding.pry
#article.category_id = #category.id
binding.pry
if #article.save
redirect_to category_path(#category)
else
render :new
end
end
def edit
#category = Category.find(params[:category_id])
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
#category = Category.find(params[:category_id])
if #article.update(articles_params)
redirect_to category_path(#category)
else
render :edit
end
end
def destroy
# binding.pry
#article = Article.find(params[:id])
#article.destroy
redirect_to category_path(#category)
end
private
def articles_params
params.require(:article).permit(:title, :body)
end
end
Everything looks fine.
Look below on the request parameters from your screenshot:
{
"id" : 1,
"category_id" : 2
}
You are looking for id 1 in the context of your Article controller.
1 refers to the article with id 1.
Meanwhile you are looking for a Category with id 2 (category_id 2).
Category.find(params[:category_id])
The error is saying that it cannot find a Category object with id 2.
The 2 comes from your request. If something is wrong, it's in your request creation.

value always the same, different in database Rails

This is my ArticleController
def new
#article = Article.new
end
def create
#render plain: params[:article].inspect
#article = Article.new(super_params)
if #article.save
flash[:notice] = "Article has been created"
redirect_to article_path(#article)
else
render 'new'
end
end
def super_params
params.require(:article).permit(:title, :description)
end
def show
#article = Article.find_by( params[:id] )
end
The main problem is that whenever i do: articles/2 or 5 or 6 i get the same article which was created as first. In database records are good i have only this problem with render it.
I know, i did:
find_by
Instead of
find
Sory for trouble...

ForbiddenAttributesError with Active Admin

I 've just started working on ROR.
I made blog app following strictly ROR official doc.
It worked fine for CRDU.
Now I added Active Admin to it, it works fine on delete but gives error while creatiing/updating focusing on
raise ActiveModel::ForbiddenAttributesError
def sanitize_for_mass_assignment(attributes)
if attributes.respond_to?(:permitted?) && !attributes.permitted?
**raise ActiveModel::ForbiddenAttributesError**
else
attributes
end
In Controller, I'm using following code:
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text, :AuthorAge)
end
I think you didn't add permit_params in your active admin file.
# app/admin/xyz.rb
permit_params :comma separated attributes.
Look into this link for more detail.

Fat Model, Skinny Controller in Rails with example

I really want to start learning Rails best practices, especially following the "fat model, skinny controller" logic.
Say I have the following comment controller
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(comment_params)
#comment.user_id = current_user.id if current_user
#comment.save!
if #comment.save
redirect_to post_path(#post)
else
render 'new'
end
end
def edit
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
end
def update
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
if #comment.update(params[:comment].permit(:comment))
redirect_to post_path(#post)
else
render 'Edit'
end
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
private
def comment_params
params.require(:comment).permit(:comment)
end
What's a good place to start refactoring the code?
Immediately I think I an make the #post and #comment in both edit and update into a separate method, follow by calling a before_action on the method. But that is still putting all the code in the controller.
Are there any code that I can move to the model? If so, how should I structure them?
This code doesn't have much room for improvement, it's a basic crud, here's an example of a before_action like you suggested
before_action :load_post_and_comment, only: %i(edit update destroy)
def load_post_and_comment
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
end
And here a couple of other notes
def create
# ...
#comment.save!
if #comment.save
# ...
else
# ..
end
end
In this codition the you should remove the extra #comment.save! you only need to save once.
def update
# ...
if #comment.update(params[:comment].permit(:comment))
# ...
else
# ...
end
end
You already have the comment_params method, use it, because if you at any point add a new attribute to the comment, you'll update that method but you'll probably forget this part and you'll get werid errors till you notice that you need to permit here too.
If you want to really go all out with the skinny controller model, there is this gem: https://github.com/NullVoxPopuli/skinny_controllers
Where, you'd configure your CommentsController like so:
class CommentsController < ApplicationController
include SkinnyControllers::Diet
def create
if model.errors.present?
render 'new'
else
redirect_to post_path(model)
end
end
def update
redirect_to post_path(model)
end
# ... etc
private
def comment_params
params.require(:comment).permit(:comment)
end
end

Rails: param is missing or the value is empty: article

I am new with Rails and I began to make a web app following the rubyonrails.org tutorial.
My app is a blog with articles.. I implemented create and edit functions which worked pretty well but suddenly an error while trying to access http://localhost:3000/articles/2/edit in order to edit an article.
The error is ActionController::ParameterMissing in ArticlesController#edit param is missing or the value is empty: articles
Here is my ruby code:
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
def new
#article = Article.new
end
def edit
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def show
#article = Article.find(params[:id])
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
private
def article_params
params.require(:article).permit(:title, :text)
end
end
The line targeted by the error alert is params.require(:articles).permit(:title, :text)
I really don't know where the error can be because everything was ok 2 minutes ago...
Thank you for your help
You are trying to update the article in the edit method. So when you navigate to "articles/2/edit/" it tries to update the article 2. But you did not pass any params.
I think what you probably want is:
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
I know is late, but i hope this solution help someone. Add to ArticleController these two methods:
def edit
#article = Article.find(params[:id])
end
and
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end

Resources