Can't seed database after using destroy_all from command line - ruby-on-rails

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!

Related

Rails. Create an object with its association in one transaction

I need to create an object with the associated item all in the step of creation.
Although I have tried creating first, and then second, this gives problems in the way that if the second fails, then I get with the first part half done.
Relationship one user has many companies
I mean something like
user = User.create!(
email: prospect.email,
first_name: prospect.first_name,
last_name: prospect.last_name,
#birthdate:prospect.user_birthday,
id_number: prospect.id_number,
phone: prospect.phone,
address: prospect.address,
password: prospect.id_number,
password_confirmation: prospect.id_number,
company = user.companies.create(
name: prospect.vat_company_name,
plan: prospect.plan,
address: prospect.address,
description: prospect.company_description,
email: prospect.email,
phone: prospect.phone,
network_id: prospect.network_id
)
current_company_id: company.id
)
which of course fails because maybe it can't be done directly.
I have tried build instead of create, but same result.
I also know that second create will fail because the first object doesn't exist yet.
How is the best way?
You can create them both separately and wrap them in a transaction:
ActiveRecord::Base.transaction do
user = User.create!(...)
company = Company.create!(...)
end
This way if one of them fails, the other doesn't end up being committed to the database.
If you are talking about separate instance storage then using a db transaction lock is the way to go forward as mentioned by Danial. But if you only need to create an associated record of active record then you can do with Active Record only. It would make sure that both records are saved.
user = User.new
email: prospect.email,
first_name: prospect.first_name,
last_name: prospect.last_name,
#birthdate:prospect.user_birthday,
id_number: prospect.id_number,
phone: prospect.phone,
address: prospect.address,
password: prospect.id_number,
password_confirmation: prospect.id_number
user.build_current_company
name: prospect.vat_company_name,
plan: prospect.plan,
address: prospect.address,
description: prospect.company_description,
email: prospect.email,
phone: prospect.phone,
network_id: prospect.network_id
user.save!
This will create both user and it's current company.
(I am taking an assumption that you have belongs_to :current_company,class_name: 'Company' in user.rb)

RSpec - failing test unless local variable is called from pry point

