Ruby on Rails Seed Data - ruby-on-rails

I am Ruby/Rails newbie. I am currently learning about the Rails console and databases using Rake and the seeds.rb file.
I am supposed to:
Add a post with a unique title and body to seeds.rb.
Before creating a unique post, verify it exists in the database. Only
seed the post if it doesn't.
Run rake db:seed a couple times, start your Rails console and confirm
that your unique post has only been seeded once.
Repeat to create a unique comment and confirm that it is also only
seeded once.
Honestly I don't know how to start working on this. I am supposed to add a post using the rails console or directly from the seeds.rb file? Any guidance will be greatly appreciated.

Despite the intention of seed-ing - that this is meant to be run once, to populate the database - there is no technical constrain preventing you from running rake db:seed command couple times. Even without cleaning/recreating your database.
In that case, try following code for db/seeds.rb
post_atrributes = [
{ title: "Sample Title 1", body: "Sample body 1" },
{ title: "Sample Title 2", body: "Sample body 2" },
{ title: "Sample Title 3", body: "Sample body 3" },
]
post_attributes.each do |attributes|
Post.create(attributes) unless Post.where(attributes).first
end
First of all, we're defining an array of attributes for each Post, to be created.
Later, we're iterating through that array (with post_attributes.each do |attributes|), and trying create a new Post, unless one with specified attributes found.
In Rails, there is quite fancy method first_or_create, which does exactly that - queries database for specified attributes (where(attributes)), and if nothing found - creates new record based on provided attributes.
post_atrributes = [
{ title: "Sample Title 1", body: "Sample body 1" },
{ title: "Sample Title 2", body: "Sample body 2" },
{ title: "Sample Title 3", body: "Sample body 3" },
]
post_attributes.each do |attributes|
Post.where(attributes).first_or_create
end
At this point, you can "seed" the database with rake db:seed and check what is stored in database (after running rails console) by:
Post.all.map(&:title)
Assuming you had empty database before running rake db:seed, it should contain only 3 Posts. The ones specified with attributes in post_attributes.
Now, if you try to modify your db/seeds.rb again, adding an attributes for one more Post:
post_atrributes = [
{ title: "Sample Title 1", body: "Sample body 1" },
{ title: "Sample Title 2", body: "Sample body 2" },
{ title: "Sample Title 3", body: "Sample body 3" },
{ title: "Another Post", body: "WOW!" },
]
post_attributes.each do |attributes|
Post.where(attributes).first_or_create
end
After running rake db:seed, and checking in console:
Post.all.map(&:title)
You can see, that only one new Post has been created. The one with title "Another Post".
In your question I understood, that when creating new Post, both attributes - title and body have be unique, so if you try to perform the same for attributes like:
post_atrributes = [
{ title: "Sample Title 1", body: "Sample body 1" },
{ title: "Sample Title 1", body: "Sample body 2" },
]
This will create two separate Posts, because they have different body attributes defined.
For Comments you can do similar thing.
Again, as jBeas mentioned earlier - seed-ing has different purpose, but if this is only exercise to play with ActiveRecord - this is one of ways how you can tackle the problem.
Hope that helps!

Seeding is the process of populating a database with data.
There are two methods used to accomplish this.
You can use ActiveRecord Migrations
class AddInitialProducts < ActiveRecord::Migration
def up
5.times do |i|
Product.create(name: "Product ##{i}", description: "A product.")
end
end
def down
Product.delete_all
end
end
Or you can store it in a separate seeds.rb file
5.times do |i|
Product.create(name: "Product ##{i}", description: "A product.")
end
afterwards, run rake db:seed
Source
http://edgeguides.rubyonrails.org/active_record_migrations.html#migrations-and-seed-data

Related

POST list of objects in rails. How can I whitelist the list of objects in strong params?

