Rails 5 – assign model attribute and save - ruby-on-rails

I've got a problem with assigning some value to model attribute and save it. I've tried a lot of ways, but none worked.
#rating = Rating.new(rating_params)
#rating.save
#rating.update_attribute(:ip_address, request.remote_ip)
or
#rating = Rating.new(rating_params)
#rating.ip_address = request.remote_ip
#rating.save
Nothing is working for me :-( Everytime I got NULL in my database for column ip_address

Solution to debug in this situation.
#rating = Rating.new(rating_params)
#rating.ip_address = request.remote_ip
#check is't valid to save: true || false
#rating.valid?
# if false, print error messages
p #rating.errors
p #rating.errors.full_messages
#either way you can try save without validation.
#rating.save(:validate => false)
Also, What data type of column ip_address. You can't save integer into string or vice versa.
remote_ip by default string class, if want to save as integer.
Convert String Ip-address to Integer

Related

Rails - PG::DatatypeMismatch: ERROR

So it's a very beginner question, I am getting the following error. I know that I need to convert it over to string type. I have tried many kinds of conversion method, but yet to work. Hard coding this field as something like '2018-01-01' works. The param content that I am getting back is correct. It is the type that is creating this error. I even try to convert it over to a date type and tested the type and returned true, but still fail to succeed. Let me know if this makes sense.
PG::DatatypeMismatch: ERROR: column "order_date" is of type date but expression is of type integer
My expresson
created_at = (params[:created_at])
Have tried
created_at = (params[:created_at]).to_date
created_at = (params[:created_at]).to_s
I am trying to get the params[:created_at] from the payload and use the following code to insert into psql. So I think I should go with the create action. Please let me know what I am doing wrong.
def create
created_at = (params[:created_at])
puts created_at
sql = "insert into api.salesorder(site, order_date,sale_type,sales_rep,terms,customer_number) values('WHS',#{created_at},'CUST','HOUSE','PRE','123456')"
results = ActiveRecord::Base.connection.execute(sql)
end
If you still want to use direct SQL (which I advise against in Rails, since Rails does the SQL for you), you need to change it to wrap your date in single quotes.
sql = "insert into api.salesorder(site, order_date, sale_type,sales_rep, terms, customer_number) values('WHS','#{created_at}','CUST','HOUSE','PRE','123456')"
A better solution would be to leverage Rails to do the SQL work for you. Something like this:
# in app/models/salesorder.rb
class Salesorder < ActiveRecord::Base
end
# in app/controller/salesorder_controller.rb
class SalesorderController < ApplicationController
def create
#salesorder = Salesorder.new
#salesorder.order_date = params[:created_at]
#salesorder.site = 'WHS'
#salesorder.sale_type = 'CUST'
#salesorder.sales_rep = 'HOUSE'
#salesorder.terms = 'PRE'
#salesorder.customer_number = '123456'
if #salesorder.save
redirect_to #salesorder, notice: 'Salesorder was successfully created.'
else
render :new
end
end
end
You could do something like created_at = Date.parse(params[:created_at]), but i don't think it's nescessary. Some more information might be helpful. Is your params an integer type?

Ruby on Rails: How can i iterate over params and convert any empty strings into nil values in a controller?

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.

Rails Precision searching the database

I have this to find a DB Entry with the key field the same as the ID params. Now, I get this:
undefined method `confirmed=' for<ActiveRecord::Relation::ActiveRecord_Relation_Email:0x007fd5254c33d8>
And the code:
key = Email.where(:key => params[:id])
if key[1] = nil
#error = true
else
key.confirmed = true
#error = false
end
I was expecting to get a nil if it wasn't in the DB or a Email Object. I was also thinking it could return a hash of Email objects. There should be 0 or 1 DB Entrys. How should I do this correctly? I have no idea what a ActiveRecord::Relation is.
Email.where return multiple records. What you actually want to use is Email.find_by which will allow you to pass a hash of conditions you want the record to match (like how Email.where works), but will return either the first record found, or nil. Your conditional will need to change as a result
You seem to get it completely wrong. Please get acquainted with ActiveRecord documentation.
ActiveRecord::Relation represents query results. Yes, you can update records through it, but this way:
key.update_all(confirmed: true)
which will update confirmed attribute on all records found by the query.
If you want to check whether it has returned at least one record, use:
if key.first
...
To update this one record only:
key.first.confirmed = true
key.first.save
or:
key.update_attribute(:confirmed, true)

Ruby / ROR assignment using or (Default values for checkbox)

I am trying to assign a default value to a check box in ROR. The following is the heirachy:
Check if value is in the params (url querystring)
Check if it's in the session variable
If neither, default to all possible values and set #rates to all possible values
I have written the following code:
#all_rates = Rates.all_rates
rates_all = {}
#all_rates.each {|rate| rates_all[rate] = "1"}
p rates_all
#rates = params[:rates] ||= session[:rates] ||= rates_all
puts #rates.length, #rates
when i p rates_all, i get the hash back, however when i check #rates.length it is not being assigned i get a 0.
Did you check if params[:rates] is nil? Because if it's an empty hash then it's still an object, just without any values. But the empty hash object would be assigned to #rates anyway, resulting that rates is an empty hash object too, with length 0.
Give this a try:
#rates = case
when params[:rates].present?
params[:rates]
when session[:rates].present?
session[:rates]
else
Rates.all_rates.inject({}) { |hsh, rate| hsh.merge(rate => '1') }
end
Sidebar:
Your model name should be the singular Rate. The ||= syntax in your example is invalid. It should be just ||.

Finding a particular attribute's value from a model in Rails

I'm trying to find the value of a particular model's attribute in rails. Here's what my code in the User controller's 'create' method looks like:
#user = User.find(1, :select => :money)
existing_money = #user
puts "#{existing_money}"
In my Heroku logs I'll see a variant of the following output instead of the :money integer for that particular user (with :id 1)
#<User:0x00000004e7cbc0>
Any thoughts? Thanks!
#user = User.find(1, :select => :money)
You are setting the #user instance variable with an object that has only one value, namely the money value. For now, all this does is save you a few bytes, by leaving off things like id, email, and any other columns you have in that table. It does however still return an object with attributes, the only difference is your object has only one attribute to call.
existing_money = #user
Given that #user is still an object with a single attribute, you now save this object in the existing_money local variable. What you probably want to do is *only store the money attribute in this variable`.
So you'd need this:
existing_money = #user.money
puts "#{existing_money}"
After the above change, this puts statement should return the attribute value, not the object encapsulating the attribute.
As existing_money is just the object you are seeing the object's ID.
As you want the money attribute you have to reference that too.
puts "#{existing_money.money}"

Resources