How to seed belongs to and has many associantion with seeds.rb - ruby-on-rails

I have two models. One is categories and the other one is products. I already populated the categories table and now I need to populate the products one with the category id.
I'm using faker for this population.
The models and the seeds.rb file are like this
class Product < ApplicationRecord
belongs_to :categories
end
class Category < ApplicationRecord
has_many :products
end
seeds.rb
category = Category.ids
100.times do
Product.create!([{
name_product: Faker::Commerce.product_name
},
{
value_product: Faker::Commerce.price
},
{
category_id: category.sample
}
])
end
But I keep getting the error "validation failed. Categories is necessary" even passing the category id.
If I comment the association inside the product model it works but this isn't a solution.

I think your problem lies in how you are attempting to create the products.
Your current code will attempt to create three products, as you're passing an array of hashes - two of which have no category ID:
Product.create!([
{
name_product: Faker::Commerce.product_name # << first product, no category
},
{
value_product: Faker::Commerce.price # << second product, no category
},
{
category_id: category.sample # << third product
}
])
It's a little unclear from your question but try one the following inside your 100.times do block instead:
Product.create!(
name_product: Faker::Commerce.product_name,
value_product: Faker::Commerce.price,
category_id: category.sample
)
Or:
Product.create!([
{
name_product: Faker::Commerce.product_name,
category_id: category.sample
},
{
value_product: Faker::Commerce.price,
category_id: category.sample
},
{
category_id: category.sample
}
])
The former will create a single record, if each instance has name_product, value_product and category_id columns; the latter three products, all of which have a category_id.
Let me know how you get on and if that helps at all.
Edit
Looks like your association is setup incorrectly. Try:
class Product < ApplicationRecord
belongs_to :category
end

Related

How to fetch associated model name in search results with seachkick

