Seeding with has_one relationship, Ruby on Rails (edited) - ruby-on-rails

I try to seed data for my app. I managed to do this, but the code is ugly, and it possibly can be a lot easier. I;m a complete beginner so I would be grateful for any help. I had to create one profile and one todolist for each user, and 5 todoitems for each todolist.
user1 = User.create!( username: "Fiorina", password_digest: "123456")
profile1 = user1.create_profile(gender: "female", first_name: "Carly", last_name: "Fiorina", birth_year: 1954)
todolist1 = user1.todo_lists.create(list_name:"List1", list_due_date:Date.today + 1.year)
user2 = User.create!( username: "Trump", password_digest: "123456")
profile2 = user2.create_profile( gender: "male", first_name: "Donald", last_name: "Trump", birth_year: 1946)
todolist2 = user2.todo_lists.create(list_name:"List2", list_due_date:Date.today + 1.year)
user3 = User.create!( username: "Carson", password_digest: "123456")
profile3 = user3.create_profile( gender: "male", first_name: "Ben", last_name: "Carson", birth_year: 1951)
todolist3 = user3.todo_lists.create(list_name:"List3", list_due_date:Date.today + 1.year)
user4 = User.create!( username: "Clinton", password_digest: "123456")
profile4 = user4.create_profile( gender: "female", first_name: "Hillary", last_name: "Clinton", birth_year: 1947)
todolist4 = user4.todo_lists.create(list_name:"List4", list_due_date:Date.today + 1.year)
for i in 0..4
todolist1.todo_items.create(due_date: Date.today + 1.year, title: "TodoItem1", description: "Opis", completed: 1)
end
for i in 0..4
todolist2.todo_items.create(due_date: Date.today + 1.year, title: "TodoItem2", description: "Opis", completed: 1)
end
for i in 0..4
todolist3.todo_items.create(due_date: Date.today + 1.year, title: "TodoItem3", description: "Opis", completed: 1)
end
for i in 0..4
todolist4.todo_items.create(due_date: Date.today + 1.year, title: "TodoItem4", description: "Opis", completed: 1)
end

