seeding user meal booking table - ruby-on-rails

Seeding Database tables Seeding user data.... Seeding meals data .... Seeding user meal booking data .... rails aborted! NoMethodError: undefined method UserMealBooking' for nil:NilClass
assuming the user's email address is "user#example.com"
meals = Meal.all
user = User.find_by(email_address`your text`: "user#example.com")
userbooking1 = user.UserMealBooking.create!(meal_id: meals.first.id, booking_type: "online", booking_date: "2023-05-12T10:00")
i want when a user books a meal their id can be shown or email
`your text``

You can't call a class from an object, this doesn't seem right user.UserMealBooking
I assume UserMealBooking it is the model between the user and the meal
so there multiple ways of creating the association, one of them is
meals = Meal.all
user = User.find_by(email_address`your text`: "user#example.com")
userbooking1 = UserMealBooking.create!(meal_id: meals.first.id, user_id: user.id, booking_type: "online", booking_date: "2023-05-12T10:00")
Make sure there are meals and a user with a specific email in your database

I assume your User model has a has_many association with the UserMealBooking model. In that case, you can modify your code like below:
meals = Meal.all
user = User.find_by(email_address`your text`: "user#example.com")
userbooking1 = user.user_meal_bookings.create!(meal_id: meals.first.id, booking_type: "online", booking_date: "2023-05-12T10:00")

Related

ActiveRecord - How to associate (unsaved) child of (unsaved) parent with another object before saving all objects

i'm relatively new to Rails and Ruby and run into the following question.
I have a 3 objects:
Parent object called Partner
Has many Tariffs
object called Tariff
Belongs to Partner
a 3rd object what has a has one relation with the child object called User
Belongs to Tariff
When i create a new Partner (partner = Partner.new) and a new tariff (tariff = Tariff.new) and add the tariff to the partner (Partner.tariffs << tariff) i'm able to save the Partner with it relation by doing partner.save!.
But in my situation i also get a user from the database (user = User.find.last) and want to directly add the association with the tariff before i save everything to the database. This because i want to save/update everything in 1 transaction so everything will be role backed in case of an error.
I tried many ways to achieve this but i cant get it done. I thought it would be something like this:
partner = Partner.new
tariff = Tariff.new
partner.tariffs << tariff
user = User.find.last
user.tariff = tariff
ActiveRecord::Base.transaction.do
partner.save!
user.save!
end
or
partner = Partner.new
tariff = Tariff.new
partner.tariffs << tariff
user = User.find.last
user.tariff = tariff
ActiveRecord::Base.transaction.do
partner.save!
user.save!
end
or
partner = Partner.new
tariff = Tariff.new
partner.tariffs << tariff
user = User.find.last
user.tariff_id = tariff.id (or something similar)
ActiveRecord::Base.transaction.do
partner.save!
user.save!
end
I understand that some of my cases/examples cant work as there is no tariff.id and there is no partner.tariff.last as long as the objects are not saved to the database.
It would be nice if someone can help me out, thanks in advance!
I solved my problem like this:
partner = Partner.new
tariff = Tariff.new
partner.tariffs << tariff
ActiveRecord::Base.transaction.do
partner.save!
user.update_attributes(:tariff_id => tariff.id)
end
This works because the tariff object has an idea after the save method is called. The tariff is also saved when the partner is saved as the child is an new object and first level child of the partner. Unfortunately children of the child are not saved automatically.

rails update field based on find in another table

I have a User model (has_many contacts) and a Contact model (belongs_to user). To send invites, I need to know if a user's contacts already exist in User table and update a status field in Contacts. My common field is phone number.
So oversimplifying I have:
User: id, phone
Contact: id, name, phone, status, user_id
How can I set status to "registered" for a user's contacts in an efficient manner?
I currently have this iteration, which works, but there has to be a better way:
all_contacts = Contact.where(user_id: user).where.not(phone: nil)
all_contacts.each do |contact|
a = User.find_by(phone: contact.phone)
if a
contact.status = 'registered'
contact.save
end
end
You can try following:
contacts = Contact.joins(:user).where("users.phone=contacts.phone and contacts.phone not NULL")
contact_ids = fetch ids from contacts array
Contact.update(your_array_of_ids, status: "registered")
If you want to update status of User to "registered" only if they have a phone number, then you could store their ids in an array(using where for example , and then you could use the update method like this:
User.update(your_array_of_ids, status: "registered")

Rails create multiple records at once from nested attributes on a different model

In my app I have model PurchaseOrder and PurchaseOrderList. When I create a purchase order it updates both tables purchase_orders and purchase_order_lists with a nested form.
Now I want to be able to add a button update stock on purchase_orders/show. When I click this button a new record will be created on table stockdiaries with same products, units and prices as on the purchase order.
The logic is that first I create a purchase order and then I click the button to update stock when goods are received.
The best I came up with is to create this method on PurchaseOrders controller:
def update_stock
#purchase_order_list = PurchaseOrderList.where(PURCHASE_ORDER: params[:ID])
#stockdiary = Stockdiary.create(PRODUCT: #purchase_order_list.PRODUCT, UNITS: #purchase_order_list.UNITS, PRICEBUY: #purchase_order_list.PRICEBUY)
flash[:notice] = "Stock updated successfully."
redirect_to(:action => 'show', :ID => #purchase_order.ID)
end
and in my purchase_orders/show:
<%= link_to "Update Stock", { controller: :purchase_orders, action: :update_stock, ID: #purchase_order.ID} %>
but it raises error
undefined method `PRODUCT' for
#<PurchaseOrderList::ActiveRecord_Relation:0x007f1efeff4898>
But there is a column PRODUCT on purchase_order_lists table.
Note that I included in the method only columns that are common to purchase_order_lists and stockdiaries as others (as id or status) are not concerned on this question. Columns names are capital as I'm building the app on existing db.
What is the correct way to create a stockdiary from a purchase order?
Updated
Rails is returning an an ActiveRecord Relation from this query:
#purchase_order_list = PurchaseOrderList.where(PURCHASE_ORDER: params[:ID])
This is because you used where, so ActiveRecord returns a relation that could potentially have multiple records in it. If you only want one record, or even if you know that there will only be one record then you should use find_by
So you can either do:
# change where to find_by
#purchase_order_list = PurchaseOrderList.find_by(PURCHASE_ORDER: params[:ID])
# and then this will work
#stockdiary = Stockdiary.create(PRODUCT: #purchase_order_list.PRODUCT, UNITS: #purchase_order_list.UNITS, PRICEBUY: #purchase_order_list.PRICEBUY)
OR... If you want where or there might be multiple records, then you can loop:
#purchase_order_list = PurchaseOrderList.where(PURCHASE_ORDER: params[:ID])
# and then loop through you potentially multiple records in #purchase_order_list
#purchase_order_list.each do |po|
#stockdiary = Stockdiary.create(PRODUCT: po.PRODUCT, UNITS: po.UNITS, PRICEBUY: po.PRICEBUY)
end
or use first:
#stockdiary = Stockdiary.create(PRODUCT: #purchase_order_list.first.PRODUCT, UNITS: #purchase_order_list.first.UNITS, PRICEBUY: #purchase_order_list.first.PRICEBUY)
Usually this means you didn't place accepts_nested_attributes_for in the PurchaseOrder model.
PurchaseOrder
class PurchaseOrder
accepts_nested_attributes_for :purchase_order_list
end

