Why isn't my sample data uploading to the sqlite database? - ruby-on-rails

I can't figure out why this code is not populating my sqlite database. I am using the faker gem with rails 3.2 and am trying to make a twitter like application. Can anyone find the problem?
namespace :db do
desc "Fill database with sample data"
task populate: :environment do
def make_users
User.create!(name: "Example User",
email: "example#example",
password: "foobar",
password_confirmation: "foobar")
99.times do |n|
name = Faker::Name.name
email = "example-#{n+1}#example.org"
password = "password"
User.create!(name: name,
email: email,
password: password,
password_confirmation: password)
end
end
def make_microposts
users = User.all(limit: 6)
50.times do
content = Faker::Lorem.sentence(5)
users.each { |user| user.microposts.create!(content: content) }
end
end
def make_relationships
users = User.all
user = users.first
followed_users = users[2..50]
followers = users[3..40]
followed_users.each { |followed| user.follow!(followed) }
followers.each { |follower| follower.follow!(user) }
end
end
end

I figured out the answer actually. Here is the correct code:
namespace :db do
desc "Fill database with sample data"
task populate: :environment do
make_users
make_microposts
make_relationships
end
end
def make_users
User.create!(name: "Example User",
email: "example#railstutorial.org",
password: "foobar",
password_confirmation: "foobar")
99.times do |n|
name = Faker::Name.name
email = "example-#{n+1}#railstutorial.org"
password = "password"
User.create!(name: name,
email: email,
password: password,
password_confirmation: password)
end
end
def make_microposts
users = User.all(limit: 6)
50.times do
content = Faker::Lorem.sentence(5)
users.each { |user| user.microposts.create!(content: content) }
end
end
def make_relationships
users = User.all
user = users.first
followed_users = users[2..50]
followers = users[3..40]
followed_users.each { |followed| user.follow!(followed) }
followers.each { |follower| follower.follow!(user) }
end

Related

Google Omniauth2 Rails Giving me "Example User" when testing

I am attempting to stub out an omniauth authentication hash to test my integration with RSpec. For some reason my User model is being fed an "Example User," that does not have all the info a regular signed in Google user would have.
This is the param given to User that is breaking the tests: {"provider"=>"default", "uid"=>"1234", "info"=>{"name"=>"Example User"}}
This is what it should be, and if I step to the next iteration with pry, it works:
{:provider=>"google",
:uid=>"12345678910",
:info=>{:email=>"limsammy1#gmail.com", :first_name=>"Sam", :last_name=>"Lim"},
:credentials=>{:token=>"abcdefg12345", :refresh_token=>"12345abcdefg", :expires_at=>Thu, 16 Nov 2017 15:27:23 -0700}}
Here is my spec:
require 'rails_helper'
def stub_omniauth
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:google] = OmniAuth::AuthHash.new({
provider: "google_oauth2",
uid: "12345678910",
info: {
email: "limsammy1#gmail.com",
first_name: "Sam",
last_name: "Lim"
},
credentials: {
token: "abcdefg12345",
refresh_token: "abcdefg12345",
expires_at: DateTime.now,
}
})
end
RSpec.feature "user logs in" do
scenario "using google oauth2 'omniauth'" do
stub_omniauth
visit root_path
expect(page).to have_link("Sign in with Google")
click_link "Sign in with Google"
expect(page).to have_content("Sam Lim")
expect(page).to have_content("Logout")
end
end
And here is my User model method:
def self.update_or_create(auth)
user = User.find_by(uid: auth[:uid]) || User.new
binding.pry
user.attributes = {
provider: auth[:provider],
uid: auth[:uid],
email: auth[:info][:email],
first_name: auth[:info][:first_name],
last_name: auth[:info][:last_name],
token: auth[:credentials][:token],
refresh_token: auth[:credentials][:refresh_token],
oauth_expires_at: auth[:credentials][:expires_at]
}
user.save!
user
end
I call that method in my sessions controller here:
def create
user = User.update_or_create(request.env["omniauth.auth"])
session[:id] = user.id
redirect_to root_path
end
I came across exactly this issue some days ago.
The problem is in def stub_omniauth.
You should change OmniAuth.config.mock_auth[:google] => OmniAuth.config.mock_auth[:google_oauth2]

Db doesn't seed: how to determine the cause?

