ActiveModel::ForbiddenAttributesError Ruby - ruby-on-rails

I'm stuck on this error and i can't figure out whats wrong.
class TicketsController < ApplicationController
def new
end
def create
#tickets = Newticket.new(params[:tickets])
#tickets.save
redirect_to #tickets
end
private
def tickets_params
params.require(tickets).permit(:title, :text)
end
end

You have to pass ticket_params to the new method
def create
# your code
#tickets = Newticket.new(params[:tickets])
# you should use
#tickets = Ticket.new(ticket_params) #if your model is named Ticket
#tickets = Newticket.new(ticket_params) #if your model is named Newticket
#tickets.save
redirect_to #tickets
end
private
def tickets_params
params.require(:tickets).permit(:title, :text) # if your model is named Ticket
params.require(:newtickets).permit(:title, :text) # if your model is named Newticket
end
end
you have create method ticket_params that is permitting :tickets values from params hash, and you have said with permit which keys are permitted in params[:tickets] hash object. You have put :title, :text. You problem was that you are using params[:ticket] that has none permitted params.

#tickets = Newticket.new(params[:tickets])
Newticket.new that one was causing the troubles. I defined that method wrong earlier when generating the controllers i called it Newticket while i should have called it tickets.
Thanks for in the input.

Related

Strong parameters for different controller methods

I'm creating a controller in Rails, and I'm looking for ways to have different strong parameters for different controller methods
In update and new actions, I would want to require post
params.require(:post).permit(:body, :is_public, :title, :id)
But in post/index, i don't need to require these parameters.
How do you make different requirements strong parameters for different controller methods?
Your "strong parameters methods" are just Ruby methods. You can have however many you want.
class PostsController < ApplicationController
def create
#post = Post.new(create_params)
end
def update
#post = Post.find(params[:id])
if #post.update(update_params)
# ...
else
# ...
end
end
private
def base_params
params.require(:post)
end
# Don't take IDs from the user for assignment!
def update_params
base_params.permit(:body, :title)
end
def create_params
base_params.permit(:body, :title, :foo, :bar)
end
end
You can also name them whatever you want. Calling it [resource_name]_params is just a scaffolding convention.
Just do something like
class FooController < ApplicationController
def create
#post = Post.new(create_params)
if #post.save
blah
else
blah
end
end
def index
... something else
end
private
def create_params
params.require(:post).permit(:body, :is_public, :title, :id)
end
end

ArgumentError: When assigning attributes, you must pass a hash as an argument

I'm upgrading from Rails 4 to 4.2. I have a users controller that looks something like this:
user_controller.rb
class UsersController < ApplicationController
def new
end
def edit
end
protected
def create_with_token
#user.attributes = params[:user]
#user.validate_password = true
if #user.save
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(
:email, :first_name, :last_name, :password, :more_attributes
)
end
end
I'm not sure yet if this has something to do with strong_params. But as far as I know params[:user] returns a hash. So why do I get ArgumentError: When assigning attributes, you must pass a hash as an argument. on #user.attributes = params[:user]?
I checked the rails code and found:
def assign_attributes(new_attributes)
if !new_attributes.respond_to?(:stringify_keys)
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
end
return if new_attributes.empty?
attributes = new_attributes.stringify_keys
_assign_attributes(sanitize_for_mass_assignment(attributes))
end
From here, assuming #assign_attributes replaced #attributes (It's actually an alias for it. I can infer that params[:user] is not responding to #stringify_keys. But why? How? What's the work around?
Your params[:user] is an instance of ActionController::Parameters, I guess... so you just need to switch:
#user.attributes = params[:user]
To
#user.attributes = user_params

I am getting an error says that undefined local variable or method 'blog_params' (Rails)

