I'm trying to build a generator in rails but I'm getting stuck at trying to access an existing model's parameters. Basically I want to do something like this:
# user is a model the has the parameters "id: integer, name: string, and email: string"
User.parameters.each do |parameter|
# do something with id, name, email
parameter.key
# do something with integer, string, string
parameter.value
end
Any ideas?
I think what you want is this
User.columns_hash.each do |key, value|
key
value.type
end
value.type will give you the type as a symbol. You can convert it to a string if you want it as a string
I think you are looking for attributes, rather than parameters.
user = User.first
user.attributes.each do |key, value|
# do something here with keys and values
puts key if key
puts value if value
end
Notice I'm grabbing an actual instance of the model as well as checking for nils (the if key/ if value part)
Got it! Need to use columns_hash like this:
Event.columns_hash.each {|k,v| puts "#{k} => #{v.type}"}
Credit to Getting types of the attributes in an ActiveRecord object
Related
Rails newbie here.
I have an integration with stripe where users can update the billing address on their card, however, stripe doesn't accept empty strings, only nil values, and it's possible that users won't need to fill in the second address line for example.
How would I go about iterating through params received from a form and convert empty strings into nil?
I have a Stripe Tool module that handles stripe related tasks.
In my controller i have:
def add_billing_address
account_id = current_user.account_id
account = Account.find_by(id: account_id)
stripe_id = account.stripe_customer_id
# convert params empty strings to nil here
StripeTool.add_billing_address(stripe_id: stripe_id,
stripe_token: params[:stripeToken],
address_line1: params[:address_line1],
address_line2: params[:address_line2],
address_city: params[:address_city],
address_state: params[:address_state],
address_zip: params[:address_zip]
)
# redirects and error handling happens after this
You can call .map .each on the params hash in the controller like this:
params.each do |key, value|
params[key] = nil if value === ''
end
But it's probably better to let your form return a nil value when a field contains no data.
I would recommend to avoid modifying the values in the params object, cause it is not good practice to change them in place. It is better to create a new object the has the values you want to use.
stripe_params = params.select { |_,v| v.present? }
This will create a new object without any of the blank attributes. I'm guessing that if an attribute is nil, you might as well not pass it at all.
Initially I import data in datatype Hash, in that i have a column called schedule, I need type of the particular column "schedule" from my db.
my tried code is
schedule = scheduleWorld.all
schedule.each do |sec|
sec.attributes.each do |key, value, type|
puts "%%%%%%%%%%%%%%%%%%%%%%%%%"
puts key
puts value
puts type
puts "%%%%%%%%%%%%%%%%%%%%%%%%%"
end
end
By this am getting nil in type, i tried another code is
schedule = scheduleWorld.where({schedule:{$type=>2}})
error is
undefined method `specify' for nil:NilClass
(eval):2:in `where'
anyone have idea about this?
Type is just one key-value pair in a mongodb document's attributes hash.
So you can always fetch it like this. I'm using Mongoid.
The exact name may vary on you ORM.
schedule = scheduleWorld.all
schedule.each do |sec|
type = sec.attributes["_type"]
sec.attributes.each do |key, value|
puts "%%%%%%%%%%%%%%%%%%%%%%%%%"
puts key
puts value
puts "%%%%%%%%%%%%%%%%%%%%%%%%%"
end
end
I m in a situation where i need to convert an Object to string so that i can check for Invalid characters/HTML in any filed of that object.
Here is my function for spam check
def seems_spam?(str)
flag = str.match(/<.*>/m) || str.match(/http/) || str.match(/href=/)
Rails.logger.info "** was spam #{flag}"
flag
end
This method use a string and look for wrong data but i don't know how to convert an object to string and pass to this method. I tried this
#request = Request
spam = seems_spam?(#request.to_s)
Please guide
Thanks
You could try #request.inspect
That will show fields that are publicly accessible
Edit: So are you trying to validate each field on the object?
If so, you could get a hash of field and value pairs and pass each one to your method.
#request.instance_values.each do |field, val|
if seems_spam? val
# handle spam
end
If you're asking about implementing a to_s method, Eugene has answered it.
You need to create "to_s" method inside your Object class, where you will cycle through all fields of the object and collecting them into one string.
It will look something like this:
def to_s
attributes.each_with_object("") do |attribute, result|
result << "#{attribute[1].to_s} "
end
end
attribute variable is an array with name of the field and value of the field - [id, 1]
Calling #object.to_s will result with a string like "100 555-2342 machete " which you can check for spam.
My code looks like this:
hash = MyModel.count(:group => 'id', :conditions => 'bla = "bla"')
The returned Hash has keys that are strings. I want them to be ints. I know it would be possible to convert the Hash manually using something like a map construct.
Edit:
Thanks for the responses. Have realised it was a json conversion process that was turning the ids into Strings and rails does in fact use the Fixnum as one might expect.
hash = MyModel.count(group: 'id', conditions: 'bla = "bla"')
should have Fixnum keys by default since id is an instance of Fixnum.
What happens is that ActiveRecord always fetch result as strings and then Rails takes care of converting them to other datatypes according to the type of the database column (we say that they are typecast).
So it's maybe a Rails bug or the 'id' column is not set as integer(which would be surprising).
If you can't fix it, convert them manually:
hash.each_with_object({}) do |(key, value), hash|
hash[key.to_i] = value
end
When I use your code I get integer keys (rails 3.07), what's the column type of id?
If you want to do it manually:
new_hash = hash.inject({}){|h,a| h[a.first.to_i] = a.last; h}
new_hash = Hash[hash.map { |k, v| [k.to_i, v] }
I have a hash of hashes like so:
Parameters: {"order"=>{"items_attributes"=>{"0"=>{"product_name"=>"FOOBAR"}}}}
Given that the depth and names of the keys may change, I need to be able to extract the value of 'product_name' (in this example "FOOBAR") with some sort of search or select method, but I cannot seem to figure it out.
An added complication is that Params is (I think) a HashWithIndifferentAccess
Thanks for your help.
Is this what you mean?
if params.has_key?("order") and params["order"].has_key?("items_attributes") then
o = params["order"]["items_attributes"]
o.each do |k, v|
# k is the key of this inner hash, ie "0" in your example
if v.has_key?("product_name") then
# Obviously you'll want to stuff this in an array or something, not print it
print v["product_name"]
end
end
end