How can I hide a parameter's defaultValue in Swagger UI? - ruby

I place the Swagger formatting directly in my Ruby API source and use Source2Swagger to create the documentation:
# ~ a = my_api.apis.add
# ~ a.set :path => "/my_api/{application_key}"
# ~ op = a.operations.add
# ~ op.set :httpMethod => "GET", :nickname => "getmyapi"
# ~ op.summary = "Get stuff from My API"
# ~ op.parameters.add :name => "application_key", :description => "User authentication token", :dataType => "string", :allowMultiple => false, :required => false, :paramType => "path", :defaultValue => "1234567890"
# ~ op.responseMessages.add :message => "No stuff found", :code => 204
# ~ op.responseMessages.add :message => "API down", :code => 500
#
get '/my_api/?:application_key?', :provides => :json do
Do stuff...
end
The "application_key" is not required, but users need to know the option when the API goes live. As you can see above, I was asked to supply a default value for internal use (please don't ask why :-)) but I would still like to hide the default value of the parameter when displaying the documentation. Is this possible?

You won't be able to do it without hacking the UI. You'd need to find that specific operation and that specific parameter and override its behavior.
If you think about it, what you're asking doesn't make a lot of sense. You're saying that you're being asked to document something one way, but when displaying the documentation, you want to display it differently.
There are of course other possible solutions like proxying your documentation and changing it at the proxy, but that may be more work than it is worth.

Related

Freeze arrays and hashes by default?

Just wondering if something like:
# frozen_string_literal: true
exists but for Array and Hash?
The goal is not having to .freeze every single of those within the same globals file.
I didn't find any library that monkey patches default ruby classes like Array or Hash. But I found an interesting gem immutable-ruby that may fit your needs
Simple example
require "immutable/hash"
person = Immutable::Hash[name: "Simon", gender: :male]
# => Immutable::Hash[:name => "Simon", :gender => :male]
and you cannot just modify values of it, cause it is immutable. You can perform some actions on that hash, but new copy will be returned to you
friend = person.put(:name, "James") # => Immutable::Hash[:name => "James", :gender => :male]
person # => Immutable::Hash[:name => "Simon", :gender => :male]
friend[:name] # => "James"
person[:name] # => "Simon"
Found a way to handle it without using another gem using only vscode and rubocop :
Install the rubocop extension on vscode
Open your .vscode/settings.json
Append those rules :
{
"editor.formatOnSave": true,
"editor.formatOnSaveTimeout": 5000,
"ruby.format": "rubocop"
}
save
enjoy
Thanks to Tom Lord for the hint.

Rhomobile Migration from Rho3.1 to Rho 4.0 Alert Msg. Error

I am trying to migrate my rho application from 3.1 to 4.0. In 3.1 i have defined alert using Alert.show_popup :title => "Please Wait", :message => "Fetching Data..." But as specified in documentation now i have changed it to the
dataPopProps = Hash.new
dataPopProps['message'] = "Fetching Data...";
dataPopProps['title'] = "Please Wait";
Rho::Notification.showPopup(dataPopProps)
But i am still getting the same error.
Error: Button list has been incorrectly defined. DIalog will not Launch
Any help will be great.
Try like this,
dataPopProps = Hash.new
dataPopProps['message'] = "Fetching Data...";
dataPopProps['title'] = "Please Wait";
dataPopProps['buttons'] = ["Ok"]
Rho::Notification.showPopup(dataPopProps)
For future reference, the official docs are often incorrect, so working with Rhodes can be frustrating. However, the example listed here seems to be a good solution. Note that the example for Notification is in Javascript.
Here is an elegant way to write this in Ruby:
dataPopProps = {
'message' => 'Fetching Data...',
'title' => 'Please Wait',
'buttons' => [{ :id => 'no', :title => 'no' }]
}
Semicolons are eggregiously unecessary in Ruby, and you can clean up your code by using literals instead of Hash.new.

In Ruby, how to upload multiple files in single request using RESTClient

I have to upload multiple files as form request. I am using the Rest Client to post my request. I am able to upload single file but I am not sure how to add multiple files in a single request.
I searched/googled for such option and I am not finding any solution that solves my problem.
Below is my code.
It has variable argument (*yamlfile) which takes one or more files. I have to upload all the files together.
The issue now is , I am getting syntax error when I add the loop to extract the file within the payload.
my assumption is now to form this outside the payload and include it inside the payload block but I am not sure how to do it.
Can someone help me with that.
( I have tried net/http/post/multipart library too and I don't find much documents around it)
def uploadRest(endpoint,archive_file_path,,yaml_file_path,*yamlfile)
$arg_len=yamlfile.length
request = RestClient::Request.new(
:method => :post,
:url => endpoint,
:payload => {
:multipart => true,
:job_upload_archive => File.new(archive_file_path,'rb'),
:job_upload_path => "/tmp",
# Trying to add multiple file, but I get syntax error
yamlfile.each_with_index { |yaml, index|
:job_upload_yaml_file+index => File.new("#{yaml_file_path}/#{pmml}")
}
})
response=request.execute
puts response.code
end
uploadRest(endpoint,archive_file_path,yaml_file_path,*yamlfile)
#files=Array.new
yamlfile.each{ |yaml_file|
#files.push(File.new("#{yaml_file_path}/#{yaml_file}"))
}
request = RestClient::Request.new(
:method => :post,
:url => endpoint,
:payload => { :multipart => true, :job_upload_archive => File.new(archive_file_path,'rb'),
:job_upload_path => "/tmp", :job_upload_yaml_file => #files })
response=request.execute
end
I had a similar problem and was able to get this to work by passing an array of arrays as a requests.
file1 = File.new("#{yaml_file_path}/#{yaml_file1}", 'rb')
file2 = File.new("#{yaml_file_path}/#{yaml_file}", 'rb')
request_body = [["files", file1], ["files", file2]]
RestClient.post url, request_body, request_headers
There were two issues with your question code:
1) Attempt to add a symbol to an integer
2) Attempt to insert contents of yamlfile direct into the hash (because that is what yamlfile.each_with_index returns, as opposed to how it calls your block. The return value from the block is not used)
Both of these code issues read as if you have gained experience in HAML or another templating language, and are using structures/ideas that would work in that?
There are lots of possble solutions in Ruby, but a simple approach to build up the hash in parts, as opposed to generate it in one go with clever hash-returning routines embedded. Try something like this:
payload_hash = {
:multipart => true,
:job_upload_archive => File.new(archive_file_path,'rb'),
:job_upload_path => "/tmp",
}
# This does not use the return value from each_with_index, instead it relies
# on the block to make changes to the hash by adding new key/value pairs
yamlfile.each_with_index { |yaml, index|
# This concatenates two strings, and then converts the combined
# string into the symbol that you want
file_key = ("job_upload_yaml_file"+index.to_s).to_sym
payload_hash[file_key] = File.new("#{yaml_file_path}/#{yaml}")
}
request = RestClient::Request.new(
:method => :post,
:url => endpoint,
:payload => payload_hash
)
For added code cleanliness, you could make the first two parts a separate method, and call it where it currently has payload_hash.
This should get you over current syntax hurdles. However, I have made no attempt to check whether this will allow you to upload multiple files via RESTClient.
Section1:
#params = {
"FacialImage" => UploadIO.new(File.new('C:\temp\ATDD\Test\test\sachin.jpg'), "image/jpeg"),
"Login" => UploadIO.new(File.new('C:\temp\ATDD\Test\test\login.txt'), "application/json")
}

SimpleForm required field (*) are not disappear even config at config.wrappers :default

I try to config simple_form to always set all fields NOT required by default.
But I still need this when I put :required => true in the view.
Then I go to config/initializers/simple_form.rb and set it like this.
config.wrappers :default, :class => :input, :required => false,
:hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
and set config.required_by_default = false
But asterisk still show up.
Thanks for any suggestion.
Rafaiel,
I had the same problem in Rails 4.0, not sure what you're using.
The best solution I've found is to go to config/locales/simple_form.en.yml and change the first lines like this (the mark: line is the one you change):
en:
simple_form:
"yes": 'Yes'
"no": 'No'
required:
text: 'required'
mark: '' #mark was previously '*', which puts an asterisk in the display!
It's also possible to change SimpleForm setup.
SimpleForm.setup do |config|
# Whether attributes are required by default (or not). Default is true.
config.required_by_default = false
end
Take this into account: (taken from simple form github page)
Required fields are marked with an * prepended to their labels.
By default all inputs are required. When the form object includes
ActiveModel::Validations (which, for example, happens with Active
Record models), fields are required only when there is presence
validation. Otherwise, Simple Form will mark fields as optional. For
performance reasons, this detection is skipped on validations that
make use of conditional options, such as :if and :unless.

Chef Recipes - Setting node attributes in ruby_block

I have a Chef recipe for a multi-node web service, each node of which needs to get the hostname and IP of the other nodes, to put it into its own local configuration.
The code is shown below. The problem is that when the node.set[][] assignments are made in the ruby_block as shown, the values are empty when the template that relies upon them is created. If I want to create that template, I have to move all of the ruby_block code outside, and have it "loose" in the recipe. Which makes it harder to do unit-testing with Chefspec and the like.
Can any Chef guru set me straight? Is it just impossible to do node.set[] like this inside of a ruby_block? And if so, why doesn't it say so in the docs?
$cm = { :name => "web", :hostname => "" , :ip_addr => "" }
$ca = { :name => "data", :hostname => "" , :ip_addr => "" }
$cg = { :name => "gateway", :hostname => "" , :ip_addr => "" }
$component_list = [$cm, $ca, $cg]
ruby_block "get host addresses" do
block do
for cmpnt in $component_list
# do REST calls to external service to get cmpnt.hostname, ip_addr
# .......
node.set[cmpnt.name]['name'] = cmpnt.name
node.set[cmpnt.name]['host'] = cmpnt.hostname
node.set[cmpnt.name]['ip'] = cmpnt.ip_addr
end
end
end
template "/etc/app/configuration/config.xml" do
source "config.xml.erb"
variables( :dataHost => node['data']['host'],
:webHost => node['web']['host'],
:gatewayHost => node['gateway']['host'] )
action :create
end
I also added
subscribes :create, "ruby_block[get host addresses]", :immediately
to the template definition to ensure that the ruby_block ran before the template was created. This didn't make a difference.
I realize this is an old post, however for future reference, I just ran across this gist which gives a nice example of node variable assignments in the Compile vs. Converge phases. To adapt the gist to your example, you'll need to add code like the following to your ruby_block:
template_r = run_context.resource_collection.find(:template => "/etc/app/configuration/config.xml")
template_r.content node['data']['host']
template_r.content node['web']['host']
template_r.content node['gateway']['host']
For Chef 11, also see Lazy Attribute Evaluation.
The problem seems to be that attribute values inside your template resource definition get evaluated before actually invoking any resources.
I.e. the file is first executed as simple Ruby, compiling the resources, and only the the resource actions gets invoked. By that time, it is too late already.
I ran into the same problem when trying to encapsulate certain attribute manipulations into a resource. It simply does not work. Should anyone know a solution to this problem, I would appreciate it very much.
EDIT:
b = ruby_block...
...
end
b.run_action(:create)
Could possibly do the trick. It invokes the resource immediately.
The simplest answer to this is to not use chef attributes and not use ruby_block to do the work of talking to the REST API. The code can also be moved to a custom resource for better reuse:
unified_mode true
provides :my_resource
action :run do
cm = { :name => "web", :hostname => "" , :ip_addr => "" }
ca = { :name => "data", :hostname => "" , :ip_addr => "" }
cg = { :name => "gateway", :hostname => "" , :ip_addr => "" }
component_list = [cm, ca, cg]
hash = {}
for cmpnt in component_list
# do REST calls to external service to get cmpnt.hostname, ip_addr
# .......
hash[cmpnt.name] = {}
hash[cmpnt.name]['name'] = cmpnt.name
hash[cmpnt.name]['host'] = cmpnt.hostname
hash[cmpnt.name]['ip'] = cmpnt.ip_addr
end
template "/etc/app/configuration/config.xml" do
source "config.xml.erb"
variables( :dataHost => hash['data']['host'],
:webHost => hash['web']['host'],
:gatewayHost => hash['gateway']['host'] )
action :create
end
end
By using unified_mode and moving into a custom resource, it also makes it easier to use a node attribute without requiring the use of lazy {} or ruby_blocks. It also still allows chef configuration (like setting up resolv.conf or other network requirements before doing the REST calls) prior to calling this code while not having to think about compile/converge two pass issues in recipe context.
There is also no reason to use a resource like ruby_block to do pure ruby processing which does not change the system under management. In this case the ruby_block is hitting a REST service purely to collect data. That does not need to be placed into a Chef resource. It isn't clear from the question if that was being done because the questioner though it was a "best practice" (in this case it is not), or if it was being done to move execution to compile time in order to allow other chef resources that aren't part of the question to fire first (in which case using a custom resource is a much better solution than using a ruby_block).
It's been a while since this question, but in case someone is still looking for it, lazy evaluate is your friend:
template '/tmp/sql_file.sql' do
source "sql_file.sql.erb"
mode 0700
variables lazy {
# Create a new instance of MySQL library
mysql_lib = Acx::MySQL.new(
'127.0.0.1', 'root', node['mysql']['service']['pass']
)
password = node['mysql']['service']['support_admin']['ct_password']
# It returns the encrypted password after evaluate it, to
# be used in template variables
{ admin_password: mysql_lib.encrypted_password(password) }
}
end
https://docs.chef.io/resource_common.html#lazy-evaluation

Resources