I have the following code:
## teams_controller.rb
def destroy
ActiveRecord::Base.transaction do
team_admins = team.team_admins
binding.pry
team.destroy!
team_admins.each(&:update_team_admin_role_if_needed!)
end
respond_with_200(team, serializer: V1::User::Management::TeamSerializer)
end
And the corresponding spec to ensure the last line of the above code fires:
## teams_controller_spec.rb
it 'demotes team admins to employees when needed' do
team_admin_account = create(:account)
admin_team_membership = create(:team_membership, team: #team, admin: true, account: team_admin_account)
team_admin_account.update!(role: Role.team_admin)
expect { process_destroy(team_id: #team.slug) }
.to change { team_admin_account.reload.role }
.from(Role.team_admin)
.to(Role.employee)
end
When I use the above code in my application it works as expected, however the spec fails as the account apparently never has their role updated:
expected `team_admin_account.reload.role` to have changed from #<Role id: 4, add_to_first_user_in_organisation: false, title: "Team admin", created_at: "2020-01-03 09:04:28", updated_at: "2020-01-03 09:04:28", management: false, cms_access: false> to #<Role id: 3, add_to_first_user_in_organisation: false, title: "Employee", created_at: "2020-01-03 09:04:28", updated_at: "2020-01-03 09:04:28", management: false, cms_access: false>, but did not change
When I hit the pry point in my spec and quit out straight away, the spec fails. Likewise when there is no pry point.
However when I enter team_admins at the pry point (which returns the one team_admin I create in my spec) and then quit out of the spec, the spec passes and the account has their role updated.
Anyone have any idea why manually calling team_admins makes my spec pass?
Thanks in advance
EDIT:
The following change to the code also makes the spec pass:
def destroy
ActiveRecord::Base.transaction do
team_admins = team.team_admins
puts team_admins ## <---- Adding this makes the spec pass
team.destroy!
team_admins.each(&:update_team_admin_role_if_needed!)
end
respond_with_200(team, serializer: V1::User::Management::TeamSerializer)
end
team_admins is an AssociationRelation from team. This does not execute a query until referenced, such as with each or puts.
team.destroy! is called before team_admins.each is called. So when team_admins.each executes there is no more team and thus no team_admins. You should be able to verify this by watching logs/test.log and looking at the queries and when they are executed.
Congratulations, you've found a bug. Execute team_admins.each before destroying team.

Ruby on rails: Session/current_user, db-insert

I'm having problems with an insert to the database. First an explanation of my little Blog app.
The models: Users och Posts. http://pastie.org/2694864
A post have columns: title, body, user id
3 controllers:
Session, Application (with current_user) and PostController: http://pastie.org/2695386
My loggin session seems to work but when a logged in user shoult write a post the database doesn't recognize any user_id. It's just set to nil. rails console:
=> #<Post id: 17, title: "hello", body: "hello world", created_at: "2011-10-14 14:54:25", updated_at: "2011-10-14 14:54:25", user_id: nil>
I guess it's in the post controller line 88 this should be fixed but I can't figure it out.
I have also tried:
#post = Post.new(params[:post], :user_id => session[:user_id])
But the user_id stills sets to nil!
This is my first app so I would be really greatful for detaild answears.
Tanx!
The problem is that you're passing Post.new two arguments (two hashes in this case), but it only takes one argument. Try this:
#post = Post.new(params[:post].merge!(:user_id => session[:user_id]))

Most efficient method of finding a model by ID with Model.find

I noticed that I can do a Model.find in a number of ways (assuming #user is an instance of the User model):
User.find(2)
=> #<User id: 2, name: "Mike Swift", email: "valid#email.com", ... etc ...
OR
User.find(#user)
=> #<User id: 2, name: "Mike Swift", email: "valid#email.com", ... etc ...
OR
User.find(#user[:id])
=> #<User id: 2, name: "Mike Swift", email: "valid#email.com", ... etc ...
OR
User.find(#user.id)
=> #<User id: 2, name: "Mike Swift", email: "valid#email.com", ... etc ...
Is there any real difference between the later three of these methods? (I already know User.find(n) would be the fastest) I would imagine they all work in about the same time, but perhaps I'm wrong.
In terms of sql they all do the same thing.
User.find(2)
This will be the fastest because there is no conversion needed.
Then User.find(#user.id) and User.find(#user[:id]).
And finally User.find(#user because rails needs convert the user to an ID.
User.find(2) should be faster as Rails doesn't have to do any work to figure out the id. The others require some level of message passing to get the id.
I doubt the difference is very significant though.
You could try all of them and look at your log to see how long it takes to get your response.

Can I scope dynamic attribute-based finders to an object?

Don't mind me, I fricked up my attribute names :(
This is entirely possible, using the exact syntax I used - you just need to be able to spell!
I can't seem to get this to work, and it seems like a common enough scenario that there must be a solution, but I'm not having any luck with the correct terminology to get a helpful Google result.
I want to do this:
u = User.first
u.clients.find_or_create_by_email('example#example.com')
With the effect that a new Client is created with user_id = u.id.
Can I get the nice dynamic finders through a has_many relationship? If not, why?
Thanks :)
This
u = User.first
u.clients.find_or_create_by_email('example#example.com')
works if you have has_many relationship set. However, it won't raise validation error if you have any validations set on your Client object and it will silently fail if the validation fails.
You can check the output in your console when you do
u.clients.find_or_create_by_email('example#example.com') # => #<Client id: nil, email: 'example#example.com', name: nil, user_id: 1, another_attribute: nil, active: true, created_at: nil, updated_at: nil>
and the user_id will be set but not the id of client because the validation has failed and the client is not created
So this should create the client only if you pass all the required attributes of client object and the validation for client object has passed successfully.
So lets say your client model has validation on name as well apart from email then you should do
u.clients.find_or_create_by_email_and_name('example#example.com', 'my_name') #=> #<Client id: 1, email: 'example#example.com', name: 'my_name', user_id: 1, another_attribute: nil, active: true, created_at: "2009-12-14 11:08:23", updated_at: "2009-12-14 11:08:23">
This is entirely possible, using the exact syntax I used - you just need to be able to spell!

Resources