Send integer data by swagger/postman in rails api - ruby-on-rails

I am submitting a form by swagger ui(as well as from postman)
param :form, 'user[role]', :string, :required . In the user model role is a enum containing the values like enum role: [1,2,3] . So In the paramters , I am sending 1 in the form field , but I am receiving like {"user" => {"role" => "1"}} which is correct. But the user form is giving error role '1' is not a valid type
Ruby 2.4
Rails 5.1.3

Why use enum when you are passing an array?. I use enums with a hash like this:
enum role: {
customer: 1,
seller: 2,
"6.5": 2,
"5.5": 0
}
And then you pass at the params
{"user" => {"role" => "admin"}}
Which save 0 at the instance for this case

Related

Rails API: Cannot whitelist JSON field attribute

I'm building a rails API with a model containing an attribute data of JSON type. (PSQL)
But when I try to post something like this
{ model: { name: 'Hello', data: { a: 1, b: 2 } } }
Rails thinks a and b are the attributes of a nested data association... It considers then they are unpermitted params.
The thing is, { a: 1, b: 2 } is the value of my field data.
How to provide JSON value to an attribute ?
-
Edit:
The error displayed is:
Unpermitted parameters: name, provider, confidence, location_type, formatted_address, place_id, types, locality, ...
The value of the data attribute is { name: 'Name', provider: 'Provider', ... }
Like I said Rails thinks they are the attributes of a nested data association.
-
Log:
Pastebin
if the keys are unknown in advance this could be a workaround:
def model_params
data_keys = params[:model].try(:fetch, :data, {}).keys
params.require(:model).permit(data: data_keys)
end
Credit goes to aliibrahim, read the discussion https://github.com/rails/rails/issues/9454 (P.S seems like strong parameters will support this use case in Rails 5.1)
When you post something, you have to make sure that your json have the same parameters that your controller.
Example rails api:
def example
#model = Model.new(params)
#model.save
render(json: model.to_json, status: :ok)
end
def params
params.permit(:name, :provider, {:data => [:a, :b]})
end
Example front-end json for post:
var body = {
name: 'myName',
provider: 'provider',
data: {
a: 'something',
b: 'otherthing',
}
};
For some reason rails doesnt recognize a nested json, so you need to write into params.permit that data will be a json with that syntax, if where a array, the [] should be empty.

Rails - permit a param of unknown type (string, hash, array, or fixnum)

My model has a custom_fields column that serializes an array of hashes. Each of these hashes has a value attribute, which can be a hash, array, string, or fixnum. What could I do to permit this value attribute regardless of its type?
My current permitted params line looks something like:
params.require(:model_name).permit([
:field_one,
:field_two,
custom_fields: [:value]
])
Is there any way I can modify this to accept when value is an unknown type?
What you want can probably be done, but will take some work. Your best bet is this post: http://blog.trackets.com/2013/08/17/strong-parameters-by-example.html
This is not my work, but I have used the technique they outline in an app I wrote. The part you are looking for is at the end:
params = ActionController::Parameters.new(user: { username: "john", data: { foo: "bar" } })
# let's assume we can't do this because the data hash can contain any kind of data
params.require(:user).permit(:username, data: [ :foo ])
# we need to use the power of ruby to do this "by hand"
params.require(:user).permit(:username).tap do |whitelisted|
whitelisted[:data] = params[:user][:data]
end
# Unpermitted parameters: data
# => { "username" => "john", "data" => {"foo"=>"bar"} }
That blog post helped me understand params and I still refer to it when I need to brush up on the details.

Using enum in a model, when saving it doesn't like the integer value