I used gem 'searchkick' for searching in my application.
here is my association and searchkick settings .
product.rb
belongs_to :sub_category
belongs_to :brand
belongs_to :product_type
has_one :category, through: :sub_category
searchkick match: :word_start,word_start: [:name], suggest: [:name]
scope :search_import, -> { includes(:brand, :sub_category, :category, :product_type) }
def search_data
{
name: name,
category_name: category.name,
sub_category_name: sub_category.name,
brand: brand.name,
product_type: product_type.name
}
end
I don't how searchkick works exactly. but i want to show the category name, sub category name and product type name in search results.
For an example,
I have list of alcohols products which belongs to different categories like beer, wine, whiskey etc.
if i search for beer, it should show beer in search results because beer is category which associated to product. i don't want the products which are associated to beer category, i want to beer category in search results.
here is my query for search query
response = Product.search( params[:query], suggest: true, fields: ["name^10", "description"], limit: 5, operator: "or",misspellings: {below: 5} ).results
it is similar functionality of any e commerce application, like if i search iPhone 7 in flipkart application it will show iPhone 7 as category in search result, if i click on that all products related to iPhone 7 will show in one page.
i don't know how to achieve this , any help will appreciated.
I think you are looking for aggregation feature. Just look the searchkick doc, you will find your answer.
Note: I am giving answer from Stackoverflow app. So I will later update it with some code from laptop.
I have to do multi search , Here is the service which i made for getting associated model with multi search.
module Search
class RetriveData
def self.multi_search(params)
#params = params
create_searchable_variables_for_multi_model_search
Searchkick.multi_search(array_of_searchkick_objects)
array_of_searchkick_objects.map(&:results).flatten
end
private
def self.array_of_searchkick_objects
array_of_models.map do |klass|
instance_variable_get("##{klass.to_s.downcase}s")
end
end
def self.searchable_fields
["name^10","sub_category_name","keyword_name",
"category_name","product_type_name","brand_name"]
end
def self.create_searchable_variables_for_multi_model_search
array_of_models.each do |klass|
instance_variable_set("##{klass.to_s.downcase}s",
klass.search( #params[:query],
constraints(klass) ))
end
end
def self.constraints(klass)
{
fields: searchable_fields,
suggest: true,
operator: "or",
misspellings: {below: 5},
where: klass == Product ? { or: [[{available_cities_name:
#params[:city]},{available_cities_short_name:
#params[:short_name]}]] } : {},
execute: false
}
end
def self.array_of_models
[Category, SubCategory, Brand, ProductType, Product]
end
end
end
Source is here

ActiveRecord many_to_many association instantiation returns uninitialized constant

I have a list of categories in my database (validations not listed for brevity).
class Category < ActiveRecord::Base
has_many :crimes_categories
has_many :crimes, through: :crime_categories
end
I am seeding my database with crimes, some of which have multiple categories (validations not listed for brevity).
class Crime < ActiveRecord::Base
belongs_to :team
has_many :crime_categories
has_many :categories, through: :crime_categories
end
These models are joined by a CrimeCategory model
class CrimeCategory < ActiveRecord::Base
belongs_to :category
belongs_to :crime
end
The seed file is iterating over a list of crime objects to format and add them to my database. I have tried a few different approaches. The first approach was to create CrimeCategory row.
seed.rb
count = 1
teamCrimeList.each do |crime|
...
categories.each do |cat|
...
end
category_object = Category.where(name: category)
crime_category_objects << category_object
CrimeCategory.create(category_id: category_object.id, crime_id: count)
That last line would throw the following error
NameError: uninitialized constant CrimeCategory
Another strategy I tried was the following
seed.rb
teamCrimeList.each do |crime|
...
categories.each do |cat|
...
end
category_object = Category.where(name: category)
crime_category_objects << category_object
end
date = Date.parse(crime['Date'])
crime_object = Crime.create(team_id: team.id, date: date, name: crime['Name'], position: crime['Position'], encounter: crime['Encounter'], description: crime['Description'], outcome: crime['Outcome'])
crime_object.categories = crime_category_objects
which returns the same error
I also tried this approach
seed.rb
teamCrimeList.each do |crime|
...
categories.each do |cat|
...
end
category_object = Category.where(name: category)
crime_category_objects << category_object
end
date = Date.parse(crime['Date'])
Crime.create(team_id: team.id, categories: crime_category_objects.flatten, date: date, name: crime['Name'], position: crime['Position'], encounter: crime['Encounter'], description: crime['Description'], outcome: crime['Outcome'])
I threw in some pry's and tried calling crime.categories, all of which returns the same error.
I scoured stack overflow and nearly all the entries I came across on this issue have to do with naming errors but insofar as I can tell, there is no naming error.
#Glyoko had the right idea. I had named my CrimeCategory model file as
app/models/crimecategory.rb instead of app/models/crime_category.rb

Get all tree from a model object

I have
#total = Purchase::Total.find(1);
Total model have:
has_many :items
belongs_to :member
belongs_to :company
..................
Also companies model has
has_many :addresses
has_one :subscription
..................
and a lot more
How can I get a tree from the #total object containing all the has_one, belongs_to dependencies?
I.E.
<Purchase::Total id: 3, member_id: 4, created_at: \"2015-11-25 14:47:46\", updated_at: \"2015-11-25 14:47:46\", affiliate_company_id: nil, is_paid: false, currency: 1, company_id: 37020, ser_id: 2>
<Company id: 37020, name: \"Andrew\", parent_id: 37019, member_company_id: 37019, payment_company_id: 37019, widget_id: 3003359>
And so ..... (I did the example with: #total.inspect and #total.company.inspect), and I need something like inspect to return automatically all the objects.
Using reflect_on_all_associations
Take a Queue and a Hash and add Total (model name) to it.
Pop a model name, get all associated models and add them queue. Also, using the tablize name of current model, create a new entry in hash and add the tablized names of associated models.
If queue is not empty, go to 2.
At the end, your hash should look like:
{ total: { company: [ :subscription, :addresses ] }, items: { associated: { another: :another_one } } }
Then you can use this in your query:
Total.where().join(hash[:total])
It will fetch all the associated data as well. Then you can simply loop through the attributes. If attribute type is ActiveRecord (or similar), then its an associated model data.

Proper way in Rails 4 to create a product with an associated category in one statement?

I have a products and category model which I'm using to build a small application. I would like to find a way of creating a product with an associated category in one statement.
Here is my Category model
class Category < ActiveRecord::Base
has_many :products
end
And my Product Model
class Product < ActiveRecord::Base
belongs_to :category
def self.search(search)
products = order(:name)
products = products.where("name like ?", "%#{search}%") if
search.present?
products
end
end
In my seeds.rb file I tried doing this but it only creates the product and not the associated category which is "nil".
Product.create!(category: Category.where(:name, "Toys & Games").create, name: "Seafarers of Catan", price: 34.99, released_at: "2011-07-15")
Is there a way where I can create a product and associate its category in one statement? Thanks
I would do it like this
category = Category.new(:name, "Toys & Games")
category.products.new(
name: "Seafarers of Catan",
price: 34.99,
released_at: "2011-07-15"
)
category.save!
The save! on category will cascade to the associated Product.
If you need access to the Product later, just save it off as a local variable
product = category.products.new(...)
What about Product.create!(category: Category.create(:name, "Toys & Games"), name: "Seafarers of Catan", price: 34.99, released_at: "2011-07-15")
?
(Note the move of the .create call -- not sure if this makes a difference, but worked in my quick test.)
Why not simply creating the category before?
category = Category.create(name: 'Toys & Games')
Product.create(category: category, name: 'Seafarers of Catan')
Ok I figured it out, this works now.
Product.create!(category: Category.create(name: "Toys & Games"), name: "Seafarers of Catan", price: 34.99, released_at: "2011-07-15")

Rails - Join query difficulties

I have two basic models: Stadium and Owner
The relations between those two models are:
A Stadium:
belongs_to :owner
An Owner:
has_many :stadiums
The thing here is, an Owner has also Categories associated, and here is where owner_category model comes in.
An Owner:
has_and_belongs_to_many :owner_categories,
:join_table => 'l_owners_owner_categories',
And OwnerCategory:
has_and_belongs_to_many :owners, :join_table => 'l_owners_owner_categories'
Basically,
The OwnerCategory table looks like this:
id,name
1,sport
2,kids
So, my question is:
Given that I let the user to choose a City and a Category, how would I get all the Stadiums from that city which Owner has the given Category?
So for example:
If I have the following Stadiums:
id,name,city,owner_id
1,'soccer stadium','New York',5
2,'music stadium','New York',4
2,'music stadium','San Francisco',4
The following Owners:
id,name
4, 'John'
5, 'Peter'
The following OwnersCategories table:
id,name,description
1,'sports','this category is associated with stadiums that support sports'
2,'music','this category is associated with stadiums that support music'
And the following join table:
owner_id,owner_category_id
5, 1
When the users chooses 'New York' and 'Sports' it should give this stadium:
1,'soccer stadium','New York',5
Try something like this (warning: not tested):
Stadium.joins(:owner).joins(:owner => :owner_categories)
.where(:city => "New York").where("owners_categories.name = ?", "sports")
class Stadium < ActiveRecord::Base
scope :for_city, lambda { |city_name| where(:city => city_name) }
scope :for_owner_category,
lambda { |owner_category_id|
joins("INNER JOIN owners ON owners.id = stadium.owner_id" +
" INNER JOIN l_owners_owner_categories ON l_owners_owner_categories.owner_id = owners.id").
where("l_owners_owner_categories.owner_category_id = :category_id",
:category_id => owner_category_id)
}
end
Stadium.for_city("New York").for_owner_category(1)

Resources