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
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
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
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.
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")
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)