Rails adds an extra 'command' object to my POST params - ruby-on-rails

Rails 4.1 is adding a strange object to my POST parameters, which is a duplicate of the data I post.
As a very basic test, I post a simple {"msg"=>"hello word!"} from Angular:
$http.post('/commands/save.json', {msg:'hello word!'}).
Rails gets:
Started POST "/commands/save.json" for ::1 at 2015-01-08 10:15:55 -0800
ActiveRecord::SchemaMigration Load (0.3ms) SELECT `ngconf_schema_migrations`.* FROM `ngconf_schema_migrations`
Processing by CommandsController#save as JSON
Parameters: {"msg"=>"hello word!", "command"=>{"msg"=>"hello word!"}}
{
"msg" => "hello word!",
"controller" => "commands",
"action" => "save",
"format" => "json",
"command" => {
"msg" => "hello word!"
}
}
Commands Load (0.3ms) SELECT `ngconf_commands`.* FROM `ngconf_commands`
Completed 200 OK in 16ms (Views: 1.5ms | ActiveRecord: 12.8ms)
Basically I am trying to understand where does this come from and how to stop it. I do not remember Rails 4.0 doing this.
"command" => {
"msg" => "hello word!"
}

This is coming from ParamsWrapper. You can disable this by specifying wrap_parameters false in the controller. If you would like to disable it application wide, edit your config/initializers/wrap_parameters.rb and set the :format option to an empty array as per the comments. As an example
# Be sure to restart your server when you modify this file.
#
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: []
end

Related

Encode string params in rails api

In this when I am passing phone as string in params rails api, it is being passed in the form of "\"9650661678\"". How to use escape string or how to encode it so that only string can be entered as input.
Any help will be welcomed ! Thanks in advance.
clients_controller.rb
def myzenica
mobile = params[:phone]
client = Client.where(:phone => mobile)
render :json => client
end
terminal
Started GET "/clients/myzenica?phone=%229650661678%22" for 127.0.0.1 at 2016-03-15 11:21:23 +0530
Processing by ClientsController#myzenica as */*
Parameters: {"phone"=>"\"9650661678\"", "client"=>{}}
Client Load (0.3ms) SELECT `clients`.* FROM `clients` WHERE `clients`.`phone` = '\"9650661678\"'
Completed 200 OK in 2ms (Views: 0.7ms | ActiveRecord: 1.2ms)
You can use CGI.
require 'cgi'
CGI.escape('%229650661678%22')
=> "\"9650661678\""
UPDATE:
def myzenica
require 'cgi'
mobile = CGI.escape(params[:phone])
client = Client.where(:phone => mobile)
render :json => client
end
NOTE:
In your input field which is on postman on your side. You should enter a text without double/single qoutes. Because postman field is just like input field on html tags. It will treat it all as string.

why I can not accept white spaces on field for save in ruby on rails?

