setting conditional attributes for API connection - ruby-on-rails

A method needs to instantiate a session with various attributes, some of which are optional
session = Checkout::Session.create({
locale: I18n.locale,
reference_id: id,
customer_email: #user_mail,
[...]
})
The last shown attribute, customer_email, is optional but it should not be generated if the value does not exist.
customer_email: #user_mail unless !#user_email,
logically hits a syntax error because an additional param (the comma) is being produced
syntax error, unexpected ',', expecting end
and thus the API expects another attribute.
(customer_email: #user_mail, unless !#user_email)
also fails as there is confusion over the parenthesis
syntax error, unexpected ')', expecting then or ';' or '\n'
How should this syntax be cast?

You need to extract the options hash into a variable and manipulate it before sending it to the Checkout::Session.create.
Something like this:
options = {
locale: I18n.locale,
reference_id: id
}
options[:customer_email] = #user_mail if #user_email
session = Checkout::Session.create(options)

Related

improper jbuilder syntax for output during API error handling

The following is a json.jbuildermethod intended to respond to an API call.
if #error_code_98?
json.set! :chain_category do
json.set! :error, #error_98_messages
end
end
#error_code_99 = true when said errors arise.
error_98_messages is a concatenation of string that provide an indentifier with the nature of the error. They are accumulated as an array of items are handled by the API action.
When the error hits, the instance variable gets populated, but at the end of the action the return message this the following error
syntax error, unexpected tSYMBEG, expecting ':'
json.set! :chain_category do
I thought this was respecting the syntax for dynamic attribution, but that is mistaken. Where is the syntax off?

How do I correctly interpolate controller name and action

I'm trying to write a method that dynamically assigns the controller name and action for all my controllers in application_controller, but I can't seem to interpolate the value correctly. If I hardcode what I want, it will render the correct page so it seems to only be the interpolation that's the problem.
This is what I have:
def authorized
render 'pages/unauthorized' unless Policy.new(current_user.role)."#{controller_name.singularize}_#{action_name}"
end
which returns
syntax error, unexpected tSTRING_BEG, expecting '(' ...Policy.new(current_user.role)."#{controller_name.singularize... ... ^
If I wrap the whole thing in ( ) then the syntax error goes away, but then I get a:
undefined method `call' for #<Policy:0x00007ff29ced4ae0 #role="user">
if I hardcode Policy.new(current_user.role).wiki_show then it correctly checks resolves. What am I doing wrong in the interpolation?
You could use Object#public_send:
public_send(string [, args...]) → obj
Invokes the method identified by symbol, passing it any arguments
specified. Unlike send, #public_send calls public methods only. When
the method is identified by a string, the string is converted to a
symbol.
It works like:
class Foo
def bar
'bar'
end
end
bar_method = 'bar'
p Foo.new.public_send(bar_method) # "bar"
So you could do
Policy.new(current_user.role).public_send("#{controller_name.singularize}_#{action_name}")

Syntax to conditional import CSV in Rails

The following import method needs to handle input variables set as nil
def self.import(file, unit_id, profit_center_column [...]
CSV.foreach(file.path, :col_sep => "\t", headers: true, skip_blanks: true) do |row|
begin
Asset.create(
unit_id: unit_id,
profit_center_id: row[profit_center_column] unless profit_center_column.nil?,
[...]
Where the controller launching this method defines
params[:profit_center_column] = #unit.profit_center_column
where #unit.profit_center_column = nil.
I am hitting an unexpected syntax error, unexpected modifier_unless, expecting ')' I have never had to use parenthesis before using unless and I woudl expect the use of the comma here to clearly seperate the statements. Where is the syntax getting messed up?
Rails 4.2.4 and Ruby 2.3.4 are in use.
Note, I've also attempted if statements, but that led to loading random xxx_column information.
You're passing a conditional to the Asset's constructor. If you need to take care of it I'd suggest first initializing Asset with ensured not nil values and afterwards using setters for the remaining attributes:
asset = Asset.new(
unit_id: unit_id,
....
asset.profit_center_id = row[profit_center_column] unless profit_center_column.nil?
asset.save

How to check if a string contain valid hash

i encounter a problem when i want to validate the input string if it contain a valid hash before execute eval on it, for example:
"{:key=>true}" if i run eval it return a correct hash, but if i run eval on this string "{:key=>true" i get syntax error of expected token:
(eval):1: syntax error, unexpected end-of-input, expecting '}' {:redirect=>true ^
i did tried some basic validation but no luck so far.
so basically what i want to know is how to validate a that a string contain correct hash format.
You can't tell without actually parsing it as Ruby, and (assuming you trust the string), the simplest way of parsing it is to simply do the eval call, and handle the exception:
begin
hash = eval(string)
rescue SyntaxError
# It's not valid
end
This is precisely what exceptions are for, instead of littering your code with checks for whether operations will succeed, you just perform the operations, and handle errors that occur.
To validate the string you can use Kernel#eval + checking the type:
def valid_hash?(string)
eval(string).is_a?(Hash)
rescue SyntaxError
false
end
Usage:
string = "{:key=>true}"
valid_hash?(string)
#=> true
string = "I am not hash"
valid_hash?(string)
#=> false
I had a similar problem, but I don't like the eval solution, because it's not safe.
I used the JSON gem and modified the string to match the JSON syntax.
Assuming you only have symbol keys.
'key: value' to '"key": value'
':key => value' to '"key": value'
string1 = "{:key_1=>true,key_2:false}"
string2 = "{:key=>true}"
string3 = "no hash"
def valid_hash?(string)
begin
string = string.gsub(/(\w+):\s*([^},])/, '"\1":\2')
#=> "{:key_1=>true,\"key_2\":false}"
string = string.gsub(/:(\w+)\s*=>/, '"\1":')
#=> "{\"key_1\":true,\"key_2\":false}"
my_hash = JSON.parse(string, {symbolize_names: true})
#=> {:key_1=>true, :key_2=>false}
my_hash.is_a? Hash # or do whatever you want with your Hash
rescue JSON::ParserError
false
end
end
valid_hash? string1
#=> true
valid_hash? string2
#=> true
valid_hash? string3
#=> false

formatting JSON object in rails 3

I have a rails app has an api for iphone/android clients. I'm doing Message.find(1).to_json(:include => :user) but that adds \ around " to escape it.
How can I prevent to_json from escaping the double quotes?
>> { "a" => "blah" }.to_json
=> "{\"a\":\"blah\"}"
I would like it to be { "a" : "blah" } or { a : "blah" }
It looks like this is actually what you want.
What you are seeing is the string formatted for display (and human readability). It is delimited by double quotes, so the double quotes inside the string are escaped. In reality, the string contains double quotes, but for literal representation, they are escaped. If you stick this into a JSON parser you will find it returns the object you want.
If you were to print this out, you will find that you get the format you want.
irb(main):001:0> puts { "a" => "blah" }.to_json
{"a":"blah"}
=> nil
For further illustration, you could try parsing it. The string you ended up with returns your original object, because JSON is represented by a string. However, attempting to insert the desired content will give you a nasty syntax error or a TypeError. This is because JSON is not a literal in Ruby, whereas in JavaScript it can be used as a literal object. In Ruby it is a representation in the form of a string.
irb(main):002:0> JSON.parse("{\"a\":\"blah\"}")
=> {"a"=>"blah"}
irb(main):003:0> JSON.parse({ "a" : "blah" })
SyntaxError: (irb):3: syntax error, unexpected ':', expecting tASSOC
JSON.parse({ "a" : "blah" })
^
(irb):3: syntax error, unexpected '}', expecting $end
JSON.parse({ "a" : "blah" })
^
irb(main):004:0> JSON.parse({a:"blah"})
TypeError: can't convert Hash into String

Resources