Rails, Mongoid: use custom key and custom key format - ruby-on-rails

I have model Account:
class Account
include Mongoid::Document
include Mongoid::Timestamps
...
end
I want to use specific ids with specific format. I want id to be 16-digits instead of 4ceede9b5e6f991aef000007, something like that: 1111222233334444.
What is the best practice to do it?

If the id is a simple number, try:
class Account
include Mongoid::Document
include Mongoid::Timestamps
identity :type => Integer
end
account = Account.new :id => 1111222233334444
#=> #<Account _id: 1111222233334444, created_at: nil, updated_at: nil>
account.save
#=> true
account
#=> #<Account _id: 1111222233334444, created_at: 2010-11-26 00:48:27 UTC, updated_at: 2010-11-26 00:48:27 UTC>
Account.count
#=> 1
Account.first
#=> #<Account _id: 1111222233334444, created_at: 2010-11-26 00:48:27 UTC, updated_at: 2010-11-26 00:48:27 UTC>
If you want to use letters in the id too, you can do identity :type => String instead.

Related

Load related model in rails 7

I'm new in ruby rails and face some difficult to achieve something.
Now I have a product model:
class Product < ApplicationRecord
belongs_to :category
And category model:
class Category < ApplicationRecord
has_many :products
When I call the product like so: #products.inspect i wan to see the category belongs to the product. My output now looks like so:
<ActiveRecord::Relation [#<Product id: 1, name: "Adidas", description: "Adidas is a Dutch multinational corporation that i...", price: 100, created_at: "2022-08-23 10:02:11.110159000 +0000", updated_at: "2022-08-23 10:02:11.114384000 +0000", category_id: 1>, #<Product id: 2, name: "asd", description: "12easd", price: 12, created_at: "2022-08-24 09:35:38.839809000 +0000", updated_at: "2022-08-24 09:35:38.847999000 +0000", category_id: 1>]>
Getting the product.category working fine, but, I need also the name of the category attached to this output. I need this because the product is sent to a JavaScript function and I need to call the category name from there.
What I already try is the follow:
def index
#products = Product.includes(:category).all
end
Thanks in advance.
I found it!
#product.to_json(include: :category)
And now I get the related category model

Rails creates many objects for has_one relationship

I've got two models in my Rails 5 app - User and Login with below association:
class User < ApplicationRecord
belongs_to :login, optional: true
end
class Login < ApplicationRecord
has_one :user
end
I thought such an association would prevent the Login from having more than one User but it turns out that in a case when the Login.last already has associated user object:
2.4.5 :108 > Login.last.user
=> #<User id: 1, type: "Registrant", login_id: 43, first_name: "test", last_name: "test", created_at: "2022-02-11 11:22:25", updated_at: "2022-02-11 11:22:25">
You can still create a new user with the same Login:
User.create(first_name: 'test2', last_name: 'test2', login_id: 43
=> #<User id: 2, login_id: 43, first_name: "test2", last_name: "test2", created_at: "2022-02-11 12:03:36", updated_at: "2022-02-11 12:03:36">
But when you are trying to fetch last login user you will get the first created user:
Login.last.user
=> #<User id: 1, type: "Registrant", login_id: 43, first_name: "test", last_name: "test", created_at: "2022-02-11 11:22:25", updated_at: "2022-02-11 11:22:25">
How to prevent creating a new user with a login that has already been used once?
You can use validation to say that a login just can be use by one user.
This will look like this in model User:
validates :login_id, uniqueness: true

rails check_box_tag to include existing values of from array of records

The following tag in a nested form
<%= check_box_tag "friend_ids[]", ff.id, #contentrestrictions.friends.include?(ff.id) %>
is handling the following array of records
>> #contentrestrictions
[
#<Contentrestriction id: 29, usercontent_id: nil, friend_id: nil, created_at: "2019-04-28 10:55:32", updated_at: "2019-04-28 10:55:32">,
#<Contentrestriction id: 30, usercontent_id: nil, friend_id: 2, created_at: "2019-04-28 10:55:32", updated_at: "2019-04-28 10:55:32">,
#<Contentrestriction id: 31, usercontent_id: nil, friend_id: 4, created_at: "2019-04-28 10:55:32", updated_at: "2019-04-28 10:55:32">]
Even though
class Contentrestriction < ApplicationRecord
belongs_to :friend, optional: true
#contentrestrictions. followed by any of friend_id, friend_ids both appended with or without [] all lead to NoMethodError: undefined method for Array.
how can this include function get a proper array to work with?
the issue is in this line:
#contentrestrictions.friends.include?(ff.id)
you are comparing a friend object with a friend id, you could use pluck to get the friend ids, or you could just compare the objects:
#contentrestrictions.friends.include?(ff)
this will make a query for the .friends and you could remove this query by pre-loading the friends association, e.g. eager_load(:friends) or includes(:friends)

Rails - how to automatically uniq joins method?

This question is based on this: Rails, why joins returns array with non-uniq values?
Let say I get non uniq array by .joins() method:
City.joins(:locations)
# => [#<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">, #<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">, #<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">, #<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">]
I can make records uniq by using
City.joins(:locations).group('cities.id') # or simpler
City.joins(:locations).uniq
# => [#<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">]
How can I make .joins() method returns uniq records by default?
You could try overriding the .joins method for the models you need, but I would suggest just writing a scope, e.g.
scope :unique_locations, -> { joins(:locations).uniq }
Then just call City.unique_locations. It's cleaner and more readable that way.
Generally overwriting methods should be done only when you're sure you won't need it 'the old way', and it makes sense. Plus, when you say City.joins(:locations) the reader expects default behaviour, and returning something else will cause chaos and confusion.
You can define has_many macro, with the stubby lambda as an argument:
has_many :locations, -> { joins(:locations).uniq }
Also you can define own AR relation method, it stil use a simple has_many macro.
has_many :locations do
def only_uniq
joins(:locations).uniq
end
end
Now use it:
c = City.find(123)
c.locations.only_uniq
It does the same thing as scope or lambda in has_many.

object with latest date mongoid

I have 2 objects with created_at attribute.
I want to know the query with Which of these two objects is the most recent date
object 1:
#<User _id: 504726081d41c809e5000003, _type: "User", created_at: 2012-09-05 10:14:33 UTC >
object 2:
#<User _id: 503fb40f1d41c8255a000007, _type: "User", created_at: 2012-08-30 18:42:24 UTC >
Edited
This 2 object are inside array: something like:
[#<User _id: 504726081d41c809e5000003, _type: "User", created_at: 2012-09-05 10:14:33>, #<User _id: 503fb40f1d41c8255a000007, _type: "User", created_at: 2012-08-30 18:42:24>]
I can not use .last. I need use lastest date.
Thank you very much
I'd say:
User.order_by([:created_at, :desc]).limit(1).first #useful to include other ordering conditions
Or:
User.desc(:created_at).limit(1).first
Since your edit:
array.max_by{|u| u.created_at}

Resources