I'm creating seed data and I can't figure out how to link the user's email to the auction model in the seller attribute on the seeds page, and I can't figure out how to link the user to the review seed data.
seeds.rb
u1 = User.create!(
name: 'Alice Johnson',
email: 'alice#email.com',
password: 'password',
rating: '3',
location: 'Memphis, TN'
)
u2 = User.create!(
name: 'Bob Jones',
email: 'bob#email.com',
password: 'password',
rating: '4',
location: 'Nashville, TN'
)
a2 = Auction.create!(
seller: , #Help
auction_start_time: DateTime.strptime("4/23/2020 08:00", "%m/%d/%Y %R"),
auction_end_time: DateTime.strptime("5/1/2020 11:59", "%m/%d/%Y %R"),
category: "Home",
current_price: 70.0,
highest_bid: 100.0,
highest_bidder: "John Doe",
name: "Vacuum",
active: TRUE
)
r1 = Review.create!(
user:u2,
description: 'The best',
rating:5,
reviewer: 'bob#email.com',
title:'Great',
user_reviewed:'Alice Johnson'
)
db/migration/addUSerFkColToReviews
class AddUserFkColToReviews < ActiveRecord::Migration[6.0]
def change
add_reference :reviews, :user, foreign_key: true
end
end
to be able to use seller: user you have to have this association in your Auction model like this:
belongs_to :seller, calss_name: 'User'
Also note you have to make sure that the seller_id column is present in your auctions table.
Related
I got this error when trying to seed database with image file in nested attributes.
rails aborted!
ArgumentError: wrong number of arguments (given 1, expected 0; required keywords: io, filename)
product.rb
class Product < ApplicationRecord
belongs_to :user
has_many :founders, dependent: :destroy
accepts_nested_attributes_for :founders, allow_destroy: true
founder.rb
class Founder < ApplicationRecord
belongs_to :product, optional: true
has_one_attached :profile_picture
end
seed.rb
user = User.create!(email: 'user#example.com', password: '1234567890')
10.times do |index|
#product = Product.create(
user: user,
name: "Product #{index+1}",
tagline: Faker::Lorem.sentence,
industry: Faker::Company.industry,
website: Faker::Internet.url,
company_name: Faker::Company.name,
company_website: Faker::Internet.url,
founders_attributes: [
{
name: Faker::Name.name,
email: Faker::Internet.email,
website: Faker::Internet.url,
profile_picture: { io: File.open(Rails.root + "app/assets/images/profile_picture.png"), filename: 'profile_picture.png', content_type: 'image/png' }
},
{
name: Faker::Name.name,
email: Faker::Internet.email,
website: Faker::Internet.url,
profile_picture: { io: File.open(Rails.root + "app/assets/images/profile_picture.png"), filename: 'profile_picture.png', content_type: 'image/png' }
}
]
)
end
I have no idea to solve this error.
Give me some advice please.
You can do it without nested attributes. And by the way you didn't close your files:
PNG_PATH = Rails.root.join('app', 'assets', 'images', 'profile_picture.png')
user = User.create!(email: 'user#example.com', password: '1234567890')
1.upto(10) do |index|
#product = Product.create(
user: user,
name: "Product #{index}",
tagline: Faker::Lorem.sentence,
industry: Faker::Company.industry,
website: Faker::Internet.url,
company_name: Faker::Company.name,
company_website: Faker::Internet.url
)
2.times do
founder =
#product.founders.create(
name: Faker::Name.name,
email: Faker::Internet.email,
website: Faker::Internet.url
)
File.open(PNG_PATH) do |file|
founder.profile_picture.attach(io: file, filename: File.basename(file.to_path))
end
end
end
class Gallery < ApplicationRecord
belongs_to :artist
include Filterable
validates :user, presence: true
belongs_to :user, optional: true
resourcify
end
How would I be able to seed data that has multiple belongs_to?
Here is my method but it gives me an error of user cannot be blank
user = User.create! :name => 'Bobby Joe', :email => '20#gmail.com', :password => 'password', :password_confirmation => 'password'
artistOne = user.artists.create!(artist_name: 'ED', first_name: 'Edgar', last_name: 'Degas', email: 'edgardegas#yahoo.com', password: 'password', street: '2625 Ashcraft',city: 'San Diego',state: 'CA',zipcode: '92103',website: 'www.edgardegas.com',sales: '',phone: '(760)210-1326')
galleryOne = artistOne.galleries.create!(name: 'Exhibition of Art', website: 'www.ExhibitionOfArt.com', phone: '(619)264-8402', opening:'10:00:00', closing:'18:00:00', street:'325 15th Street', city:'San Diego', state:'CA', zipcode: '92101')
You need to add associations which you created (artistOne, user),
galleryOne = artistOne.galleries.create!(name: 'Exhibition of Art', website: 'www.ExhibitionOfArt.com', phone: '(619)264-8402', opening:'10:00:00', closing:'18:00:00', street:'325 15th Street', city:'San Diego', state:'CA', zipcode: '92101', artist: artistOne, user: user)
You have to set your relationship id in your Gallery creation like that :
galleryOne = artistOne.galleries.create!(name: 'Exhibition of Art', website: 'www.ExhibitionOfArt.com', phone: '(619)264-8402', opening:'10:00:00', closing:'18:00:00', street:'325 15th Street', city:'San Diego', state:'CA', zipcode: '92101', user_id: user.id, artist_id: artistOne.id)
I have three models using Active Record associations:
Book Model
has_many :checkouts
User Model
has_many :checkouts
Checkout Model
belongs_to :book
belongs_to :user
In my view, I need the book, checkout, and user names from the checkouts.
By using Book.first.checkouts I get:
#<ActiveRecord::AssociationRelation
[#<Checkout id: 30,
checkout_date: "2017-04-13",
return_date: nil,
book_id: 118,
user_id: 1,
created_at: "2017-04-13 17:43:07",
updated_at: "2017-04-13 17:43:07"
>,#<Checkout id: 50,
checkout_date: "2017-04-13",
return_date: nil,
book_id: 118,
user_id: 1,
created_at: "2017-04-14 00:33:34",
updated_at: "2017-04-14 00:33:34">
]>
But, I would like to the user name, not just the id. I've tried Book.first.checkouts.map { |c| c.user.name } but that returns only the name, and I need the rest of the checkout information. Ideally, my data (converted to json) looks something like:
{
name: "Book Name",
checkouts: [
checkout_data: "Today",
user_name: "Mary"
]
}
How can I add the user name to my checkout data?
You can try this at your controller:
render json: #books, include: { checkout: { only: :checkout_date, include: { user: { only: :name } } }}
You should preload the data to prevent (N+1) query problem,
For Display possible checkouts for particular book:
book_id = <given book id>
book = Book.find(book_id)
checkouts = book.checkouts.includes(:user)
return_hash = {name: book.name, checkouts: []}
checkouts.each do |checkout|
return_hash[:checkouts] << { checkout_data: checkout.checkout_date,
user_name: checkout.user.name
}
end
To include other solutions, I found this worked pretty well:
checkouts = book.checkouts.unreturned.map do |checkout|
checkout.attributes.merge({ user_name: checkout.user.name })
end
{ checkouts: checkouts, available: book.available?, book_id: book.id }
attributes.merge did the trick.
I have models Favorite_Photo, User, and Photo
In Heroku Console:
u = User.find(1)
u.favorites.last
=> #<Photo id: 37, user_id: 1, picture: "th.jpeg", title: "Cookies & Cream Pocky ", description: nil, photo_type: nil, location_type: nil, remote_picture_url: nil, created_at: "2016-07-07 03:04:03", updated_at: "2016-07-07 03:04:03">
And If I query:
u = User.find(1)
u.favorite_photos.last
=> #<FavoritePhoto id: 87, photo_id: 12, user_id: 1, created_at: "2016-07-07 19:37:28", updated_at: "2016-07-07 19:37:28">
class User
has_many :favorite_photos
has_many :favorites, through: :favorite_photos, source: :photo
class Photo
has_many :favorite_photos
has_many :favorited_by, through: :favorite_photos, source: :user
class FavoritePhoto
belongs_to :user
belongs_to :photo
validates :user_id, uniqueness: {
scope: [:photo_id],
message: 'can only favorite an item once'
}
UsersController
def show
#user = User.find(params[:id])
#favorites = #user.favorites
end
This returns a list of favorites ordered by photo_id. I want to create a scope that will order the favorites based on FavoritePhoto id:
has_many :favorites, -> { order("favorite_photos.id ASC") }, through: :favorite_photos, source: :photo
reference: scopes for has_many
class Subject
has_many :subject_attribute_types
has_many :subject_attributes
accepts_nested_attributes_for :subject_attributes
end
class SubjectAttributeType
belongs_to :subject
has_many :subject_attributes
attr_accessible :type_name
end
class SubjectAttribute
belongs_to :subject
belongs_to :subject_attribute_type
attr_accessible :value
end
For example:
s1 = Subject.create()
s2 = Subject.create()
sat1 = SubjectAttributeType.create(subject: s1, name: 'Age')
sat2 = SubjectAttributeType.create(subject: s1, name: 'Sex')
sat3 = SubjectAttributeType.create(subject: s2, type_name: 'Age')
sat5 = SubjectAttributeType.create(subject: s2, type_name: 'Username')
SubjectAttribute.create(subject: s1, subject_attribute_type: sat1, value: 20)
SubjectAttribute.create(subject: s1, subject_attribute_type: sat2, value: "male")
SubjectAttribute.create(subject: s2, subject_attribute_type: sat3, value: 21)
SubjectAttribute.create(subject: s2, subject_attribute_type: sat1, value: "user1")
Problem:
What's the best practice to make a search on exact subject_attributes.
If i want to find all Subjects with age >= 18 and nickname like %user%
currently i am using ransack gem, but i can't think out how to make a search on nested_attributes
I see there is a problem in business logic of your app. Why would you need your AttributeType to know about any of subject?
class Subject < ActiveRecord::Base
has_many :subject_attributes
has_many :attribute_types, through: :subject_attributes
end
class SubjectAttribute < ActiveRecord::Base
belongs_to :attribute_type
belongs_to :subject
attr_accessible :attribute_type_id, :subject_id, :value
end
class AttributeType < ActiveRecord::Base
attr_accessible :type_name
end
After that if you insert some data:
s1 = Subject.create
s2 = Subject.create
sat1 = AttributeType.create(type_name: "Age")
sat2 = AttributeType.create(type_name: "Sex")
sat3 = AttributeType.create(type_name: "Username")
SubjectAttribute.create(subject:s1, attribute_type:sat1, value: 20)
SubjectAttribute.create(subject:s1, attribute_type:sat2, value:"male")
SubjectAttribute.create(subject:s2, attribute_type:sat1, value:21)
SubjectAttribute.create(subject:s2, attribute_type:sat3, value:"user1")
you will be able to make selects.
In your example you use several attributes, so you have to make several requests:
that way you'll find subject with value name:
names = Subject.joins(:attribute_types).where("attribute_types.type_name = 'Username'
and value like '%user%'")
=> [#<Subject id: 2, created_at: "2013-05-29 11:11:51", updated_at: "2013-05-29 11:11:51">]
that way you'll find subject with value age
ages = Subject.joins(:attribute_types).where("attribute_types.type_name = 'Age'
and value >= 18")
=> [#<Subject id: 1, created_at: "2013-05-29 11:11:42", updated_at: "2013-05-29 11:11:42">,
#<Subject id: 2, created_at: "2013-05-29 11:11:51", updated_at: "2013-05-29 11:11:51">]
That way you'll find intersected subjects
subjects = (names&ages)
=> [#<Subject id: 2, created_at: "2013-05-29 11:11:51", updated_at: "2013-05-29 11:11:51">]
Using dynamic attribute_types makes select really hard. so if you ok with making separate request for each type-value params, use it. Otherwise maybe its really just columns of Subjects?