I'm trying to avoid conflicts with Rails reserved names in a Controller that's receiving JSON.
The code:
class TransactionsController < ApplicationController
#before_action :set_origin_transaction, only: [:show, :edit, :update, :destroy]
skip_before_action :verify_authenticity_token, :only => [:create]
def create
total = origin_transaction_params[:total]
outputs_value = origin_transaction_params[:origin_inputs_attributes][:output_value]
binding.pry
origin_inputs_addresses = origin_transaction_params[:origin_inputs_attributes][:addresses]
origin_outputs_value = origin_transaction_params[:origin_outputs_attributes][:output_value]
origin_outputs_addresses = origin_transaction_params[:origin_outputs_attributes][:addresses]
puts "total: " + total + "outputs_value: " + origin_outputs_value + "inputs_addresses: " + origin_inputs_addresses
puts "outputs_value: " + origin_outputs_value + "outputs_addresses: " + origin_outputs_addresses
end
# This is made to avoid using reserved names of ruby (transaction, inputs, outputs, etc), we change the keys
private
def origin_transaction_params
params.deep_transform_keys! { |key| key == "hash" ? "origin_hash" : ( key == "inputs" ? "origin_inputs_attributes" : ( key == "outputs" ? "origin_outputs_attributes" : ( key == "addresses" ? "btcaddresses" : key))) }
params.permit(
:block_height,
:block_index,
:origin_hash,
:total,
:fees,
:size,
:preference,
:relayed_by,
:received,
:ver,
:lock_time,
:double_spend,
:vin_sz,
:vout_sz, :confirmations,
:origin_inputs_attributes => [ :prev_hash, :output_index, :script, :output_value, :sequence, :btcaddresses, :script_type ],
:origin_outputs_attributes => [ :value, :script, :btcaddresses, :script_type ])
end
end
The error:
Processing by TransactionsController#create as */*
Parameters: {"block_height"=>-1, "block_index"=>-1, "hash"=>"4f14eb3517c92221892d7b86b4e691de404dddecbcc5d6d03148de8b1a6aceb8", "addresses"=>["12onkFjRFBdmgAMW5fapaGfo8E2PWxNRbb", "191JF8jDaCCADJsjrx171fd6PE6D9YtGoi", "1MGHXDQAA4mfBSLK4Dt3QDrAXNcXaaW7JY", "1PZCBuJC53HwjVhXb5B1rA4uFhrHrqrUUC"], "total"=>183092, "fees"=>33660, "size"=>372, "preference"=>"high", "relayed_by"=>"67.205.175.175:8333", "received"=>"2017-01-02T00:59:06.751Z", "ver"=>1, "lock_time"=>0, "double_spend"=>false, "vin_sz"=>2, "vout_sz"=>2, "confirmations"=>0, "inputs"=>[{"prev_hash"=>"dcb03a8c3dc38e28376b5b97479b06c383813c3fc5bcc66fb59c4967b85436c3", "output_index"=>1, "script"=>"47304402205c1cdd0cf3f789375a6dfc0c76eba142724edda2473b235547b7275f7dd0f1c4022046ec4f0be0726d848f6ccd1467b04023897e4575988115c0ac8dbaf569fe03da012102a6237f2117e38d566581452171cff013cfee6f69d5af84fab2214350882a81d9", "output_value"=>108376, "sequence"=>4294967295, "addresses"=>["12onkFjRFBdmgAMW5fapaGfo8E2PWxNRbb"], "script_type"=>"pay-to-pubkey-hash"}, {"prev_hash"=>"9609e8f8a18a11ce54f2b726df5cee24e4589a03feef9b121be5a2eb4ce27ce0", "output_index"=>1, "script"=>"47304402207a29300f3570b5d635b344e3fdc38b3906cb7712870a4a775b4a10cb000b0b6202207ffbd30d0ad0cafb1e93253b17ab302583816c8e17d9d15114c544a6614c9e3201210314fd8f972f8d3e840dfeee629dc5bdcb81c272334c6b23ff34ccd5cbc761fadd", "output_value"=>108376, "sequence"=>4294967295, "addresses"=>["1PZCBuJC53HwjVhXb5B1rA4uFhrHrqrUUC"], "script_type"=>"pay-to-pubkey-hash"}], "outputs"=>[{"value"=>82592, "script"=>"76a91457cf668b86c09b50e1fe89fac148ba321380d54588ac", "addresses"=>["191JF8jDaCCADJsjrx171fd6PE6D9YtGoi"], "script_type"=>"pay-to-pubkey-hash"}, {"value"=>100500, "script"=>"76a914de468bcbc3c1bf0e25dd9b626c60eac3a8d8d91488ac", "addresses"=>["1MGHXDQAA4mfBSLK4Dt3QDrAXNcXaaW7JY"], "script_type"=>"pay-to-pubkey-hash"}], "transaction"=>{"block_height"=>-1, "block_index"=>-1, "hash"=>"4f14eb3517c92221892d7b86b4e691de404dddecbcc5d6d03148de8b1a6aceb8", "addresses"=>["12onkFjRFBdmgAMW5fapaGfo8E2PWxNRbb", "191JF8jDaCCADJsjrx171fd6PE6D9YtGoi", "1MGHXDQAA4mfBSLK4Dt3QDrAXNcXaaW7JY", "1PZCBuJC53HwjVhXb5B1rA4uFhrHrqrUUC"], "total"=>183092, "fees"=>33660, "size"=>372, "preference"=>"high", "relayed_by"=>"67.205.175.175:8333", "received"=>"2017-01-02T00:59:06.751Z", "ver"=>1, "lock_time"=>0, "double_spend"=>false, "vin_sz"=>2, "vout_sz"=>2, "confirmations"=>0, "inputs"=>[{"prev_hash"=>"dcb03a8c3dc38e28376b5b97479b06c383813c3fc5bcc66fb59c4967b85436c3", "output_index"=>1, "script"=>"47304402205c1cdd0cf3f789375a6dfc0c76eba142724edda2473b235547b7275f7dd0f1c4022046ec4f0be0726d848f6ccd1467b04023897e4575988115c0ac8dbaf569fe03da012102a6237f2117e38d566581452171cff013cfee6f69d5af84fab2214350882a81d9", "output_value"=>108376, "sequence"=>4294967295, "addresses"=>["12onkFjRFBdmgAMW5fapaGfo8E2PWxNRbb"], "script_type"=>"pay-to-pubkey-hash"}, {"prev_hash"=>"9609e8f8a18a11ce54f2b726df5cee24e4589a03feef9b121be5a2eb4ce27ce0", "output_index"=>1, "script"=>"47304402207a29300f3570b5d635b344e3fdc38b3906cb7712870a4a775b4a10cb000b0b6202207ffbd30d0ad0cafb1e93253b17ab302583816c8e17d9d15114c544a6614c9e3201210314fd8f972f8d3e840dfeee629dc5bdcb81c272334c6b23ff34ccd5cbc761fadd", "output_value"=>108376, "sequence"=>4294967295, "addresses"=>["1PZCBuJC53HwjVhXb5B1rA4uFhrHrqrUUC"], "script_type"=>"pay-to-pubkey-hash"}], "outputs"=>[{"value"=>82592, "script"=>"76a91457cf668b86c09b50e1fe89fac148ba321380d54588ac", "addresses"=>["191JF8jDaCCADJsjrx171fd6PE6D9YtGoi"], "script_type"=>"pay-to-pubkey-hash"}, {"value"=>100500, "script"=>"76a914de468bcbc3c1bf0e25dd9b626c60eac3a8d8d91488ac", "addresses"=>["1MGHXDQAA4mfBSLK4Dt3QDrAXNcXaaW7JY"], "script_type"=>"pay-to-pubkey-hash"}]}}
DEPRECATION WARNING: Method deep_transform_keys! is deprecated and will be removed in Rails 5.1, as `ActionController::Parameters` no longer inherits from hash. Using this deprecated behavior exposes potential security problems. If you continue to use this method you may be creating a security vulnerability in your app that can be exploited. Instead, consider using one of these documented methods which are not deprecated: http://api.rubyonrails.org/v5.0.1/classes/ActionController/Parameters.html (called from origin_transaction_params at /var/www/html/hubble/app/controllers/transactions_controller.rb:23)
Unpermitted parameter: btcaddresses
Unpermitted parameter: btcaddresses
Unpermitted parameter: btcaddresses
Unpermitted parameter: btcaddresses
Unpermitted parameters: btcaddresses, transaction
DEPRECATION WARNING: Method deep_transform_keys! is deprecated and will be removed in Rails 5.1, as `ActionController::Parameters` no longer inherits from hash. Using this deprecated behavior exposes potential security problems. If you continue to use this method you may be creating a security vulnerability in your app that can be exploited. Instead, consider using one of these documented methods which are not deprecated: http://api.rubyonrails.org/v5.0.1/classes/ActionController/Parameters.html (called from origin_transaction_params at /var/www/html/hubble/app/controllers/transactions_controller.rb:23)
Unpermitted parameter: btcaddresses
Unpermitted parameter: btcaddresses
Unpermitted parameter: btcaddresses
Unpermitted parameter: btcaddresses
Unpermitted parameters: btcaddresses, transaction
Completed 500 Internal Server Error in 13ms (ActiveRecord: 0.0ms)
TypeError (no implicit conversion of Symbol into Integer):
app/controllers/transactions_controller.rb:9:in `[]'
I would also like to stop using the deprecated method.
UPDATE
As suggested by #Glyoko removed a lot of wrong things:
class TransactionsController < ApplicationController
skip_before_action :verify_authenticity_token, :only => [:create]
def create
total = transaction_params[:total]
binding.pry #debugging
render status: :created
end
private
def transaction_params
params.permit(
:block_height, :block_index, :hash,
:addresses[], #### LINE 15 ERROR
:total, :fees, :size, :preference, :relayed_by, :received,
:ver, :lock_time, :double_spend, :vin_sz, :vout_sz, :confirmations,
:inputs => [ :prev_hash, :output_index, :script, :output_value, :sequence, :addresses[], :script_type],
:outputs => [ :value, :script, :addresses [], :script_type ])
end
end
ERROR:
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms)
ArgumentError (wrong number of arguments (given 0, expected 1..2)):
app/controllers/transactions_controller.rb:15:in []'
app/controllers/transactions_controller.rb:15:intransaction_params'
app/controllers/transactions_controller.rb:6:in `create'
Notice that addresses might have 1 or several addresses
I don't think there's any problem here relating to reserved keywords, though I see at least 4 things going wrong:
1) The TypeError on line 9,
2) The deprecation warning,
3) The unpermitted parameter warning, and
4) The 500 error,
The tl;dr is that the params.deep_transform_keys! is doing some serious dark magic for all the wrong reasons, and you should probably delete that line and rethink your approach. That deep_transform_keys! is definitely the reason for (2) and (3), and is possibly the reason for (1). More detailed answers, in the order I listed them:
1) The TypeError on line 9 comes from origin_transaction_params[:origin_inputs_attributes][:output_value]. origin_transaction_params[:origin_inputs_attributes] is returning some sort of non-hash object, which means you're calling something_thats_not_a_hash[:output_value], which produces the TypeError. You could add protection for this in your controller, but this probably reflects a deeper problem with your data structure. (What's the JSON payload look like?)
2) As of Rails 4, params is now an instance of ActionController::Parameters. params will look and act like a hash, but it is not really a hash proper under the hood. This means that not all hash methods will work on it. In this case, deep_transform_keys! happens to work for now, but as the warning says, its implementation will change as of Rails 5.1 and deep_transform_keys! will no longer work on it. There's no way to get rid of this warning without getting rid of the call to deep_transform_keys!.
In fact, the proper use case of strong params is to call permit only on key names that are part of the expected payload. That is, only call permit on key names that are part of the unaltered JSON payload. This probably means you should in fact get rid of the deep_transform_keys!, as using it to alter the params hash is improper usage.
In any case, "transaction", "inputs", and "outputs" are NOT reserved keywords in ruby, and even if they were, that wouldn't stop them from being keys in a hash as long as they're quoted.
3) The deep_transform_keys! line is creating a root level key called "btcaddresses". It's not just inside origin_inputs_attributes/origin_outputs_attributes, so it needs to be permitted at the root. Again, this is only needed if you keep the deep_transform_keys! line. You really probably want to get rid of it.
4) The 500 error is coming from (1), so this would be solved once that's fixed, although you may still encounter 500's if your views aren't setup properly. If this happens, try adding something like
render status: :created
to the end of the create method, and make sure you have a create template in your view/ directory.
everyone
Code is now working, it just still saying "Unpermitted parameter: transaction", but it's printing what I needed. I searched the JSON and there's not a single word named transaction, and same thing within the code:
class TransactionsController < ApplicationController
skip_before_action :verify_authenticity_token, :only => [:create]
def create
amount = btcTx_params[:total]
btcAddresses = btcTx_params[:outputs][0][:addresses]
confirmations = btcTx_params[:confirmations]
double_spend = btcTx_params[:double_spend]
puts "Bitcoin Addresses = #{btcAddresses}"
puts "Amount = #{amount}"
puts "Confirmations = #{confirmations}"
puts "Is double spend? = #{double_spend}"
#binding.pry #debugging
render status: :created
end
private
def btcTx_params
params.permit(
:block_height, :block_index, :hash,
:total, :fees, :size, :preference, :relayed_by, :received,
:ver, :lock_time, :double_spend, :vin_sz, :vout_sz, :confirmations,
:inputs => [ :prev_hash, :output_index, :script, :output_value, :sequence, :script_type, :addresses => [] ],
:outputs => [ :value, :script, :script_type, :addresses => [] ],
:addresses => [])
end
end
Output:
Parameters:
{
"block_height":-1,
"block_index":-1,
"hash":"4f14eb3517c92221892d7b86b4e691de404dddecbcc5d6d03148de8b1a6aceb8",
"addresses":[
"12onkFjRFBdmgAMW5fapaGfo8E2PWxNRbb",
"191JF8jDaCCADJsjrx171fd6PE6D9YtGoi",
"1MGHXDQAA4mfBSLK4Dt3QDrAXNcXaaW7JY",
"1PZCBuJC53HwjVhXb5B1rA4uFhrHrqrUUC"
],
"total":183092,
"fees":33660,
"size":372,
"preference":"high",
"relayed_by":"67.205.175.175:8333",
"received":"2017-01-02T00:59:06.751Z",
"ver":1,
"lock_time":0,
"double_spend":false,
"vin_sz":2,
"vout_sz":2,
"confirmations":0,
"inputs":[
{
"prev_hash":"dcb03a8c3dc38e28376b5b97479b06c383813c3fc5bcc66fb59c4967b85436c3",
"output_index":1,
"script":"47304402205c1cdd0cf3f789375a6dfc0c76eba142724edda2473b235547b7275f7dd0f1c4022046ec4f0be0726d848f6ccd1467b04023897e4575988115c0ac8dbaf569fe03da012102a6237f2117e38d566581452171cff013cfee6f69d5af84fab2214350882a81d9",
"output_value":108376,
"sequence":4294967295,
"addresses":[
"12onkFjRFBdmgAMW5fapaGfo8E2PWxNRbb"
],
"script_type":"pay-to-pubkey-hash"
},
{
"prev_hash":"9609e8f8a18a11ce54f2b726df5cee24e4589a03feef9b121be5a2eb4ce27ce0",
"output_index":1,
"script":"47304402207a29300f3570b5d635b344e3fdc38b3906cb7712870a4a775b4a10cb000b0b6202207ffbd30d0ad0cafb1e93253b17ab302583816c8e17d9d15114c544a6614c9e3201210314fd8f972f8d3e840dfeee629dc5bdcb81c272334c6b23ff34ccd5cbc761fadd",
"output_value":108376,
"sequence":4294967295,
"addresses":[
"1PZCBuJC53HwjVhXb5B1rA4uFhrHrqrUUC"
],
"script_type":"pay-to-pubkey-hash"
}
],
"outputs":[
{
"value":82592,
"script":"76a91457cf668b86c09b50e1fe89fac148ba321380d54588ac",
"addresses":[
"191JF8jDaCCADJsjrx171fd6PE6D9YtGoi"
],
"script_type":"pay-to-pubkey-hash"
},
{
"value":100500,
"script":"76a914de468bcbc3c1bf0e25dd9b626c60eac3a8d8d91488ac",
"addresses":[
"1MGHXDQAA4mfBSLK4Dt3QDrAXNcXaaW7JY"
],
"script_type":"pay-to-pubkey-hash"
}
]
}
Unpermitted parameter: transaction
Unpermitted parameter: transaction
Unpermitted parameter: transaction
Unpermitted parameter: transaction
PUTS
Bitcoin Addresses = ["191JF8jDaCCADJsjrx171fd6PE6D9YtGoi"]
Amount = 183092
Confirmations = 0
Is double spend? = false
Rendering transactions/create.html.erb within layouts/application
Rendered transactions/create.html.erb within layouts/application (0.6ms)
Completed 201 Created in 41ms (Views: 28.5ms | ActiveRecord: 0.0ms)
But that was hell out of an improvement.
Thanks a lot, guys
Aaaaaand...it's done!
class TransactionsController < ApplicationController
skip_before_action :verify_authenticity_token, :only => [:create]
def create
amount = btcTx_params[:total]
btcAddresses = btcTx_params[:outputs][0][:addresses]
confirmations = btcTx_params[:confirmations]
double_spend = btcTx_params[:double_spend]
puts "Bitcoin Addresses = #{btcAddresses}"
puts "Amount = #{amount}"
puts "Confirmations = #{confirmations}"
puts "Is double spend? = #{double_spend}"
#binding.pry
#binding.pry #debugging
render status: :created
end
private
def btcTx_params
params.require(:transaction).permit(
:block_height, :block_index, :hash,
:total, :fees, :size, :preference, :relayed_by, :received,
:ver, :lock_time, :double_spend, :vin_sz, :vout_sz, :confirmations,
:inputs => [ :prev_hash, :output_index, :script, :output_value, :sequence, :script_type, :addresses => [] ],
:outputs => [ :value, :script, :script_type, :addresses => [] ],
:addresses => [])
end
end
It needed params.require(:transaction). Now the unpermitted parametter: transaction error is gone =) thanks a lot for your help