Using rails 4.1.1
My model has an enum like:
class Article < ActiveRecord::Base
enum article_status: { published: 1, draft :2 }
Now in my new.html.erb I have:
<%= form.select :article_status, options_for_select(Article.article_statuses) %>
When going to save the model I get this error:
'1' is not a valid article_status
I was thinking it would be able to handle this during an update.
What am I doing wrong?
The update_attributes or new call in your controllers will expect the stringified version of the enum symbol, not the integer. So you need something like:
options_for_select(Article.article_statuses.
collect{|item, val| [item.humanize, item]}, selected: #article.status)
There is a full example in this article.

How to sanitize grape params

I want to mass update attributes of an entity.
How can I sanitize properly the params which is coming from grape?
This is my console log about the parameters:
params.except(:route_info, :token, :id)
=> {"display_number"=>"7"}
[18] pry(#<Grape::Endpoint>)> params.permit(:display_number)
ArgumentError: wrong number of arguments (2 for 0..1)
from /Users/boti/.rvm/gems/ruby-2.0.0-p353#thelocker/gems/hashie-2.0.5/lib/hashie/mash.rb:207:in `default'
[19] pry(#<Grape::Endpoint>)> params.sanitize
=> nil
In grape you need to declare your params before the actual method.
Within the method the params object is a Hashie::Mash instance, and does not have APIs like permit and sanitize...
Here is the relevant documentation for declaring and validating parameters in grape:
You can define validations and coercion options for your parameters
using a params block.
params do
requires :id, type: Integer
optional :text, type: String, regexp: /^[a-z]+$/
group :media do
requires :url
end
optional :audio do
requires :format, type: Symbol, values: [:mp3, :wav, :aac, :ogg], default: :mp3
end
mutually_exclusive :media, :audio
end
put ':id' do
# params[:id] is an Integer
end
When a type is specified an implicit validation is done after the
coercion to ensure the output type is the one declared.
If you still want to use strong parameters, you'll need to use the strong_parameters gem, and create a new instance of ActionController::Paramter yourself:
raw_parameters = { :email => "john#example.com", :name => "John", :admin => true }
parameters = ActionController::Parameters.new(raw_parameters)
user = User.create(parameters.permit(:name, :email))

Working with Boolean fields on Mongoid

I create a Model that has a Boolean field, but when catch the value it gave me 1 or 0. I discover that it's because BSON type for Boolean is "\x00" and "\x01".
So my question is, how can I get the "boolean" value of the field? Do I need to do a method on a model or a controller that returns me true if value is 1 or false if 0? Or will Mongoid do this for me?
Mongoid Version: 4.0.0 38de2e9
EDIT
Mongo Shell
db.feedbacks.find().limit(1).pretty()
{
"_id" : ObjectId("52290a2f56de969f8d000001"),
"like" : "1",
...
}
Explain:
I create a app with scaffold:
rails g scaffold Feedback like:Boolean
When I insert a new record, in Mongo the Document stay as I sad.
When I do Feedback.first, the field like in Model has the "0" or "1" value.
class Feedback
include Mongoid::Document
include Mongoid::Timestamps
field :comment, type: String
field :like, type: Boolean
def isLike?
like=="1"
end
end
This is the repo:
https://github.com/afucher/4kFeedback/blob/master/app/models/feedback.rb
Mongoid handles that in a transparent manner if you use the Boolean type. Checkout the documentation.
EDIT :
From the rails console (in an app with an Indicator model defining a field global of type Boolean) :
Indicator.first.global?
# => true
Indicator.first.global?.class
# => TrueClass
The equivalent from the mongo shell :
> db.indicators.find().limit(1).pretty()
{
"_id" : ObjectId("52319eeb56c02cc74200009c"),
...
"global" : true,
...
}
EDIT
The spec for the Boolean extension clearly shows that for any of true, "true", "t", "yes", "y", 1, 1.0 on the MongoDB side you'll get a TrueClass instance. Same for false.
I can resolve my problem, reading the check_box documentation:
http://apidock.com/rails/ActionView/Helpers/FormHelper/check_box
The default value of Check Box is "0" or "1". To change this value, is just pass the values that you want to the tag:
check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
So, I change to this:
<%= f.check_box :like,{}, "true", "false" %>
Thanks Jef for help me!!

Resources