How is it possible to get the data of just one column in a database table, e.g. title? I'd like to have an array of strings at the end for bootstrap typeahead.
There's a special method just for that: pluck
Post.pluck :title
If your database model is called "Post" and the column is "title" then
Post.select(:title).all.map(&:title)
Will give you an array of all the titles.
This should work:
def get_titles
Yourcolumn.all.each do |i|
#titles += i.title
end
return #titles
end
Related
I have a rails data migration (postgres db) where I have to use pure sql to convert the data due to some model restrictions. The data is stored as json as a string, but I need it to be a usable hash for other purposes.
My migration works to convert it to the hash. However, my down method ends up just deleting the data or leaving it as an empty {}. Btw to clear up any confusion, my column name is actually saved as data in table Games
Based on my up method, how would i properly reverse the migration using sql only?
class ConvertGamesDataToJson < ActiveRecord::Migration[6.0]
def up
statement = <<~SQL
update games set data = regexp_replace(trim(both '"' from data::text), '\\\\"', '"', 'g')::jsonb;
SQL
ActiveRecord::Base.connection.execute(statement)
# this part works!
end
def down
statement = <<~SQL
update games set data = to_json(data::text)::jsonb;
SQL
ActiveRecord::Base.connection.execute(statement)
end
end
Here is how the it looks after properly converting it
data: {
"id"=>"d092a-f2323",
"recent"=>'yes',
"note"=>"some text",
"order"=>1
}
how it is before the migration and what it needs to rollback to:
data:
"{
\"id\":\"d092a-f2323\",
\"recent\":\"yes\",
\"note\":\"some text\",
\"order\":1,
}"
If you're displaying a data structure in the rails console, those \" aren't really there. They're just formatting because the console has wrapped the string in ". For example...
[2] pry(main)> %{"up": "down"}
=> "\"up\": \"down\""
But if we print it...
[3] pry(main)> puts %{"up": "down"}
"up": "down"
Given that is a JSON string, you can simply change the type of the column to jsonb and be done with it.
-- up
alter table games alter column data type jsonb USING data::jsonb;
-- down
alter table games alter column data type text;
Postgres doesn't know how to automatically cast text to jsonb, so we need to tell it. using data::jsonb does a simple cast of the text to jsonb. It can cast jsonb to text just fine.
You can do this in a migration with change_column.
def up
change_column :users, :data, :jsonb, using: 'data::jsonb'
end
def down
change_column :users, :data, :text
end
I want to search a table for a list of pair values.
Ex. This is an array of first and last names.
array = [['jane','doe'],['jack','chen'],['jane','ty'],['mike','ji'],['mike','smith']]
I want to search the User table for each one of these combinations.
Currently, I can only think of running a query per combination.
array.each do |a|
User.where("firstname like (?) and lastname like (?)",a[0],a[1])
end
Is there any way of running all the queries in a single query?
Maintaining the combinations is required.
Following should work for you
query_string_array = []
query_array = []
array.each do |a|
query_string_array << "(firstname like '%?%' AND lastname like '%?%')"
query_array << a
end
User.where(query_string_array.join(" OR "), *query_array.flatten)
Im trying to pull all records from a Project model that includes in the project_name the word 'Fox'. I can do an active record search and return specific project_names, like 'Brown Fox':
#projects = Project.where("project_name like ?", "Brown Fox")
But if I want to return all the names that INCLUDE 'Fox', this does not work unless the complete project name is 'Fox':
#projects = Project.where("project_name like ?", "Fox")
How do I do a search that returns all the objects with the word 'Fox' in the name?
Try using:
variable = "Fox"
Project.where("project_name like ?", "%#{variable}%")
You can use the SQL % operator:
#projects = Project.where("project_name like ?", "%Fox%")
Note that if you want your query to return results ignoring the word case, you can use PostgreSQL ilike instead of like.
Did you try ransack ?
With ransack you can do something like
#projects = Project.search(:project_name_cont => "Fox")
If you think it is too much for what you need. you can use the % operator as MurifoX said
Here's a version that will allow you to handle any number of input words and to search for all of them within a name. I was looking for this answer and didn't find the more complicated case, so here it is:
def self.search(pattern)
if pattern.blank? # blank? covers both nil and empty string
all
else
search_functions = []
search_terms = pattern.split(' ').map{|word| "%#{word.downcase}%"}
search_terms.length.times do |i|
search_functions << 'LOWER(project_name) LIKE ?'
end
like_patterns = search_functions.join(' and ')
where("#{like_patterns}", *search_terms)
end
end
I have a two models as:
Product { has_may variants}
Variant {belongs to product}
I used Sunspot search, and in result I retrieved selected variants, now I want this result as my search result contains the each Product who's one or more variant is retrieved by the search.
code sample of search is as follows:
#search = Sunspot.search(Spree::Variant) do
keywords params[:keywords]
with :is_active, true
with :deleted_at,nil
if params[:ah].present? && params[:al].present?
(Date.parse(params[:al])..Date.parse(params[:ah])).each do |d|
with :f2r_available_on, d.to_time
end
end
end
#products = #search.results
Let me first clarify: in your code above, #search.results is an array of variant records returned from your search, and you want to get all products associated with one or more of these variants?
If so, then this should do that:
#products = Product.where(:id => #search.results.map(&:product_id))
I currently have a .find method in one of my rails controller actions - the relevant part is:
.find(:all, :select => 'last_name as id, last_name as name')
I am getting some odd behaviour trying to alias the last_name column as id - if I alias it as anything else, it works fine (i can do last_name as xyz and it outputs the last name in a column called xyz, but as I am using this to populate a drop-down where I need to have the name in the id column, i need it to be called 'id').
I should point out that it does output an id column, but it is always "id":0.
Could anyone shed any light on what I need to do to get this column aliased as 'id'?
Thanks!
I'm not sure of how you can do this in a Rails query statement. Rails is going to try and take over the id column, casting the value returned by the database as id with the type of column that id is (presumably integer). That's why your id column keeps getting set to 0, because "string".to_i #=> 0
However, there is a way to do it, once you have the results back.
Since you have the question tagged as Rails 3, it is preferable to use the new ActiveRelation syntax. You can do the following:
# First, get the results from the query, then loop through all of them.
Customer.select("last_name as 'ln', last_name as 'name'").all.collect do |c|
# The first step of the loop is to get the attributes into a hash form
h = c.attributes
# The next step is to create an "id" key in the hash.
# The Hash#delete method deletes the key/value pair at the key specified and returns the value.
# We'll take that returned value and assign it to the just created "id" key.
h["id"] = h.delete("ln")
# And we have to call out the hash to ensure that it's the returned value from the collect.
h
end
That will get you a hash with the id value as the text string value last_name and a name value as the same.
Hope that helps!
You shouldn't need to setup aliases in the finder SQL just to populate a drop-down. Instead simply use the last_name value for the value attribute (as well as the display text).
Eg if you're using the collection_select helper:
<%= f.collection_select :attribute_id, #collection, :last_name, :last_name %>