I'm trying to post a list of objects called tasks that looks like the following.
{
// Shared attributes
"parent_id": "1",
"author": "Name Name",
// Task list
"tasks": [
{"name":"task 1"},
{"name":"task 2"}...
]
}
In my controller, I have the following, which iterates through tasks, appends the shared attributes, and creates a new Task object:
task_params[:tasks].each do |task|
new_params = task
new_params[:parent_id] = task_params[:parent_id]
new_params[:author] = task_params[:author]
new_task = Task.new(new_params)
end
The problem is that :tasks isn't showing up in my task_params despite being passed in as a parameter. This seems to be because it isn't whitelisted in strong_params, but that doesn't seem to make a difference. It looks to me like I can only whitelist parameters that correspond to attr_accessors. So how can I pass in the custom parameter tasks through strong_params and into the controller method?
Edit:
My params definition:
def task_params
params.require(:task).permit(:parent_id, :author, tasks: [:name])
end
Rails output:
Parameters: {"parent_id"=>1, "author"=> "Name name", "tasks"=>[{"name"=>"task 1"}, {"name"=>"task 2"}], "task"=>{"job_id"=>1, "author"=>"Name name"}}
But when I print the task params in the controller:
{"parent_id"=>1, "author"=>"Name name"}
Look at the documentation on nested parameters with Strong Parameters. You'd do something like:
params.permit(:parent_id, :author, tasks: [:name])
Are the tasks associated to one another in the model (might be worth copying that code into the question)? If so, do you just need to use accepts_nested_attributes_for?
Docs are here: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for
That way, by adding accepts_nested_attributes_for :tasks (or however you're naming the association) and using fields_for in the form, you should be able to access task data in the params (it'll still need permitting).
Put simply, from the docs:
Defines an attributes writer for the specified association(s).
If you're using the stringified task data, you can probably use an attr_reader in the model to allow this to be passed in the params.
This help?
Your params, as posted in your question, are malformed (missing a comma, a close bracket, etc.). That's probably a cut and paste error, I'm guessing. So, let's assume they are supposed to look like this:
{
task: {
"parent_id"=>1,
"author": "Name name",
"tasks"=>[
{"name"=>"task 1"},
{"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}}
]
}
}
Then if I do this in console:
params = ActionController::Parameters.new(task: {"parent_id"=>1, "author": "Name name", "tasks"=>[{"name"=>"task 1"}, {"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}}]})
task_params = params.require(:task).permit(:parent_id, :author, tasks: [:name, task: [:job_id, :author]])
task_params[:tasks].each do |task|
puts task.merge!(parent_id: task_params[:parent_id], author: task_params[:author])
end
Then I see from the puts statements:
{"name"=>"task 1", "parent_id"=>1, "author"=>"Name name"}
{"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}, "parent_id"=>1, "author"=>"Name name"}
Which would be your arguments for Task.new, which you could do as:
task_params[:tasks].each do |task|
new_task = Task.new(task.merge!(parent_id: task_params[:parent_id], author: task_params[:author]))
end

Can't seed database after using destroy_all from command line

In my application I have Posts that Users can create. When I initially started my project, I created some placeholder Posts and Users from the command line just so I can play around. As the application advanced I created a seed file and ran 'rake db:seed' from the command line. Everything worked fine but I realized that I still had the placeholder Posts and Users still in the database so I decided to delete them. I decided to destroy all Posts and Users from the command line using the 'destroy_all' method. I just wanted to see if it would work and it did as everything was deleted. But now when I run 'rake db:seed' to populate the database, nothing shows up. I get no errors and nothing gets returned when I run Post.all or User.all from the command line. I'm not sure what's going on but I would appreciate any assistance, thank you!
User.create(name: 'John', email: 'John#gmail.com', password: '123456', password_confirmation: '123456')
User.create(name: 'Bill', email: 'Bill#gmail.com', password: '123456', password_confirmation: '123456')
Post.create([
{
user_id: 1,
category_id: 1,
title: "Tech tattoos put a working circuit board on your skin",
url: "http://www.slashgear.com/tech-tattoos-put-a-working-circuit-board-on-your-skin-25416060/"
},
{
user_id: 2,
category_id: 1,
title: "This robot can print emoji on your fingernails",
url: "http://mashable.com/2015/11/24/nailbot-printed-manicure/#Rml2qXalMmqp"
},
{
user_id: 3,
category_id: 2,
title: "Thiago Silva scores a goal from behind the goal",
url: "http://www.gyfbin.com/2015/11/hgfp.gif.html"
}])
Have a simple way to you can see error message at. You can use bang (!) after create method (ex: User.create!(.....), Post.create!(.....)). Console will raise error message when have any errors.
If you do same that. you can search yourself error.
destroy_all doesn't drop the table. First you ran the seed file. so, 5 users were created with ID (1 to 5). It destroys the USERS but not truncate. Then you destroy those users. Again ran the seed file. Now the 5 users were created with ID (6 to 10). So, there is no user_id with 1 anymore. It may be the problem.
solution 1: You can drop the tables (user, post) and then migrate and seed.
solution 2:
pick user ids randomly. Use:
users = User.all.collect{|u| u.id}
# same goes for category.
Post.create([
{
user_id: users.sample,
category_id: 1,
title: "Tech tattoos put a working circuit board on your skin",
url: "http://www.slashgear.com/tech-tattoos-put-a-working-circuit-board-on-your-skin-25416060/"
},
{
user_id: users.sample,
category_id: 1,
title: "This robot can print emoji on your fingernails",
url: "http://mashable.com/2015/11/24/nailbot-printed-manicure/#Rml2qXalMmqp"
},
{
user_id: users.sample,
category_id: 2,
title: "Thiago Silva scores a goal from behind the goal",
url: "http://www.gyfbin.com/2015/11/hgfp.gif.html"
}])
Hope it helps!

How to create seeds.rb array?

I'd like to populate the Department table using the seeds.rb file. I've created only two columns in the table. There are three more created by rails (id, created_at, updated_at).
When I run rake db:seed, I get the following error:
ArgumentError: wrong number of arguments (3 for 0..1)
Here's what the seeds.rb file looks like:
departments = Department.create([{ depttitle: 'dept 1' }, { deptdescription: 'this is the first dept' }],
[{ depttitle: 'dept 2' }, { deptdescription: 'this is the second dept' }],
[{ depttitle: 'dept 3' }, { deptdescription: 'this is the third dept' }])
Is the issue with how I've created the array or something else?
The reason it didn't work is that you actually passed three arrays with two hashes in each of them.
Pass a single array to the #create method with a single hash for each record you want to create.
For example:
Department.create([{ deptitle: 'dept 1', deptdescription: 'this is the first dept' },
{ depttitle: 'dept 2', deptdescription: 'this is the second dept' }])
But instead of 'creating an array' you could use a simple loop to create Department records.
10.times do |x|
Department.create({deptitle: "dept #{x}", deptdescription: "this is the #{x} department"})
end
In my opinion it looks cleaner, takes less place and it is easier to change number of seed records if you need to.
To create a numeral from a number (for "this is the Xst dept" sentence) you could use a humanize gem.
The way we do it is as follows:
departments = [
{depttitle: "Title", deptdescription: "description"},
{depttitle: "Title2", deptdescription: "description2"},
{depttitle: "Title3", deptdesctiption: "description3"}
]
You can then loop through them like this:
departments.each do |department|
Department.create department
end
#Sebastian Brych's answer is right though - you're passing arrays for each new record when you should pass a single array with multiple hashes.
You can create your records separately as shown below.
Department.create(depttitle: 'dept 1' , deptdescription: 'this is the first dept')
Department.create(depttitle: 'dept 2' , deptdescription: 'this is the second dept')

Multikey indexing in rails mongoid

I want to store data in this format.
{
"_id": ObjectId(...)
"title": "Grocery Quality"
"comments": [
{ author_id: ObjectId(...)
date: Date(...)
text: "Please expand the cheddar selection." },
{ author_id: ObjectId(...)
date: Date(...)
text: "Please expand the mustard selection." },
{ author_id: ObjectId(...)
date: Date(...)
text: "Please expand the olive selection." }
]
}
I'm confused as to how to achieve this format for my data.
I am using mongoid; does Mongoid support Multikey Indexing?
How can use mongoid to achieve my desired format and behaviour?
I'm not sure if I got your doubt correctly but as I can't comment I'm answering right away. If it isnt this what you asked, please explain a little bit more =)
You have your model with those fields you wrote before, I will call it Post model. For the comments on it, I would suggest you create another model callend Comment and embed it on the Post model:
class Post
field: title
embeds_many :comments
end
class Comment
field :date
field :text
has_one :author
embedded_in :post
end
And to index the comments on the Post model you could do:
index({ :"comments.updated_at" => 1 })

Rails3/Mongoid - Basic db:seed with embedded documents

I'm using MongoID with rails 3.1. and I would like to seed my database (both in dev and production). I have a Pages model with Feeds embedded. What's the best way for me to seed the embedded feeds for each page? I can easily seed all of the page data just not the embedded feeds. Please note that I'm looking to actual have real unique data for these pages/feeds not just arbitrary test data. thanks!
page.rb (model)
...
embeds_many :feeds
feed.rb (model)
class Feed
include Mongoid::Document
field :source, :type => String
field :user, :type => String
embedded_in :page, :inverse_of => :feeds
end
db/seeds.rb
Page.create(title: "Page 1", userID: "EMAIL#gmail.com", presentation: 'cards', customURL: 'testing1')
Page.create(title: "Page 2", userID: "EMAIL#gmail.com", presentation: 'cards', customURL: 'testing2')
Page.create(title: "Page 3", userID: "EMAIL#gmail.com", presentation: 'cards', customURL: 'testing3')
Page.create(title: "Page 4", userID: "EMAIL#gmail.com", presentation: 'cards', customURL: 'testing4')
Page.create(title: "Page 5", userID: "EMAIL#gmail.com", presentation: 'cards', customURL: 'testing5')
How best can I embed some feed data in each page? Thanks much.
Page.create(title: "blah", feeds: [
Feed.new(source: "blahblah", user: "me!"),
Feed.new(....),
Feed.new(.....),
])
Is how I do it in my db:seed, I even have a few that are multiple documents deep.
You can do something like this:
(1..5).each do |i|
page = Page.create(title: "Page #{i}", userID: "EMAIL#gmail.com", presentation: 'cards', customURL: "testing#{i}")
3.times { Feed.create(page: page) }
end

Resources