Rails 4 strong parameters without required parameters
You can use fetch
instead of require
.
def device_params
params.fetch(:device, {}).permit(:notification_token)
end
Above will return empty hash when device is not present in params
Documentation here.
Rails: .require() without actually requiring it?
You can use fetch
instead of require
:
params.fetch(:subscriber).permit(:utm_source, :utm_medium, :utm_campaign, :utm_term, :utm_content)
Check the rails guides for more information on strong parameters.
Rails strong parameters - Request allowed without required key
This behaviour is because of the ParamsWrapper functionality which is enabled by default in Rails 6. wrap_parameters
wraps the parameters that are received, into a nested hash. Hence, this allows clients to send requests without nesting data in the root elements.
For example, in a model named Tag
, it basically converts
{
name: "Some name",
age: "Some age"
}
to
{
tag:
{
name: "Some name",
age: "Some age"
}
}
However, as you see in your test, if you change the required key to not_tag
, the wrapping breaks the API call, as expected.
This configuration can be changed using the config/initializers/wrap_parameters.rb
file. In that file, you could set wrap_parameters format: [:json]
to wrap_parameters format: []
to disallow such wrapping of parameters.
Allowing only certain values though a strong parameter in Rails 4
delete_if
cleans it up. Still a bit hacky, but slightly less so : )
params.require(:company_user).permit(:otp_setup).delete_if do |key, val|
key == 'otp_setup' && val == true
end
This leaves the original params
object intact.
There isn't a built in way to do this. It looks like there used to be but no more https://github.com/rails/strong_parameters/issues/167
delete_if
is defined on Hash
in the core library, so it is probably the best way to do it in Ruby and by extension in Rails in the absence of a built in method.
Update
I thought it was an interesting idea, so I wrote a small gem called allowable for this type of use case. It will add a few methods to Hash
and ActionController::Parameters
: #allow
, #allow!
, #forbid
and #forbid!
You would use it like this
params.require(:company_user).permit(:otp_setup).forbid(otp_setup: [true])
# or
params.require(:company_user).permit(:otp_setup).allow(otp_setup: [false])
You can specify a single value or an array of values, and it doesn't mutate the original params
object
rails 4 using strong parameters with no controller
You permit the parameters into whichever controller you are sending them through. It sounds like you are sending them through your track controller, if so you would add them there.
see this question about how to permit nested params Rails 4 - Strong Parameters - Nested Objects
Shortcut for including strong parameters in Rails 4 : without listing all fields
Strong Parameters were introduced in Rails 4:
It provides an interface for protecting attributes from end-user
assignment. This makes Action Controller parameters forbidden to be
used in Active Model mass assignment until they have been whitelisted.
Basically, it means only certain param values will be sent through your controller to the model (thus allowing you more control over which data is handled by Rails)
DRY
If you're wanting to use strong params for multiple controllers, or just want to DRY up the process, we use this:
#app/controllers/application_controller.rb
private
#Strong Params
def permitted_params
@resource = self.resource_class
@model = "#{@resource}".downcase.to_sym
attributes = @resource.attribute_names + %w(custom items here)
params.permit(@model => attributes)
end
Strong Parameters and Find in Rails 4
So to clear a few things up.
Strong Parameters is responsible for the allowed parameters which are passed to your database. It should prevent the users to modify attributes in the database which they aren't allowed to modify.
For example:
You have the following table with columns:
User:
- firstname
- lastname
- email
- password_digest
- role (user, admin)
You probably want to prevent normal users to change their role
. But if you pass a parameters hash as it is to the database, he could also add a role
key with value to the hash. Your application would accept it. Strong parameters checks the hash and prevent the change.
In your example above, Strong Parameters brings no advantages. You assign the values directly to the appropriate table columns. It isn't possible to modify any other attributes in the database for the user. If you don't have any other methods in your controller, you could remove the entire #order_params
. Strong Parameters just raises an exception if you would try to pass a hash directly through.
However I would recommend you to search for the payment in the database before you assign it. If you assign payment_id
directly you have no guarantee that payment exists. So first check for the payment and if you found it assign it to the order.
Here is how I would have done it:
class PaymentConfirmationController < ApplicationController
before_action :authenticate_user!
before_action :authorize_user! # To DRY up your code
def lookup
@orders = Order.where(:status => 'PENDING')
end
def confirm
@order = Order.find(params[:order_id])
@payment = Payment.find(params[:operation_id])
# You should catch the exceptions if an order or payment wasn't found
@order.payment = @payment
@order.payment_confirmation_date = Time.now()
@order.save
end
private
def authorize_user!
authorize! :confirm, :confirmpayment
end
end
I haven't tested the code but it should work.
Here are the Docs of Strong Parameters. They describe everything in more detail.
I hope this helps!
Happy coding :)
Rails4 Strong parameters without database column
Please, permit only the params you expect your user send with data. If start_time is not user data for update your db, use this way:
params.require(:timeslot).permit(:employee_id, :dienstplan_id, :start_date)
Strong parameters prevents save data that user sends and you don't want he/she update.
If you use :start_time, it must be defined at your model.
Ops, I've seen your update:
@e.start_date = @e.start_date.to_s + " " + @e.start_time.to_s
If you send :start_time to an Timeslot instance them start_time must be a method of Timeslot model. Defined by rails if it is a db field, defined with attr_accesor or att_reader or defined by a def key on your source model.
If not @e.start_time
trigger undefined method 'start_time'
.
edited again:
Now, start_time is a model variable. Make sure it is send to the form in the same way that you do with the fields. By default we use an f <%= f.text_field :the_field %>
. Just don't forget the f.
Now you must permit this field again, if you follow my first advice.
Related Topics
How to Detect Browser Type and Its Version
Differencebetween 'Size' and 'Length' Methods
Comma Separated Array with a Text_Field in Rails
Is It a Bad Idea to Reload Routes Dynamically in Rails
Rails 12 Hour Am/Pm Range for a Day
Breaking Ruby Module Across Several Files
Convert HTML to Plain Text (With Inclusion of <Br>S)
Elegantly Selecting Attributes from Has_Many :Through Join Models in Rails
Ruby on Rails - Using Concerns in Controllers
Conditional Haml - If Else Nesting
How to Escape a Single Quote in Ruby
Rails 3: User Created Custom Forms
How to Get a Substring from Position N to the Last Char in Ruby
What Is the Most Elegant Way in Ruby to Remove a Parameter from a Url
Ruby Array to Hash: Each Element the Key and Derive Value from It