Strong parameters for different controller methods - ruby-on-rails

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

Related

How to routing to concern throug controller

To have a cleaner code I want to split my controller in some concerns.
In my routes.rb how to redirect to concern without redefine the methods of concern index show destroy create ...
class SomeController
include SomeConcern
def index
end
end
module SomeConcern
def index
end
end
Sorry for my bad english.
Lets say we have a CarsController and AirplanesController that have the typical create and new actions.
class AirplanesController < ApplicationController
def new
#airplane = Airplane.new
end
def create
#airplane = Airplane.new(create_params)
if #airplane.save
redirect_to #airplane
else
render :new
end
end
# ...
end
class CarsController < ApplicationController
def new
#car = Car.new
end
def create
#car = Car.new(create_params)
if #car.save
redirect_to #car
else
render :new
end
end
# ...
end
To dry this up we can extract the shared code to a module:
module Createable
extend ActiveSupport::Concern
included do
attr_accessor :resource
alias_attribute :self.controller_name.to_sym, :resource
end
def new
#resource = resource_class.new
yield #resource if block_given?
end
def create
#resource = resource_class.new(create_params)
if #resource.save
yield #resource if block_given?
redirect_to #resource
else
render :new
end
end
private
def create_params
raise "not implemented controller!"
end
def resource_class
#resource_class ||= self.controller_name.classify.constantize
end
end
We can then apply it to the controller classes by:
class CarsController < ApplicationController
include Createable
def create_params
params.require(:car)
.permit(:model) # ...
end
end
class AirplanesController < ApplicationController
include Createable
def create_params
params.require(:airplane)
.permit(:model) # ...
end
end
But a very important point here is that you are not routing to the module. The module is providing methods to the controller class.
You have to always map to your controller. Concerns are modules where you can put shared logic (it makes sense only in case you need 2 absolutely similar methods in 2 different controllers).
I think, that such code should work:
class SomeController
include SomeConcern
end
module SomeConcern
def index
end
end
Isn't it?
But concerns mostly used to move out some private helper methods from controller, rather actions as we do in this code piece

uninitialized constant UController::User_param

I am making a basic account setup and to try to learn how the database stuff works. I have been running into this error constantly, and I have no idea how to make it disappear. I have my stuff named as U, so the URL will be easier to type a username like Reddit has it example.com/u/username
The Error is uninitialized constant UController::User_param
It highlights this code: #user = U.new(User_param)
Controller:
class UController < ApplicationController
def index
#users = U.all
end
def show
end
def create
#user = U.new(User_param)
if #user.save
redirect_to :action => 'list'
else
#user = U.all
render :action => 'new'
end
end
def User_param
params.require(:Us).permit(:id, :email, :password, :created_at, :updated_at)
end
def new
#user = U.new
end
def edit
end
end
Routes:
resources :u
U Model:
class U < ActiveRecord::Base
end
In Rails you don't capitalize methods, only constants and classes. change User_param to user_params along with the method and that should work. I made params plural since it is clearer and easier to understand
Also, change the user_param method to this:
def user_params
params.require(:u).permit(:id, :email, :password, :created_at, :updated_at)
end
The .require(:u) doesn't need to be plural as you had it.

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.

Pass all class methods to another function in Ruby on Rails

I have made the following validation method:
def if_admin(&block)
if #current_user.administrator?
yield
else
redirect_to '/go_away'
end
end
and i find my classes are increasingly looking like:
class Foo < ApplicationsController
def index
if_admin do
.....
end
end
def show
if_admin do
.....
end
end
def new
if_admin do
.....
end
end
def edit
if_admin do
.....
end
end
.......
end
I want to know if there is anything similar to before_action which would pass the method into the if_admin method, thus DRYing up the code?
Just like you wrote, there is before_action. You can use it like this:
class Foo < ApplicationsController
before_action :if_admin
# ...
private
def if_admin
redirect_to '/go/away' unless #current_user.administrator?
end
end

ActiveModel::ForbiddenAttributesError Ruby

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.

Resources