None of the data in seeds.rb is loaded into the development db. There is no error message. How can I determine the cause?
If I run rake:db:migrate:reset it just runs and produces no error messages. The if I go to the console, run User.first, it says nil. Also I downloaded the development db and there are no records in it (tables are created correctly, just no records).
Is there some way to trace the cause?
Part of seeds.rb:
User.create!(fullname: "Example User",
username: "fakename0",
email: "example#railstutorial.org",
admin: true,
activated: true,
activated_at: Time.zone.now,
password: "foobar",
password_confirmation: "foobar")
User.create!(fullname: "Example User 2",
username: "fawwkename0",
email: "exaaample#railstutorial.org",
admin: false,
activated: true,
activated_at: Time.zone.now,
password: "foobar",
password_confirmation: "foobar")
99.times do |n|
fullname = Faker::Name.name
username = "fakename#{n+1}"
email = "example-#{n+1}#railstutorial.org"
password = "password"
User.create!(fullname: fullname,
username: username,
email: email,
password: password,
password_confirmation: password,
activated: true,
activated_at: Time.zone.now)
end
Message.create!(email: "example#example.com",
name: "Example User",
content: "This is my message")
Organization.create!(org_name: "Fictious business",
bio: "The background of the organization here",
actioncode: 111)
99.times do |n|
org_name = Faker::Company.name
bio = Faker::Lorem.paragraph(2)
actioncode = Faker::Number.number(3)
Organization.create!(org_name: org_name,
bio: bio,
actioncode: actioncode)
end
Member.create!(organization_id: rand(1..100),
email: "me#example.com",
username: "fake-name0",
fullname: Faker::Name.name,
activated: 1,
activated_at: Time.zone.now,
password: "foobar",
password_confirmation: "foobar")
99.times do |n|
organization_id = rand(1..100)
email = "rails0-#{n+1}#example.com"
username = "fake-name#{n+1}"
fullname = Faker::Name.name
activated = rand(0..1)
activated_at = Faker::Date.backward(14) if activated==1
password = "foobar"
password_confirmation = "foobar"
Member.create!(organization_id: organization_id,
email: email,
username: username,
fullname: fullname,
activated: activated,
activated_at: activated_at,
password: password,
password_confirmation: password_confirmation)
end
To load db/seeds.rb you need to run rake db:seed.

Ruby on Rails, Michael Hartl;s Tutorial chapter 6.31

