Whitelist Parameters in Controller without a Model - ruby-on-rails

I would like to whitelist a parameter from my params. I have a controller ElectiveRecommendationsController that isn't tied to any Model.
How do I whitelist my :electives? I tried the following, but it didn't work.
def permitted_params
params.permit(:electives)
end
The error I am getting:

You need to specify that electives is a Hash. You'll want this
def permitted_params
params.permit(electives: {})
end

Related

Rails: Using Strong Params as keyword parameters

Let's say I have a User Model with a class method create_with_info. Currently if I want to password the params into the method using keyword parameters, It will be something like this.
# user_controller.rb
def create_with_info
User.create_with_info(**user_info_params)
end
private
def user_info_params
params.require([:name, :age, :email])
params.permit(:name, :age, :email).to_h.symbolize_keys
end
# user.rb
def self.create_with_info(name:, age:, email:)
# do something
end
I'm not sure is it the correct way to use keyword parameters in controller or is there a better way to handle? using to_h.symbolize_keys is annoying for me.

Overwrite permited_params if rails controller has been inherited

Here an example:
class Base<ApplicationController
private
def permited_params
params.require(:object_name).permit(:name, :description)
end
end
class Post<Base
private
def permited_params
params.require(:post).permit(:name, :description, :owner)
end
end
I'm getting an error ActiveModel::ForbiddenAttributesError when call action create. How I can overwrite this permited_params
Params, in general, have a good reason to exist and make sure that not everything can be saved into your database. However, if you want to permit all params you can call
params.require(:post).permit!
In case you just want to change the params you can change the attribute names.
params.require(:post).permit(:name, :description, :some_you_want, some_more ) etc.
In general, you should add all params you want to save into the list of permitted params. So you make sure that all the attributes you want to save will be stored and no more. You can have permitted_params in every controller. You do not need to call it permitted params. For instance you can call it like this in your posts_controller:
def create
#post = Post.new(post_params)
#.... your code
end
private
def post_params
params.require(:post).permit(:name, :description, :owner)
end
This also works for inherited controllers.
Instead of params.require(:post).permit(...
you can use whatever params you want, like params.require(:reply).permit(...
The required param will throw an error if it is not available. So you need to make sure it exists for example by
#post = Post.new
Other params are optional and will not cause an error by default.

Why is my params hash nil?

In my rails controller, in a pry session, my params hash is nil. request.params has the expected hash.
If I comment out the params = … line, params returns to normal.
class UsersController < Clearance::UsersController
skip_before_filter :verify_authenticity_token
def update
binding.pry
params = params.require(:user).allow(:foo)
end
end
What could be causing this?
To begin with, params is a method. http://api.rubyonrails.org/classes/ActionController/StrongParameters.html#method-i-params
In your code, when you write
params = params.require(:user).allow(:foo)
you initialize a variable called params.
When you hit your pry, you have already initialized (gets initialized upon loading of code) but not yet set the value of your variable, params. Therefore, when you call it within your pry, it is set to nil. The method params is overwritten by your variable within the scope of your update method.
The params hash is what you get when the user request the page. For example:
https://www.example.com/index.html?username=john&email=john#example.com
The params hash would be
{username: 'john', email: 'john#example.com'}
And you can assess then like params[:username].
Looks like you are trying to use strong parameters to set what the user can or cannot update. In that case, what you should do is
def update
user = User.find(params[:id])
user.update_attributes(params.require(:user).permit(:foo))
end
This will only allow the user to update the foo attribute and nothing else.
Because this is so common, it is standard to write a private method called user_params and just call that method when you call save.
def update
user = User.find(params[:id])
user.update_attributes(user_params)
end
private
def user_params
params.require(:user).permit(:foo)
end

Disable strong parameters for a specific action

I have a serious problem with strong parameters. Its working pretty well in my about 200 actions but in one it doesn't because I'm working very dynamic with the parameters there and I also cant change it because of the applications design.
So I want to disable strong parameters validation in just this specific action. Is there a way to do this?
Strong parameters overrides the params method in ActionController::Base. You can simply override it and set it back to what you want yourself.
So this:
class MyController < ApplicationController
def params
request.parameters
end
end
Will effectively disable strong parameters for all actions in your controller. You only wanted to disable it for a particular action though so you could do that with:
class MyController < ApplicationController
before_action :use_unsafe_params, only: [:particular_action]
def params
#_dangerous_params || super
end
def particular_action
# My params is unsafe
end
def normal_action
# my params is safe
end
private
def use_unsafe_params
#_dangerous_params = request.parameters
end
end
Not too sure if this is best practice but for Rails 5 I just use request.params instead of params anytime I want to skip strong params.
So instead of something like:
post = Post.new(params[:post])
I use:
post = Post.new(request.params[:post])
You can use .permit! to whitelist any keys in a hash.
params.require(:something).permit!
However this should be treated as an extreme code smell and a security risk.
Nested hashes can be whitelisted with this trick:
params.require(:product).permit(:name, data: params[:product][:data].try(:keys))

How to access params[] when using a callback on model

I'm using the callback before_update to call a function on model which set the checkbox value on my variable.
The problem is the checkbox value which is on params[:mail_checker_issue] isn't accessible on the model layer.
The question is: How to access this params using the callback before_update ? Below my code:
module IssueSetChecketIssuePatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_mail_checker
end
end
end
module InstanceMethods
require_dependency 'issue'
def before_mail_checker
self.set_mail_checker_issue(params[:mail_checker_issue])
end
def set_mail_checker_issue(mail)
#mail_checker = mail
end
def get_mail_checker_issue
#mail_checker
end
end
Rails.configuration.to_prepare do
Issue.send(:include, IssueSetChecketIssuePatch)
end
params are a controller concern and are wholly separate from models. Consider what should happen if you tried to save that model from a console, for example.
You need to pass the param to the model after you instantiate it from your controller, then check the value set on the model in your before_save callback.
It's also worth noting that your code is somewhat un-Rubyish (and really, looks a lot like Java!) - you could get the same effect by just defining an attr on the model.
Rails.configuration.to_prepare do
require_dependency 'issue'
class Issue
attr_accessor :mail_checker_issue
end
end
Then, once you have an issue:
# Controller code
#issue = Issue.find(params[:id])
#issue.mail_checker_issue = params[:mail_checker_issue]
You don't, models don't know about controllers or params hash.
You should include this logic at your controller instead of forcing it in a callback.

Resources