I am trying to save a form with rails, its a simple one, and everytime I try to send a name with a space (like john smith) I dont actually get an error, it returns succcess, but does not save anything, when I try johnsmith then it works.
I checked on my model and I have this
validates :first_name, :allow_blank => true, :format => { :with => /\A[a-zA-Z]+\z/, :message => "Only letters allowed" }
validating only letters, but accepting spaces, still, when I try, no success.
At my controller I have something like this.
name = params[:name].to_s
and later
#user.atributes = { :weight => weight, :name => name ... and so on
at the end I only make a #user.save
Any idea how to avoid this problem? I do want to accept spaces on the names, but without getting into security problems.
Thanks
result of the post in my console
Started POST "/users/custom" for 192.168.1.21 at 2013-05-21 17:51:06 -0600
Processing by UsersController#custom as JS
Parameters: {"name"=>" new user", "lastname"=>" my last name", "mail"=>"newuser#gmail.com", "sex"=>"0" ... n so on}
User Load (0.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 6 LIMIT 1
(0.1ms) BEGIN
(0.3ms) UPDATE `users` SET `first_name` = ' new user', `ssn` = 0, `updated_at` = '2013-05-21 23:51:06' WHERE `users`.`id` = 6
(1.2ms) COMMIT
Rendered users/custom.html.erb within layouts/application (0.1ms)
Completed 200 OK in 16ms (Views: 11.0ms | ActiveRecord: 1.7ms)
Your regex is wrong. You're accepting only letters, whitespace is not a letter. Try something like this: \A[a-zA-Z,\s]+\z
BTW rubular is pretty cool tool, if you need to test your regexps.
http://rubular.com/
About the validation message not showing up:
If you're doing asynchronous request, you'll need to make your validation on the client side. There are some gems which can help you with this, e.g. client side validations gem.
Also, if you're using jQuery.ajax() you can use its callback to perform an action after the call (notify user of success or do whatever with DOM you want to):
$.ajax({
url: "http://some/url.com",
// rest of your ajax call
}).done(function (data) {
console.log("Your data:", data); // this will be run after the async. call
});
If you need to debug things like this try pry. Just add to your gemfile:
group :test, :development do
gem 'pry', '~> 0.9.12'
end
Run bundle install, restart server and then you can add:
binding.pry
wherever you want to stop code execution and inspect current state of your app enviroment in the console.
In your case it would be somewhere at the end of UsersController#custom method. You can then check in your terminal value of #user. Methods #user.valid? and #user.errors will tell you if your #user object is valid and show you an array with all validation errors associated with the object.

Provide params hash for put / post requests in rails console

I find it more convenient to check response for some requests from within console
>> app.put '/users/2/'
=> 500
But wasn't able to find a way to specify request parameters. How I have to do that?
If you want to put or post to a URL there are also methods for that. You can copy/paste the parameters exactly as they are displayed in your Rails production log:
app.post('/foo', {"this" => "that", "items" => ["bar", "baz"]})
app.put('/foo', {"this" => "that", "items" => ["bar", "baz"]})
If you want to sent a custom header, you can add an optional third parameter:
app.post('/foo', {:this => "that", :items => ["bar", "baz"]}, {"X-Do-Something" => "yes"})
Any of the get/post/put/delete methods will display their full log output on the console for you to examine. If you want to get information such as the response body returned, HTTP status or response headers these are easy too:
app.response.body
app.response.status
app.response.headers.inspect
Source: http://andyjeffries.co.uk/articles/debug-level-logging-for-a-single-rails-production-request
The above has changed to
app.post '/foo', params: {"this" => "that", "items" => ["bar", "baz"]}
Also for forms I had to give an authenticity_token as well.
So in my example the full command was
app.post '/login', params: {email: 'my_email#gmail.com', password: 'abcd', authenticity_token: 'my_authenticity_token_generated_for_this_view' }

Ruby: HTTParty: can't format XML POST data correctly?

NOTE: "object" is a placeholder work, as I don't think I should be saying what the controller does specifically.
so, I have multiple ways of calling my apps API, the following works in the command line:
curl -H 'Content-Type: application/xml' -d '<object><name>Test API object</name><password>password</password><description>This is a test object</description></object>' "http://acme.example.dev/objects.xml?api_key=1234"
the above command generates the following request in the devlog:
Processing ObjectsController#create to xml (for 127.0.0.1 at 2011-07-07 09:17:51) [POST]
Parameters: {"format"=>"xml", "action"=>"create", "api_key"=>"1234", "controller"=>"objects",
"object"=>{"name"=>"Test API object", "description"=>"This is a test object", "password"=>"[FILTERED]"}}
Now, I'm trying to write tests for the actions using the API, to make sure the API works, as well as the controllers.
Here is my current (broken) httparty command:
response = post("create", :api_key => SharedTest.user_api_key, :xml => data, :format => "xml")
this command generates the following request in the testlog:
Processing ObjectsController#create to xml (for 0.0.0.0 at 2011-07-07 09:37:35) [POST]
Parameters: {
"xml"=>"<object><name><![CDATA[first post]]></name>
<description><![CDATA[Things are not as they used to be]]></description>
<password><![CDATA[WHEE]]></password>
</object>",
"format"=>"xml",
"api_key"=>"the_hatter_wants_to_have_tea1",
"action"=>"create",
"controller"=>"objects
So, as you can see, the command line command actually generates the object hash from the xml, whereas the httparty command ends up staying in xml, which causes problems for the create method, as it needs a hash.
Any ideas / proper documentation?
Current documentation says that post takes an url, and "options" and then never says what options are available
**EDIT:
as per #Casper's suggestion, my method now looks like this:
def post_through_api_to_url(url, data, api_key = SharedTest.user_api_key)
response = post("create", {
:query => {
:api_key => api_key
},
:headers => {
"Content-Type" => "application/xml"
},
:body => data
})
ap #request.env["REQUEST_URI"]
assert_response :success
return response
end
unfortunately, the assert_response fails, because the authentication via the api key fails.
looking at the very of of the request_uri, the api_key isn't being set properly... it shows:
api_key%5D=the_hatter_wants_to_have_tea1"
but it should just be equals, without the %5D (right square bracket)
I think this is how you're supposed to use it:
options = {
:query => {
:api_key => 1234
},
:headers => {
"Content-Type" => "application/xml"
},
:body => "<xmlcode>goes here</xmlcode>"
}
post("/create", options)
Forgive me for being basic about it but if you only want to send one variable as a parameter, why don't you do as Casper suggests, but just do:
post("/create?api_key=1234", options)
Or rather than testing HTTParty's peculiarities in accessing your API, perhaps write your tests using Rack::Test? Very rough example...
require "rack/test"
require "nokogiri"
class ObjectsTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
MyApp.new
end
def create_an_object(o)
authorize "x", "1234" # or however you want to authenticate using query params
header 'Accept', 'text/xml'
header 'Content-Type', 'text/xml'
body o.to_xml
post "/create"
xml = Nokogiri::XML(last_response.body)
assert something_logic_about(xml)
end
end

Problem with Rails 3 and AMF , rails3-amf, RocketAMF

im trying to get AMF to work with Rails3.
I have succesfully installed rails3-amf-0.1.0 gem and the RocketAMF-0.2.1 gem.
In my app there is a controller with the following code:
def getRandomCards
#incoming = params[0]
#cards = Cardvo.first
respond_with(#cards) do |format|
format.amf { render :amf => #cards.to_amf}
end
end
through a call from Actionscript i would like to return some data in amf format.
further more, as mentioned in the instructions for rails3-amf i did the following.
in my production.rb under config/environment i added the line
config.rails3amf.map_params :controller => 'CardvosController', :action => 'getRandomCards'
an my amf gateway got
config.rails3amf.gateway_path = "/gateway"
The problem is:
Any call from Actionscript / Flash raises the following
(taken from the log )
Started POST "/gateway" for 192.178.168.1 at Fri Nov 19 15:13:28 +0100 2010
Processing by CardvosController#getRandomCards as AMF
Parameters: {0=>100.0}
[1m[36mSQL (0.4ms)[0m [1mSHOW TABLES[0m
[1m[35mCardvo Load (0.2ms)[0m SELECT `cardvos`.* FROM `cardvos` LIMIT 1
Completed 200 OK in 13ms (Views: 0.9ms | ActiveRecord: 0.5ms)
NoMethodError (undefined method `constructed?' for #<RocketAMF::Envelope:0x39ba868>):
The Amf file is created but the method, which is in remoting.rb from RocketAMF could not be found.
I think the error is thrown at request_parser.rb from Rails3AMF asking for constructed?
# Wrap request and response
env['rack.input'].rewind
env['rails3amf.request'] = RocketAMF::Envelope.new.populate_from_stream(env['rack.input'].read)
env['rails3amf.response'] = RocketAMF::Envelope.new
# Pass up the chain to the request processor, or whatever is layered in between
result = #app.call(env)
# Calculate length and return response
if env['rails3amf.response'].constructed?
For me it seems it is looking at the wron class for the method.
Where
NoMethodError (undefined method `constructed?' for #RocketAMF::Envelope:0x39ba868):
the essential part is
RocketAMF::Envelope:0x39ba868
which should be
RocketAMF:ANOTHER_CLASS:Envelope:0x39ba868
Am i right and where the heck is the error ?
Any help would be appreciated!
chris

Resources