I got two tests that are failing in my application. I see that the problem is with the user's ID but I don't know how to solve it.
1) User return value of authenticate method with valid password
Failure/Error: it { should eq found_user.authenticate(#user.password) }
expected: #<User id: 2, name: "Example User", email: "user#example.com", created_at: "2014-08-09 17:17:22", updated_at: "2014-08-09 17:17:22", password_digest: "$2a$04$kQk6PkLu3X6rbTPiDDPce.zy6VYtAZ2rxchGLSP27VaG...">
got: #<User id: nil, name: "Example User", email: "user#example.com", created_at: nil, updated_at: nil, password_digest: "$2a$04$dccvbYxyrCa2M1LjxmwQqOBEEhYLNKrFmUh0GlAxH1bH...">
(compared using ==)
Diff:
## -1,2 +1,2 ##
-#<User id: 2, name: "Example User", email: "user#example.com", created_at: "2014-08-09 17:17:22", updated_at: "2014-08-09 17:17:22", password_digest: "$2a$04$kQk6PkLu3X6rbTPiDDPce.zy6VYtAZ2rxchGLSP27VaG...">
+#<User id: nil, name: "Example User", email: "user#example.com", created_at: nil, updated_at: nil, password_digest: "$2a$04$dccvbYxyrCa2M1LjxmwQqOBEEhYLNKrFmUh0GlAxH1bH...">
# ./spec/models/user_spec.rb:102:in `block (4 levels) in <top (required)>'
2) User email address with mixed case should be saved as all lower-case
Failure/Error: expect(#user.reload.email).to eq mixed_case_email.downcase
ActiveRecord::RecordNotFound:
Couldn't find User without an ID
# ./spec/models/user_spec.rb:72:in `block (3 levels) in <top (required)>'
Here is my user_spec.rb file :
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
end
subject {#user}
it {should respond_to(:name)}
it {should respond_to(:email)}
it {should respond_to(:password_digest)}
it {should respond_to(:password)}
it {should respond_to(:password_confirmation)}
it {should respond_to(:authenticate)}
describe "When name is not present" do
before {#user.name = " "}
it {should_not be_valid}
end
describe "When email is not present" do
before {#user.email = " "}
it {should_not be_valid}
end
describe "When name is too long" do
before {#user.name = "a"*51}
it {should_not be_valid}
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org example.user#foo.
foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
#user.email = invalid_address
expect(#user).not_to be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[user#foo.COM A_US-ER#f.b.org frst.lst#foo.jp a+b#baz.cn]
addresses.each do |valid_address|
#user.email = valid_address
expect(#user).to be_valid
end
end
end
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
describe "email address with mixed case" do
let(:mixed_case_email) { "Foo#ExAMPle.CoM" }
it "should be saved as all lower-case" do
#user.email = mixed_case_email
#user.save
expect(#user.reload.email).to eq mixed_case_email.downcase
end
end
#PASSWORD
describe "when password is not present" do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: " ", password_confirmation: " ")
it { should_not be_valid }
end
end
describe "when password doesn't match confirmation" do
before { #user.password_confirmation = "mismatch" }
it { should_not be_valid }
end
describe "with a password that's too short" do
before { #user.password = #user.password_confirmation = "a" * 5 }
it { should be_invalid }
end
describe "return value of authenticate method" do
before { #user.save }
let(:found_user) { User.find_by(email: #user.email) }
describe "with valid password" do
it { should eq found_user.authenticate(#user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not eq user_for_invalid_password }
specify { expect(user_for_invalid_password).to be_false }
end
end
end
And the user.rb file
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
end
Change
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
to
#user = User.create(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
new just creates a model but doesnt save it to DB whereas
create creates the model AND saves it to DB
other option is to use save
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
#user.save
(For the 2ยบ test) You have to save the user in a before block
describe "email address with mixed case" do
let(:mixed_case_email) { "Foo#ExAMPle.CoM" }
before do
#user.email = mixed_case_email
#user.save
end
it "should be saved as all lower-case" do
expect(#user.reload.email).to eq mixed_case_email.downcase
end
end
That is the problem which causes "Couldn't find User without an ID"
The error is here:
specify { expect(user_for_invalid_password).to be_false }
this line is wrong, correct one is:
specify { expect(user_for_invalid_password).to be false }

How do I keep a controller spec and its mocks DRY?

I'm told this is the correct way to write a controller it block:
describe UsersController do
let(:user){ mock_model(User, id: 2, name: "Jimbo", email: 'jimbo#email.com', password: 'passwordhuzzah', password_confirmation: 'passwordhuzzah') }
describe 'PATCH #update' do
it "should fail in this case" do
User.should_receive(:find).with(user.id.to_s).and_return user
user.should_receive(:update_attributes).with({ "email" => user.email, "name" => user.name, "password" => user.password, "password_confirmation" => user.password_confirmation }).and_return true
patch :update, id: user.id, user: { email: user.email, name: user.name, password: user.password, password_confirmation: user.password_confirmation }
flash[:error].should == "could not update user"
response.status.should == 200
end
end
end
But I am surprised, because it doesn't seem DRY to me. Let's say I want to create two 'contexts' here. One where the user.update_attributes call returns false and returns true. Am I meant to simply copy paste two it blocks and tweak that one tiny argument?
describe UsersController do
let(:user){ mock_model(User, id: 2, name: "Jimbo", email: 'jimbo#email.com', password: 'passwordhuzzah', password_confirmation: 'passwordhuzzah') }
it "should pass in this case" do
User.should_receive(:find).with(user.id.to_s).and_return user
user.should_receive(:update_attributes).with({ "email" => user.email, "name" => user.name, "password" => user.password, "password_confirmation" => user.password_confirmation }).and_return true
patch :update, id: user.id, user: { email: user.email, name: user.name, password: user.password, password_confirmation: user.password_confirmation }
flash[:error].should == "updated user"
response.status.should == 302
end
it "should fail in this case" do
User.should_receive(:find).with(user.id.to_s).and_return user
user.should_receive(:update_attributes).with({ "email" => user.email, "name" => user.name, "password" => user.password, "password_confirmation" => user.password_confirmation }).and_return false
patch :update, id: user.id, user: { email: user.email, name: user.name, password: user.password, password_confirmation: user.password_confirmation }
flash[:error].should == "could not update user"
response.status.should == 200
end
end
end
I was hoping rspec would allow me to write this sort of structure:
describe 'PATCH #update' do
before {}
context 'when attributes can be updated' do
before {}
it "should set the flash" do end
it "should set the status" do end
end
context 'when attributes can\'t be updated' do
before {}
it "should set the status" do end
it "should set the flash" do end
end
end
Note the multiple it blocks for the same contexts, because isn't one expectation per it block a good practise because it allows you to see exactly what's not working? How are you meant to do this with mocks?

Populating database with faker

I want to populate the database with a number of stores and users, that each user corresponds to one store. The issue with the code below is that I get the error Validation failed: Email has already been taken.
namespace :db do
desc "Fill database with sample data"
task populate: :environment do
make_stores
make_users
end
end
def make_stores
50.times do
name = Faker::Company.name
manager = Faker::Name.name
address = Faker::Address.street_name
Store.create!(name: name,
manager: manager,
address: address)
end
end
def make_users
stores = Store.all(limit: 8)
99.times do |n|
first_name = Faker::Name.first_name
last_name = Faker::Name.last_name
email = "example-#{n+1}#example.org"
password = "password"
stores.each { |store| store.users.create!(first_name: first_name,
last_name: last_name,
email: email,
password: password,
password_confirmation: password) }
end
end
The problem is that you're setting the email variable before calling stores.each, so all 8 stores will get a user with the same email.
Do something like this instead:
def make_users
stores = Store.all(limit: 8)
99.times do |n|
password = "password"
stores.each do |store|
first_name = Faker::Name.first_name
last_name = Faker::Name.last_name
email = "#{store.name.parameterize}-#{n+1}#example.org"
store.users.create!(first_name: first_name,
last_name: last_name,
email: email,
password: password,
password_confirmation: password)
end
end
end
Now the first 8 users will have an email like (some-store-name)-1#example.org, next 8 will have (some-store-name)-2#example.org and so on.

Resources