access to record params with ActiveRecord relation number - ruby-on-rails

I'm trying to get a record in DB by having these two lines in one of my models:
a = Arel::Table.new(:receivers)
e = Receiver.where(a[:name].matches('%afsane%'))
In my receivers table I have a row in which the name column equals to "afsane".I want to have that row's id in my model.
but by printing the e in my model I've got this :
"========#<Receiver::ActiveRecord_Relation:0x0056094261eff8>============"
which gives the relation number but no params.
When I run them in rails console I got this response:
#<ActiveRecord::Relation [#<Receiver id: 2, name: "afsane", created_at: "2016-09-27 09:24:16", updated_at: "2016-10-09 10:10:02">]>
I managed to have this in my model But I couldn't .
ps:Using Rails 5.
Have any Ideas ?

I'm not sure what the variable a looks like but the variable e is a collection.
where returns a collection which means you will have to iterate through e in order to pull out some data.
Like so:
e.each do |data|
data.name
end
If you want to return only 1 result then you can simply do the following:
e = Receiver.where(a[:name].matches('%afsane%')).limit(1)
Note: I've kept the answer simple but there are more elegant solutions to this so I recommend you reading the ActiveRecord Rails Guides

Related

Rails 6 get the difference of the 2 timestamp and assigned to one new field in query

I am working on the rails 6 application with postgresql database, where I have to count to the time of the call.
I have 2 fields in my database one is answered_at(timestamp) and another is end_at(timestamp)
I use the following query, and in that query, I need the difference of (end_at - answered_at) and access in call_duration field
So I can access the call_duration field by attr_accessor but I do not know how to get the difference and set it into the query.
My original query is
#in_app_calls = InAppCall.where("caller_user_id =? OR receiver_user_id =?", chat_user&.first&.id, chat_user&.first&.id)
.group_by(&:call_type) unless chat_user.nil?
following is my database record
<InAppCall id: 1, caller_user_id: 10, receiver_user_id: 61, call_type: "audio", call_answered: true, answered_at: "2020-07-16 04:24:17", end_at: nil, created_at: "2020-07-08 09:58:36", updated_at: "2020-07-16 04:24:17", on_going_updated_at: nil>
I may get nil value in answered_at(timestamp) or end_at(timestamp) field, in that case, I will not consider that record.
Can anyone help me with the query?
An elegant way to do this is to use virtual attributes that ActiveRecord basically creates on the fly for you when you modify the select list. You can do it like so:
user_id = chat_user&.first&.id
#in_app_calls = InAppCall.
select("in_all_calls.*, EXTRACT(EPOCH FROM end_at - answered_at)::int AS call_duration").
where("caller_user_id = :user_id OR receiver_user_id = :user_id", user_id: user_id).
where.not(answered_at: nil, end_at: nil).
group_by(&:call_type) if user_id.present?
Note the additional field that I'm creating with AS call_duration => ActiveRecord simply turns this into an attr_reader on the model, so you can do #in_app_calls[0].call_duration and such things like you would with any regular column.
I also took the liberty of cleaning up your handling of the user_id – I hope it's correct this way, otherwise you should have no trouble reverting this bit back to your original.

ruby map find_each can't add to array

I have 2 Models: Document and Keywords. They are habtm in relation to each other and they both accepts_nested_attributes_for each other so I can create a nested form. That works well.
So in params, I have
"document"=>{"book_id"=>"1", "keywords"=>{"keywords"=>"term, administration, witness "}, ...
In the controller I put the keywords in a separate array like this :
q = params[:document][:keywords].fetch(:keywords).split(",")
This works well too.
What I now need to do, is get the keywords ids and put them in an array. Each element of that array will populate the join table.
I've tried this :
a = Array.new
q.each do |var|
id = Keyword.select(:id).find_by keyword: var
a << id
id
end
But, this only answers [#<Keyword id: 496>, nil, nil], although the server log shows that all 3 SQL requests are executed and they are correct.
I have also tried this :
a = Array.new
q.map do |e|
Keyword.where(motcle: e).select(:id).find_each do |wrd|
a << wrd.id
end
end
Then again, this only return the FIRST id of the keyword, although the server log shows that all 3 SQL requests are executed.
What I'm trying to get is a = [496, 367, 2398]
So I have 2 questions :
1/ Why are the ids not added to the array, despite the server executing all SQL requests ?
2/ How to write in rails a request would be
SELECT "motclefs"."id" FROM "motclefs" WHERE "motclefs"."motcle" in ('déchéances','comtesse') ORDER BY "motclefs"."id";
Thanks !
The returned value is an object of Keyword. You need to get the id attribute of the object. eg:
id = Keyword.where(keyword: var).select(:id).first.id
A better way to get all the ids would be
a = Keyword.where(keyword: ['term', 'administration', 'witness']).pluck(:id)
# I think this might answer your second question.

Column with hash value is now a string after aliasing

I have a psql table with a column named params that contains a hash. Below is my scenario:
When I do the following query...
game = Game.select('games.params').where(id: 123).first
... it prints out...
p game.params.class # => !ruby/class 'ActiveSupport::HashWithIndifferentAccess
Now I can go ahead an access values inside the returned hash normally.
But when I give the column name an alias in my query (here is my problem)...
game = Game.select('games.params as parameters').where(id: 123).first
... it prints out...
p game.parameters.class # => !ruby/class 'String'
I need to be able to change the column name in my query and then access the values inside the hash, but when I try to do p game[:time] it's being treated as a string.
I'm new to Ruby and Ruby on Rails, so this might be very simple to figure out but I am at a dead end right now.
What about this query:
g = Game.find 123
g.params

ruby hash with database

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.

Rails returns a nil, when searching with find_by

I'm beginning to learn RoR, but i've a problem which i don't understand. With Product.find :all returns all the records from DB. But if i want to find_by_gender(1) (or even 2) it returns a nil, i'm certain that the db contains products with a gender
My code controller:
gender = params[:gender].to_i
#search_results = Product.find_by_gender(gender)
this returns a nill,
What am i doing wrong?
Greetings!
find_by_... returns either first record or nil if none found, find_all_by_... returns all records that match (or empty array if none). In your case nil means no records found with gender = 1.
Verify your data first!
Look at some sample records:
Do something like:
Product.all(:limit => 5).each {|product| product.id.to_s + product.gender}
or go into sql
sql> select id, gender from products where id < 6;
If you are to verify what the gender values are you can then create named scopes in your model for those conditions, e.g. (rails3)
(Product Model - app/models/product.rb)
scope :male where(:gender) = male_value # i.e. 1 or 'M' or 'Male' or whatever
scope :female where(:gender) = female_value # i.e. '2' or 'F' or whatever
Which will then you let write Products.male or Products.female !
Final note - should gender be in your users table? , or is this for male / female specific products?
in rails console execute
Product.pluck(:gender)
And u will know that values does it have in AR(i think true and false), so u have to use query Product.find_by_gender(true)

Resources