I am returning a params hash in a controller.
params[:questions] = {"ad6d1d19-f95b-228c-8a19-49150ad15f23"=>"answer21", "90783719-9cd6-23de-f3fb-9bc80e7a72a0"=>"answer22"}
With multiple key value pairs.
I have model Model1. This has a json column called answers.
Every time a params[:questions] is returned. I'm trying a create a Model1 object as follows:
Model1.create(answers: {q_id: the_id, ans: the_answer})
How can I create multiple key value pair answers column? If I iterate through the params[:questions] and create an object, it will create a new object for every pair. So that's not a solution.
Would this work?
m = Model1.new
params[:questions].each do |id, answer|
m.answers << {q_id: id, ans: answer}
end
m.save!
or maybe
hash = {}
params[:questions].each do |id, answer|
hash << {q_id: id, ans: answer}
end
Model1.create(answers: hash
)
Related
Ok, so 8 months into Ruby Hashes are still proving somewhat of an enigma.
I pull 10 records from the database, each with its own category field. Many of the records with share the same category, so I want them grouped by their categories in a hash.
I understand that the Key's are always unique, which is what makes a Hash a Hash. What I am struggling to do is add values to the existing key in the hash.
def self.categorise_events
hash = {}
self.limit(10).map do |event|
if hash.key?(event.event_type) #check if the key already exists
hash[event.event_type][event] #add the event record to that key
else
hash[event.event_type] = event #create the key if it doesn't exist and add the record
end
end
hash
end
This is more of a gist of what I am trying to achieve. I've had other compositions which have been closer but still not quite doing it.
You can add to an existing hash like
hash[key] = value
but in your case, your value is a collection of values, so it's an array
hash[key] = []
hash[key] << value
so you can add to an existing group with
unless hash.key?(event.event_type)
hash[event.event_type] = []
end
hash[event.event_type] << event
Now, this can be accomplished with the builtin method #group_by as seen on the documentations. But in your case, because it's using ActiveRecord, you can consider using #group to group records using SQL and greatly improving the performance of the grouping
self.limit(10).group(:event_type)
Check out the docs here.
Key is always uniq. So if you want to add values to a key, that value should be Array.
In this situation you can use group_by. Try
hash = self.limit(10).group_by{|e| e.event_type}
It returns a Hash whose keys are event_type and values are Array of records.
I would like to sort objects, but i want this sorting to not be based on the direct value i have stored in the database.
In the database there are integer values, 1,2,3... but there is also a hash, that specifies, what those values mean.
{1 => "a", 2 => "za", 3 => "xa"}.
So if an instance has value 3, it should be sorted as "xa". Can I achieve this goal with order() method? It is important to not use arrays, but rather ActiveRecord Relations
For the making of a temp_table and populate it with the values of your hash, this should work.
sqlQuery1 = ActiveRecord::Base.connection.execute("CREATE TEMP TABLE IF NOT EXISTS hash_tmp(id integer, hash_values integer)")
sqlQuery2 = ActiveRecord::Base.connection.execute(TRUNCATE hash_tmp)
Your_hash.each do |id, value|
sqlQuery3 = ActiveRecord::Base.connection.execute("INSERT INTO hash_tmp(id, hash_values) VALUES (#{id}, '#{value}')")
end
You should have a model for that temp table you created, then you can get all the values (filtered or not) and order by the new field:
#YourTemp = Yourtemp_model.all(:order=> "hash_values")
This is assuming that to this point your hash holds all the possible values which means you can iterate it and populate your temp table with them.
I am trying to understand this line of code:
#rating = Rating.where(review_id: #review.id, user_id: #current_user.id).first
The line of code comes from a Ruby on Rails app that has a user, review, and rating model. Here is what I understand so far:
#rating is a variable
Rating.where().first is a method
review_id: #review.id + user_id: #current_user.id are parameters- and are an implicit hash key/value pair
How does review_id: #review.id or user_id: #current_user.id work with the database?
Update question: Sorry I'm still confused. How does #review.id or #current_user.id point to anything in the database? I have nothing in my database starting with the # symbol
You have 2 fields: "review_id", "user_id" in table "ratings".
Symbol # - means that is instance variable and it is available not only in the controller
variable structure example:
#current_user = {
id: 1,
name: "Jhon",
last_name: "Wayne"
}
this means that #current_user.id = 1
user_id: #current_user.id
And query search 1 in table ratings field user_id
If you know database SQL queries then
Rating.where(review_id: #review.id, user_id: #current_user.id)
is equivalent to
SELECT * from ratings where review_id = #review.id AND user_id = #current_user.id;
#rating is not just a variable , its a instance variable
Rating.where() will return an array of ratings. and Rating.where().first will return first record of the array
Rating.where provides ActiveRecord::Relation object, which knows about conditions on review_id and user_id. When you call first for the object -- it executes sql query, and appends LIMIT 1 condition.
SELECT ratings.* FROM ratings WHERE ratings.review_id = 11 AND ratings.user_id = 12 LIMIT 1
The ORM converts the response from the database to the ruby object. Which you place in the instance variable #rating, probably in a controller. This variable will be accessible in the view.
When you provide a hash in where clause it means then key of hash is field name and value of that key is value in database
This line selects all the ratings which belong to a review with id #review.id and belong to the currently logged-in user with id #current_user.id.
The SQL version of this will look something like this:
query = "SELECT * FROM ratings WHERE review_id = #{#review.id} AND user_id = #{#current_user.id}"
EDIT: In the hash, every key refers to the column name in the table and the corresponding value is what you are searching for in that column. That value is given by what is stored in the instance variable.
I am getting collection of ids [1,2,3,4] in the params and I make a call to an API that will return the array for the corresponding ids. E.g. ["Apple","Orange","Mango"]. How can I update this in my database for the corresponding ids?
For example: the ids which are mentioned above are from my user table. ids = [1,2,3,4], which are primary keys in my user table.
From the API response I got an array of fruit_names for the correlated user_ids. E.g.: ids = [1,2,3,4] and fruit_names = ["a","b","c","d"], where the fruit_name column exists in my user table. How do I update fruit_name from the API response correlated ids in my user table?
You can use each_with_index in combination with update for this:
ids.each_with_index do |id, index|
User.update(id, :fruit_name, fruit_names[index])
end
The above code assumes:
ids = [1,2,3,4]
fruit_names = ["a","b","c","d"]
and that the indexes of those arrays match.
Note that this will execute a query for each item in your ids array. If your ids array is very big this is not going to perform well.
Hash[ids.zip fruit_names].each do |id, fruit|
User.update_all({:fruit_name => fruit}, {:id => id})
end
OR
User.where(:id => ids).each do |usr|
usr.update_attribute(:fruit_name, fruit_names[ids.index(usr.id)])
end
using Rails 3.2, there is a way to find out if a column is a reference column to other model?
I don't want to rely in "_id" string search in the name.
thanks.
UPDATE:
I need to iterate over all columns and made a special treatment in references columns, something like:
result = Hash.new
self.attribute_names.each do |name|
if self[name]
result[name] = self[name]
if name is reference column
insert xxx_description (from the other model) in hash.
end
end
end
I will return this hash as json to client.
{name: 'joseph', sector_id: 2, sector_name: 'backend'...}
Where sector_name, is person.sector.name...
thanks.
alternative method if you don't know the name of the association :
Post.reflect_on_all_associations(:belongs_to).map &:foreign_key
# => ['author_id','category_id']
See http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html
Post.reflections[:comments].primary_key_name # => "message_id"
How to get activerecord associations via reflection