Reference database column with variable in sequel sinatra - ruby

How do I refernce the column in the database with the column variable in the url/route. The column varible is a string coming from a webpage, and I have to reference the column with a hash key.
Sinatra route:
get '/users/update/:id/:column/:value' do
User.where(id: params[:id]).update(column: params[:value])
redirect back
end
Html:
Value

If you are looking to use params[:column] as a variable key in the update you can use the hash rocket syntax:
User.where(id: params[:id]).update(params[:column] => params[:value])

Related

ruby sequel gem - how to query arrays with the pg_array extension

I am using the pg_array extension and sequel version 4.1.1.
I have added the extension like this:
Sequel::Database.extension :pg_array
I have created a column like this:
alter_table :emails do
add_column :references, "text[]", null: true
end
I can load and retrieve arrays into a postgress array column, just like working with normal arrays.
What is not clear from the above link is how do I execute a query based on the values in this array column.
For example, if one row in the emails table contained these values in the references column:
references
--------------------------------------------------------------------
{}
{5363f773bccf9_32123fe75c45e6f090953#Pauls-MacBook-Pro.local.mail}
How can I query the emails table to find a row that contains a references array value of the above value:
Email.where(references: ????)
Use the pg_array_ops extension:
Sequel.extension :pg_array_ops
Email.where(Sequel.pg_array_op(:references).contains('5363f773bccf9_32123fe75c45e6f090953#Pauls-MacBook-Pro.local.mail'))
Have you tried?
ref = '5363f773bccf9'
emails = Email.arel_table
Email.where( emails[ :references ].matches( "%#{ref}%" ))

How to use Sequel to select one field from database

I am using Sinatra and Sequel with PostgreSQL.
After authentication, I want to welcome the user by printing their name but I cannot get only the value of the user's name from the database, it comes out as a hash.
The query is:
current_user = DB[:users].select(:username).where('password = ?', password).first
and the resulting piece of data is:
Welcome, {:username=>"Rich"}
which looks rather weird, I would prefer it to read "Welcome, Rich".
What am I doing wrong here? I tried the same query without 'first" at the end and that does not work either.
You can either pull the (single) column you selected out of the Hash you are given:
current_user = DB[:users].select(:username).where('password=?', password).first[:username]
Or you can map your results to an array of usernames and pull the first:
# Using a hash in the filter method is simpler than SQL placeholders.
current_user = DB[:users].filter(password:password).select_map(:username).first
But the best way is to get only the user you care about, and then get the name:
# Using [] on a dataset returns the first row matching the criteria
current_user = DB[:users][password:password][:username]
Try Sequel::Dataset#get. Also, as Phrogz points out, Sequel::Dataset#where can take a hash (it will securely escape values to prevent injection attacks).
current_username = DB[:users].where(password: password).get(:username)
There's also Sequel::Dataset#where_single_value, which is optimized for this exact situation:
current_username = DB[:users].select(:username).where_single_value(password: password)

Sequel Migration update with a row's ID

How can you run a Sequel migration that updates a newly added column with a value from the row?
The Sequel documentation shows how you can update the column with a static value:
self[:artists].update(:location=>'Sacramento')
What I need to do is update the new column with the value of the ID column:
something like:
self[:artists].each |artist| do
artist.update(:location => artist[:id])
end
But the above doesn't work and I have been unable to figure out how to get it to go.
Thanks!
artist in your loop is a Hash, so you are calling Hash#update, which just updates the Hash instance, it doesn't modify the database. That's why your loop doesn't appear to do anything.
I could explain how to make the loop work (using all instead of each and updating a dataset restricted to the matching primary key value), but since you are just assigning the value of one column to the value of another column for all rows, you can just do:
self[:artists].update(:location=>:id)
if you need update all rows of a table, because it is a new column that need be populate
artists = DB[:artists]
artists.update(:column_name => 'new value')
or if you need, update only a unique row into your migration file you can:
artists = DB[:artists]
artists.where(:id => 1).update(:column_name1 => 'new value1', :column_name2 => "other")

Timestamp Column from Joined Table Becomes String

I have a table named subs which has many articles. The articles table has a timestamp column called published.
Sub.select( "subs.*,MAX(articles.published) published").joins("LEFT OUTER JOIN articles ON subs.id=articles.sub_id").group("subs.id").first.published.class
=> String
Article.select("max(published) published").group("id").first.published.class
=> ActiveSupport::TimeWithZone
I want to get an ActiveSupport::TimeWithZone object back from the first query.
Rails 3
Rails determines how to type cast attributes based on their database column definitions. For example, say you have a created_at method on your Sub model. When a record is loaded read_attribute is used (ActiveRecord::AttributeMethods::Read). This uses type_cast_attribute which determines how to cast the value based on the column info. For example, if you are using PostgreSQL it may use:
Sub.columns.detect { |c| c.name == "created_at" }.type_cast_code("v")
=> "ActiveRecord::ConnectionAdapters::PostgreSQLColumn.string_to_time(v)"
But Rails doesn't know what to do with columns that aren't on the Sub model. So it just gives back a String. If you need to work with a ActiveSupport::TimeWithZone object, you can cast the value with:
published = Sub.select( "subs.*,MAX(articles.published) published").joins("LEFT OUTER JOIN articles ON subs.id=articles.sub_id").group("subs.id").first.published
published.present? ? Time.zone.parse(published) : nil
Rails 4
In Rails 4, Rails is smarter about this kind of type-casting. When the SQL is executed, ActiveRecord::Result is created and the column_types are passed to the initializer. In your example Sub.select query, the published column would be cast as a Time object.

Ruby Rails - save vs update where method

I am trying to make a inventory system, my table has the index "id" by default as primary key. My inventory number should be unique value to create new entry in the table, if the inventory already exists then it shall update the attributes. How do do this? By making inventory number as primary key? or is there any way to check and update an inventory already exists?
You can have unique field number (for example). Than you can use find_or_create_by_<field_name> dirty method.
#ticket = Ticket.find_or_create_by_number(503)
Updated:
#ticket.attrib = 'new attribute value'
#ticket.save
or
#ticket.update_attribute :attrib, 'new attribute value'
This worked: create_or_update method in rails
my_class = ClassName.find_or_initialize_by_name(name)
my_class.update_attributes({:street_address => self.street_address,.....})

Resources