Seeding in Ruby on Rails - ruby-on-rails

I have several deeply nested models and I would like to seed my database. The models are as following: Each restaurant has many menus. Each menu has many categories. Each category has many meals. Currently, my seed looks like this:
restaurant_seed = [
{
name: "KFC",
address: "Sofia",
description: "Fast food.",
phone_number: "88888888"
}
]
menu_seed = [
{
name: 'Spring menu.',
active: true
},
}
name: 'Winter menu.',
active: false
}
]
category_seed = [
{
name: "Dessert",
available_all_day: false,
age_restriction: false,
category_avatar: File.open(File.join(Rails.root, "app/assets/images/desserts.jpg"))
},
{
name: "Salad",
available_all_day: true,
age_restriction: false,
category_avatar: File.open(File.join(Rails.root, "app/assets/images/salads.jpeg"))
}
]
meal_seed = [
{
name: "Shopska salata",
meal_avatar: File.open(File.join(Rails.root, "app/assets/images/shopska_salad.jpg"))
},
{
name: "Shisha",
meal_avatar: File.open(File.join(Rails.root, "app/assets/images/shisha.jpg"))
}
]
However, I do not know how to actually seed the database with that info. The idea is that each restaurant will have all of the menu seeds, each of the menus in each restaurant will have each category from the category seed and so on. Thank you for any suggestions!

Write a method to iterate all seeds and create corresponding records.
def setup_restaurants(restaurant_seed, menu_seed, category_seed, meal_seed)
restaurant_seed.each do |r_seed|
restaurant = Restaurant.create(r_seed)
menu_seed.each do |m_seed|
menu = restaurant.menus.create(m_seed)
category_seed.each do |c_seed|
category = menu.categories.create(c_seed)
meal_seed.each do |mm_seed|
category.meals.create(mm_seed)
end
end
end
end
end

Related

ActiveRecord: Skip validation when saving multiple objects

I know I can skip validations for an individual save, like this:
User.new(name: 'John').save(validate: false)
But how can I do that when saving multiple objects at once? Like this:
Category.create([
{ name: 'Apps' },
{ name: 'Songs' },
{ name: 'Movies' }
])
I found this gem: https://github.com/zdennis/activerecord-import
It works like this:
categories = [
Category.new(name: 'Apps'),
Category.new(name: 'Songs'),
Category.new(name: 'Movies')
]
Category.import(categories, validate: false)
It is also possible to use plain arrays instead of ActiveRecord objects.
I guess it generates pure SQL when validate is set to false so it can skip validations.
You can't do that with create. If you really must skip validations you can do something like this:
[
{ name: 'Apps' },
{ name: 'Songs' },
{ name: 'Movies' }
].each do |attributes|
c = Category.new(attributes)
s.save(validate: false)
end

Additional attributes in N-N mongoid (Like in pivot table)

I have a has_many_and_belongs_to relationship between central and coordinators.
So my mongo documents are represented as below:
central = {
_id: 1,
title: 'First Name',
coordinators: [
BSON[1],
BSON[2],
BSON[3]
]
}
coordinators = [
{
_id: 1,
name: 'Me',
centrals: [BSON[1], BSON[2]]
},
{
_id: 1,
name: 'Mateus'
centrals: [BSON[1]]
},
{
_id: 1,
name: 'Gomes'
centrals: [BSON[1]]
},
]
If I do this:
#central = Central.find(1)
#coordinator = #central.coordinators.find(1)
#coordinator.can_edit = false
It will apply to the coordinators document resulting in this:
coordinator = {
_id: 1,
name: 'Me',
centrals: [BSON[1], BSON[2]],
can_edit: false
}
But what I really want to do is apply this can_edit attribute in the relationship, like in pivot table in RDBMS:
central = {
_id: 1,
titulo: 'First Name',
coordinators: [
{
_id: 1,
name: 'Me',
can_edit: false
},
BSON[2],
BSON[3]
]
}
Only for the central with id 1 I want to aply the can_edit to false.
I have to keep the relation between a Central and Coordinator, but in some situation, I want to have an additional information about that relation, like if I would not allow a coordinator to edit some data only in central with id 1.
How can I do this using mongoid?
The solution for this was create another relation N-N:
Add on central.rb
has_and_belongs_to_many :blocked_coordenadors,
class_name: "Central",
inverse_of: :blocked_centrals
And in coordinator.rb:
has_and_belongs_to_many :blocked_centrals,
class_name: "Central",
inverse_of: :blocked_coordenadors
And to check I do this:
central.blocked_coordenadors.include? coordinator

Wildcard for nested params

Is there a way I can test for both these params to be true? Some sort of wildcard value for the first key?
params[:book][:return_to]
params[:work][:return_to]
At the moment I'm having to do:
if params[:book] and params[:book][:return_to]
# blah
elsif params[:work] and params[:work][:return_to]
# blah
Hashie is the solution I've used.
https://github.com/intridea/hashie
From their readme:
user = {
name: { first: 'Bob', last: 'Boberts' },
groups: [
{ name: 'Rubyists' },
{ name: 'Open source enthusiasts' }
]
}
user.extend Hashie::Extensions::DeepFind
user.deep_find(:name) #=> { first: 'Bob', last: 'Boberts' }

Render RABL template with two objects

I recently came across a condition were i wanted to send two objects in the RABL as a response.
[
{
id: "1",
name: "XYZ"
},
{
id: "1",
name: "XYZ"
},
{
total: "2"
}
]
All I could manage was this , which is not correct.
[
{
id: "1",
name: "XYZ",
total: "2"
},
{
id: "1",
name: "XYZ",
total: "2"
}
]
I Found a solution which was to use a partial to iterate on the object and just add a new
node(:name) {partial("users/names", :object => #users)}
node(:total){ #total}
This is a hack, which i don't want because it wraps all the names in a node .
Is there any other way to do it ?
In your rabl file try this:
child #users, object_root: false do
attributes :id, :name
end
node(:total) { #users.size }

Populate a Scaffold via Seed

I have an Item's Scaffold which has approximately 200+ Item's which are pre-fix.
So adding them manually is really painful.
Can i populate the Scaffold in my seed-file and then db:seed on production ?
I don't know the proper method but i think it's something like this:
items = Item.create([
{ name: 'css' },
{ name: 'css3' },
{ name: 'ruby' },
{ name: 'rails' },
{ name: 'python' },
{ name: 'html' }
])
I'm searching for a Solution that will seed my Item's Scaffold...
Try the following code by adding remaining items in array in db/seeds.rb file and run rake db:seed command. That generates expected records in items table.
['css','rubyonrails','java'].each do |item|
Item.find_or_create_by_name(:name => item)
end
Good luck.
You have to do it that way, but you don't need to asign it to the items variable.
You just have to add to the seed.rb file the code with your items. I've added the delete_all before to avoid creating duplicate items.
Item.delete_all
Item.create([
{ name: 'css' },
{ name: 'css3' },
{ name: 'ruby' },
{ name: 'rails' },
{ name: 'python' },
{ name: 'html' }
])
And then you'll have to seed your database with rake:db seed.

Resources