DRY it (don't repeat yourself):
[
{last_name:'Fiorina', first_name:'Carly', gender:'female', birth_year:1954},
{last_name:'Trump', first_name:'Donald', gender:'male', birth_year:1946},
{last_name:'Carson', first_name:'Ben', gender:'male', birth_year:1951},
{last_name:'Clinton', first_name:'Hillary', gender:'female', birth_year:1947},
].each_with_index do |p, index|
user = User.create!( username: p[:last_name], password_digest: "123456")
profile = user.create_profile(p) # note that p only has fields for profile attributes
todolist = user.create_todo_list(list_name:"List#{index+1}", list_due_date:Date.today + 1.year)
5.times.each{|i|
todolist.create_todo_item(due_date: Date.today + 1.year, title: "TodoItem#{i+1}", description: "Opis", completed: 1)
}
end

Hey you can build_profile for has_one relation ship and used todo_lists.build for has_many try this way
User.create!( username: "Fiorina", password_digest: "123456").build_profile(gender: "female", first_name: "Carly", last_name: "Fiorina", birth_year: 1954).save!
for has_many relation ship
User.create!( username: "Fiorina", password_digest: "123456").todo_lists.build().save!

Related

ActiveRecord::AssociationTypeMismatch: User(#35560) expected, got ... which is an instance of User(#22700)

I've been getting intermittent errors while seeding with rails. I'm hoping someone can help provide some insight into the different types of the User class.
The error in full:
ActiveRecord::AssociationTypeMismatch: User(#35560) expected, got #<User id: "bedc7c4e-cdd2-4ea1-a7ee-4e6642467fba", email: "phil#email.domain", jti: "7376cf41-7f88-407d-8365-1e311d946b88", ios_device_token: nil, fcm_device_token: nil, first_name: "Phil", last_name: "6", phone_number: nil, date_of_birth: nil, super_user: true, created_at: "2023-02-08 08:16:37.559974000 +0000", updated_at: "2023-02-08 08:16:37.559974000 +0000"> which is an instance of User(#22700)
The code which causes it:
user = User.new(
first_name: 'Phil',
last_name: '6',
email: 'phil#email.domain',
super_user: true,
password: 'test1234'
)
user.skip_confirmation!
user.save!
organisation = Organisation.find_by_name('Team')
Membership.create!(
user:,
organisation:,
verified: true,
verified_at: now,
organisation_admin: true,
shift_admin: true,
email: 'phil.6#group.com',
email_confirmed: true,
category: organisation.categories.find_by_name('Developer')
)
organisation = Organisation.find_by_name('Test Org')
membership = Membership.create!(
user:,
organisation:,
verified: true,
verified_at: now,
email: 'phil#testorg.com',
email_confirmed: true
)
If I pause execution before the error I can see that user == User.first is false despite User.first and user being these two lines, which are visually identical:
#<User id: "6ce62b08-cf4c-4bfa-878a-02a1ed889c69", email: "phil#email.domain", jti: "710948b6-5f4f-40ea-ab9f-df8e3b1219c3", ios_device_token: nil, fcm_device_token: nil, first_name: "Phil", last_name: "6", phone_number: nil, date_of_birth: nil, super_user: true, created_at: "2023-02-08 08:17:06.024800000 +0000", updated_at: "2023-02-08 08:17:06.024800000 +0000">
#<User id: "6ce62b08-cf4c-4bfa-878a-02a1ed889c69", email: "phil#email.domain", jti: "710948b6-5f4f-40ea-ab9f-df8e3b1219c3", ios_device_token: nil, fcm_device_token: nil, first_name: "Phil", last_name: "6", phone_number: nil, date_of_birth: nil, super_user: true, created_at: "2023-02-08 08:17:06.024800000 +0000", updated_at: "2023-02-08 08:17:06.024800000 +0000">
It's the same thing if I compare user.class and User.first.class, they look the same but a comparison evaluates to false.
Am I doing something to mutate the local variable?
What you should be doing here is to create an assocation:
class User < ApplicationRecord
has_many :memberships
end
Then you create the memberships through that assocation instead:
user = User.create!(
first_name: 'Phil',
last_name: '6',
email: 'phil#email.domain',
super_user: true,
password: 'test1234',
confirmed_at: Time.current # the easy way to skip Devise::Confirmable
)
# make sure you use the bang method so that you're not just getting a nil
organisation = Organisation.find_by_name!('Test Org')
user.memberships.create!(
organisation: organisation,
verified: true,
verified_at: now,
organisation_admin: true,
shift_admin: true,
email: 'phil.6#group.com',
email_confirmed: true,
category: organisation.categories.find_by_name!('Developer')
)

How to repeat single hash multiple times in one array?

I want to create dozens of logins that rely on data from this array, logins:
logins = [
{
email: Faker::Internet.email,
password: "password",
first_name: Faker::Name.first_name,
last_name: Faker::Name.last_name
},
{
email: Faker::Internet.email,
password: "password",
first_name: Faker::Name.first_name,
last_name: Faker::Name.last_name
}
]
What is a better way of writing this array rather than copy and pasting that hash dozens of times? I am familiar with x.times do but that wouldn't work on an array.
Here's the code where I pass in the logins:
logins.each do |login|
li = LoginInformation.new(login: login[:email], password: login[:password])
if UserManager.save(li)
company_ids.each do |id|
li.contacts.create(first_name: login[:first_name], last_name: login[:last_name], email_address: login[:email], company_id: id, is_employee: true)
end
end
end
One way to simplify the creation of your logins array is to pass the hash object with the included Faker methods as a block, like so:
logins = Array.new(10) { { email: Faker::Internet.email, password: 'password', first_name: Faker::Name.first_name, last_name: Faker::Name.last_name } }
You can replace the 10 in this example with the number of elements required for your use case.
Hope this helps!
.times returns an enumerator that you can call .map on to get an array.
logins = 10.times.map do
{
email: Faker::Internet.email,
password: "password",
first_name: Faker::Name.first_name,
last_name: Faker::Name.last_name
}
end
Or use Array.new as mentioned by Zoran Pesic.
You can use for loop to insert the values multiple times
logins=[]
for i in 0..10
logins <<
{
email: Faker::Internet.email,
password: "password",
first_name: Faker::Name.first_name,
last_name: Faker::Name.last_name
}
end
Can do this way also:
10.times do
login = { email: Faker::Internet.email, password: 'password', first_name: Faker::Name.first_name, last_name: Faker::Name.last_name }
li = LoginInformation.new(login: login[:email], password: login[:password])
if UserManager.save(li)
company_ids.each do |id|
li.contacts.create(first_name: login[:first_name], last_name: login[:last_name], email_address: login[:email], company_id: id, is_employee: true)
end
end
end

rspec undefined method `id' for nil:NilClass

require 'rails_helper'
feature "comment" do
given(:current_user) do
create(:user)
end
given(:undertaking) do
create(:undertaking)
end
background do
login_as(current_user)
end
scenario "can create comment" do
#below two because undertaking = user_id:2 & asking_id:1
create(:user)
create(:asking)
p undertaking
p Asking.find(1)
p User.find(2)
p User.find(1)
p Undertaking.all
visit undertaking_path(undertaking)
expect(current_path).to eq undertaking_path(1)
within("form#undertake-form-test") do
fill_in "content" , with: "heyheyhey"
end
click_button 'Send'
expect(page).to have_content 'heyheyhey'
end
end
This is spec/features/comment_spec.rb.
and this below is result command rspec.
#<Undertaking id: 1, title: "MyString", content: "MyText", result: false, user_id: 2, asking_id: 1, created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08">
#<Asking id: 1, content: "MyText", fromlang: "MyString", tolang: "MyString", usepoint: 1, finished: false, title: "MyString", deadline: nil, user_id: 1, created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08">
#<User id: 2, email: "shiba.hayato2#docomo.ne.jp", created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08", provider: nil, uid: nil, name: "Shiruba", occupation: "大学生", age: 10, sex: "男性", content: "heyheyheyeheyeheye", skill: "日本語検定3級", picture: "/assets/default_user.jpg", point: 500, country: "Japan", language1: "Japanese", language2: "Korea", language3: "English">
#<User id: 1, email: "shiba.hayato1#docomo.ne.jp", created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08", provider: nil, uid: nil, name: "Shiruba", occupation: "大学生", age: 10, sex: "男性", content: "heyheyheyeheyeheye", skill: "日本語検定3級", picture: "/assets/default_user.jpg", point: 500, country: "Japan", language1: "Japanese", language2: "Korea", language3: "English">
#<ActiveRecord::Relation [#<Undertaking id: 1, title: "MyString", content: "MyText", result: false, user_id: 2, asking_id: 1, created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08">]>
F
Failures:
1) comment can create comment
Failure/Error: <%= #undertaking.id %>
ActionView::Template::Error:
undefined method `id' for nil:NilClass
and this below is undertaking_controller.rb.
class UndertakingController < ApplicationController
def show
#undertaking=Undertaking.find(params[:id])
#comment=Comment.new do |c|
c.user=current_user
end
end
end
and this below is undertaking/show.html.erb.
<%= #undertaking.id %>
Why do I have the error? Why #undertaking is nil in view although Undertaking.first is not nil in spec/features/comment_spec.rb?Please help me.
I think it has to do with the naming used for your controller . The convention is undertakings/show.html.erb for the view instead of undertaking/show.html.erb . I would also use
class UndertakingsController < ApplicationController
instead of
class UndertakingController < ApplicationController
Finally I would check that all my routes also have the correct naming. Hope that helps. Good luck

get parent id on a nested attribute in rake seed

I'm trying to setup my seed like this:
company = Company.create!( name: 'Hirthe-Ritchie',
time_zone: 'Stockholm',
users_attributes: [{
first_name: 'Demo',
last_name: 'Memo',
title: 'CEO',
email: 'demo#demo.com',
time_zone: 'Stockholm',
admin: true,
password: 'foobar',
activated: true,
activated_at: Time.zone.now,
reviewer_attributes: {
reviewer_user_id: # parent id
}
}]
)
now what I want is that on reviewer_attributes, to make reviewer_used_id, the user id of the user being created.
So I have user_id and reviewer_user_id in my Reviewer model, now how do I get the parent's id in a nested attribute like I have here?
You will have to split your code into several new/create between the related objects. Try the following:
user_attrs = {
first_name: 'Demo',
last_name: 'Memo',
title: 'CEO',
email: 'demo#demo.com',
time_zone: 'Stockholm',
admin: true,
password: 'foobar',
activated: true,
activated_at: Time.zone.now
}
user = User.new(user_attrs)
user.reviewer = user
company = Company.new(name: 'Hirthe-Ritchie', time_zone: 'Stockholm')
company.users << user
company.save!

Association clears when reloading a record in test

I am only familiar with Rspec, but now I need to fix a library which uses Test::Unit.
I find out that when I reload the record, the association becomes nil
For example:
test "accepts nested attributes from subscription to user ()" do
#user = User.create(name:'Ash')
#subscription = #user.create_subscription()
puts "user: " << #user.inspect
puts "subscription: " << #user.subscription.inspect
#subscription.update_attributes({ :user_attributes => { :notification_comment => true } })
#user.reload
puts "user: " << #user.inspect
puts "subscription: " << #user.subscription.inspect
assert #user.subscription, "should have an subscription"
end
Outputs:
user: #<User id: 815823837, account_id: nil, name: "Ash", email: nil, settings: {}, created_at: "2013-02-07 04:28:51", updated_at: "2013-02-07 04:28:51">
subscription: #<Subscription id: 1, user_id: 815823837, created_at: "2013-02-07 04:28:51", updated_at: "2013-02-07 04:28:51">
user: #<User id: 815823837, account_id: nil, name: "Ash", email: nil, settings: {}, created_at: "2013-02-07 04:28:51", updated_at: "2013-02-07 04:28:51">
subscription: nil
Why does this happen? I did check and I can confirm that I can Subscription.find(#subscription.id) so it is saved in the database.

Resources