So I got a very basic blog app running with three links to a blog post. However, when I click on a post of my selection and edit the post and click on "update blog", I will get an error saying NameError in BlogsController#update and undefined local variable or method 'blog_params' for blogscontroller. I cannot figure out what the issue is so I would like some help to guide me through
This is what my blogs controller file looks like
class BlogsController < ApplicationController
def index
#blogs = Blog.all
end
def show
#blog = Blog.find(params[:id])
end
def new
#blog = Blog.new
end
def create
#blog = Blog.new
#blog.title = params[:blog][:title]
#blog.body = params[:blog][:body]
#blog.save
redirect_to blog_path(#blog)
end
def destroy
#blog = Blog.find(params[:id])
#blog.destroy
redirect_to blog_path(#blog)
end
def edit
#blog = Blog.find(params[:id])
end
def update
#blog = Blog.find(params[:id])
#blog.update(blog_params)
redirect_to blog_path(#blog)
end
end
def update
#blog = Blog.find(params[:id])
**#blog.update(blog_params)**
redirect_to blog_path(#blog)
end
here you are calling blog_params but you haven't defined it anywhere in your code.
See example here:
See strong params
You need to do this:
#app/controllers/blogs_controller.rb
class BlogsController < ApplicationController
def update
#blog = Blog.find params[:id]
#blog = #blog.update blog_params
end
private
def blog_params
params.require(:blog).permit(:title, :body) #-> in "permit" put the attributes of your "blog" model
end
end
The error is a standard programming issue - undeclared function.
Because you're starting - and to give you more context - the reason this is a problem is because you're calling blog_params when you run the .update method:
#blog.update blog_params
This, as mentioned by Pardeep Dhingra, is the strong params pattern introduced into Rails 4. Strong params prevents mass assignment by explicitly permitting particular attributes of your model.
Whilst your code is okay, you lack the strong params method (in your case blog_params), which Rails needs to complete the request. Adding the method will fix the issue.

How to auto-assign value to the permitted params in Rails controller create method

I have Ruby On Rails application. I have created method in my CommentsController and I want to always auto-assign value to one of the permitted fields (in my case its :commenter)"
class CommentsController < ApplicationController
def create
#meme = Meme.find(params[:meme_id])
#comment = #meme.comments.create(comment_params)
redirect_to meme_path(#meme)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
How can I achieve this?
At first, you should authenticate a user. Since the current user is authenticated there is no need to pass him in parameters. You can do something like this:
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
#meme = Meme.find(params[:meme_id])
#comment = #meme.comments.create(comment_params)
redirect_to meme_path(#meme)
end
private
def comment_params
params.require(:comment).permit(:body).merge(commenter: current_user)
end
end
Merging it along with the comment_params, you can add more params that you want as key and values in the second hash
def comment_params
params.require(:comment).permit(:body).merge!({commenter: 'default_value'})
end
You can use tap:
def comment_params
params.require(:comment).permit(:commenter, :body).tap do |comment|
comment[:commenter] = "some value here"
comment[:any_other_key] = "some other value"
end
end
Could you add t.string :commenter, default: "default_commenter" in your migrations. That way if you are working on the console then you won't get blank values. It will also clean up the controller code.

Extract User's ID and insert into Posts table in ruby on rails

Experimenting with ruby on rails.. I put a new Post form on a users show page.(i.e. 0.0.0.0:3000/users/2) I'm trying to extract the user's id and insert it into a 'user_id' field in the Post table when you create a new post. So when the form is submitted from the user's page, I can link it to the user that wrote it.
models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
before_save :create_user_id
def create_user_id
self.user_id = current_user
end
end
models/user.rb
class User < ActiveRecord::Base
has_many :posts
end
helpers/application_helper.rb
module ApplicationHelper
def current_user
#current_user ||= User.find(params[:id])
end
end
controllers/post_controller.rb
class PostsController < ApplicationController
def new
#post = Post.new
end
def show
#post = Post.find(params[:id])
#page_title = #post.title.capitalize
#author = User.find(#post.user_id)
#author_url = "/users/" + #post.user_id.to_s
end
def create
#post = Post.create(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
# private
private
def post_params
params.require(:post).permit(:title, :body, :user_id)
end
end
The error I get:
Couldn't find User without an ID
Extracted source (around line #15):
#post = Post.find(params[:id])
#page_title = #post.title.capitalize
>>#author = User.find(#post.user_id)
#author_url = "/users/" + #post.user_id.to_s
end
If I test and change my application_helper.rb to this it works, and inserts 2 into the Post's user_id field. The current set up just returns nil
module ApplicationHelper
def current_user
#current_user = 2
end
end
First you want to get the current user, for now you can test using something like this:
#current_user ||= User.find(2)
Note that there will not be an :id param available on a create call, :id refers to a specific member of your resource so in this case if get http://localhost:3000/posts/1 posts would be the resource and 1 would be the param :id so this would not return the current_user you expected.
Then association should do all of the work for you and there is no need for the create_user_id method. All you would have to do is tweak your create method to
#post = current_user.posts.create(post_params)

Resources