Rails find_or_initialize_by with joins ActiveRecord::AssociationTypeMismatch

I have two models
users (id, name, ...)
authorizations (id, provider, provider_uid, user_id,...)
users has_many authorizations
Now when i have to login via facebook i need to check if the provider_uid is preset if not create a new one.
user = User.joins(:authorizations).find_or_initialize_by(
authorizations: {
provider: 'facebook',
provider_uid: provider_uid
}
)
Error
ActiveRecord::AssociationTypeMismatch - Authorization(#70336918074440)
expected, got Array(#70336893054160):
Try using first_or_initialize instead, both the scenarios are covered below
You can try this if you want to initialize a user object
user = User.joins(:authorizations).where("authorizations.provider = 'facebook' AND authorizations.provider_uid = ?", provider_uid).first_or_initialize
But, if you want to find or create authorization for an existing user, you can do this, you can use first_or_initialize
authorization = Authorization.where(user_id: user_id, provider: 'facebook', provider_uid: provider_uid).first_or_initialize
authorization.save if authorization.new_record?
Hope this helps!

How do I assign a User_ID to the seed

I'm trying to assign random user_id's to products that are generated from the seeds database. Everything is generating for me as I want it except for the user_id which is rendering nil. I'm trying to get a better understanding of how the belongs_to interaction works - any help here would be awesome!
10.times do |n|
name = Faker::Name.name
job = Faker::Company.name
User.create!(name: name,
job: job )
end
10.times do |n|
users = User.all
name = "Turkey"
price = Random.rand(42-10) + 10
user_id = users[1..10]
Product.create!(name: name,
price: price,
user_id: user_id)
end
Thanks in advance for the help!
Edit ** Thanks for the help everyone. This is what I ended up changing the code to.
users = User.order(:created_at).take(6)
10.times do |n|
name = "Turkey"
price = Random.rand(42-10) + 10
users.each { |user| user.products.create!(name: name, price: price)}
end
I'm not 100% what you're asking in terms of assigning a random user id to the product. From your comment on #tadman answer it seems you just want a product to belong to each one of the users. Why not just do something like this:
10.times do |n|
name = Faker::Name.name
job = Faker::Company.name
User.create!(name: name, job: job)
end
User.all.each do |user|
name = "Turkey"
price = Random.rand(42-10) + 10
user.products.create!(name: name, price: price)
end
Assuming your User model has many products and a product belongs to a User that should get your desired outcome.
user.products will automatically assign the user.id to the user_id field to the product record when sending build or create
You probably mean this:
user_id = users.last.id
Or possibly:
user_id = users.shuffle.last.id
I'm not sure what your range notation 1..10 is intending. Arrays are 0-indexed.
User id will automatically get generated for each new user in sequential order. There is no need to have the "user_id" field there.
Like Mukul215 said the ID will be generated automatically in sequential order. It is BAD practice to hard code ID's in the seed.

Resources