I am using RSpec to test my controller actions and have been successfully tested my index, show, edit actions so far. But for create action it is giving me the following error for valid attributes. I'm using rails 5 and ruby 2.5.3. Can't understand what am I doing wrong.
file /spec/factories/leaves.rb
FactoryBot.define do
factory :leave do
id {Faker::Number.between(from = 1, to = 3)}
user_id {Faker::Number.between(from = 1, to = 3)}
team_lead_id {Faker::Number.between(from = 1, to = 3)}
fiscal_year_id {Faker::Number.between(from = 1, to = 3)}
start_day {Date.today - Faker::Number.number(3).to_i.days}
end_day {Date.today - Faker::Number.number(3).to_i.days}
reason {Faker::Lorem.sentences(sentence_count = 3, supplemental = false)}
status {Faker::Number.between(from = 1, to = 3)}
factory :invalid_leave do
user_id nil
end
end
end
file /spec/controllers/leave_controller_spec.rb
context 'with valid attributes' do
it 'saves the new leave in the database' do
leave_params = FactoryBot.attributes_for(:leave)
expect{ post :create, params: {leave: leave_params}}.to change(Leave,:count).by(1)
end
it 'redirects to leave#index' do
render_template :index
end
end
file /app/controller/leave_controller.rb
def create
#leave = Leave.new(leave_params)
if #leave.save
flash[:notice] = t('leave.leave_create')
redirect_to leave_index_path
else
flash[:notice] = t('leave.leave_create_error')
redirect_to leave_index_path
end
end
The error is:
LeaveController POST#create with valid attributes saves the new leave in the database
Failure/Error: expect{ post :create, params: {leave: leave_params}}.to change(Leave,:count).by(1)
expected `Leave.count` to have changed by 1, but was changed by 0
# ./spec/controllers/leave_controller_spec.rb:64:in `block (4 levels) in <top (required)>'
Update Leave Database
create_table "leaves", force: :cascade do |t|
t.integer "user_id", null: false
t.integer "team_lead_id", null: false
t.integer "fiscal_year_id", null: false
t.date "start_day", null: false
t.date "end_day", null: false
t.text "reason", null: false
t.integer "status", null: false
t.string "comment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Leave Model
class Leave < ApplicationRecord
validates :user_id, :team_lead_id, :fiscal_year_id, :start_day, :end_day, :reason, :status, presence: true
end
I think that might be because of id which you set in factory. You shouldn't set id attribute in factory. That's why number of Leave objects didn't change.
Additionally, I assume that you have some relations there - user_id, team_lead_id etc. If these relations are necessarry to create leave object then you have to create factories for these models, too.
In the end your factory should look like this
FactoryBot.define do
factory :leave do
user
team_lead
fiscal_year
start_day {Date.today - Faker::Number.number(3).to_i.days}
end_day {Date.today - Faker::Number.number(3).to_i.days}
reason {Faker::Lorem.sentences(sentence_count = 3, supplemental = false)}
status {Faker::Number.between(from = 1, to = 3)}
factory :invalid_leave do
user nil
end
end
end
Reference: Factory Bot documentation - associations
[For Future Reader] I got it to work by doing the fooling in leave_controller_spec.rb file.
describe 'POST#create' do
context 'with valid attributes' do
let(:valid_attribute) do
attributes_for(:leave,
user_id: 2,
team_lead_id: 3,
fiscal_year_id: 2,
start_day: '2018-10-10'.to_date,
end_day: '2018-10-10'.to_date,
reason: 'Sick',
status: 2)
end
it 'saves the new leave in the database' do
expect do
post :create, params: {leave: valid_attribute}
end.to change(Leave,:count).by(1)
end
it 'redirects to leave#index' do
render_template :index
end
end
Related
I am using graphiql-ruby gem for using graphql. I am trying to get the list of users with its userprofile and its company. However, it consumes more than 5 minutes and hits the api several times. It even crashes my server. Can anyone help me at this, please?
this is what i have done
module Queries
module Users
extend ActiveSupport::Concern
include GraphQL::Schema::Member::GraphQLTypeNames
included do
field :users, [Types::UserType], null: false
field :user, Types::UserType, null: false do
argument :id, ID, required: true
end
field :currentUser, Types::UserType, null: false
end
# Get all users list except admins
def users
User.where.not(roles: ['admin'])
# context[:current_user].logs.info!('User Data Fetched') && user
end
def user(id:)
User.find(id)
end
def current_user
context[:current_user]
end
end
end
module Types
class UserType < Types::BaseObject
field :id, ID, null: false
field :email, String, null: false
field :user_profile, Types::UserProfileType, null: false
field :grants, [Types::GrantType], null: true
field :companies, [Types::CompanyType], null: true
field :my_companies_with_grants, [Types::CompanyGrantType], null: true
def grants
Grant.where(user_id: object.id)
end
def my_companies_with_grants
current_user = User.find_by(id: object.id)
company = current_user.companies
userid = current_user.id
company.map {|comp| { company: comp, grants: comp.get_user_grants(userid), company_id: comp.id } }
end
end
end
Here is how i am querying for the list of users
query {
employees: users {
id
email
userProfile {
...UserProfile
}
roles
createdAt
companies {
...Company
}
grants {
...Grant
}
}
}
${COMPANY}
${GRANT}
${USER_PROFILE}
why it is taking too long time to load all the users ? How can it be make efficient?
UPDATE
class ApiSchema < GraphQL::Schema
mutation(Types::MutationType)
query(Types::QueryType)
use GraphQL::Batch
end
Record loader
class RecordLoader < GraphQL::Batch::Loader
def initialize(model)
#model = model
end
def perform(ids)
#model.where(id: ids).each { |record| fulfill(record.id, record) }
ids.each { |id| fulfill(id, nil) unless fulfilled?(id) }
end
end
I changed my user_type.rb and did the following for user_profile
field :user_profile, [Types::UserProfileType, null: true], null: false do
argument :id, [ID], required: true
end
def user_profile(ids:)
RecordLoader.for(UserProfile).load_many(ids)
end
But i get "message":"Field 'userProfile' is missing required arguments: ids" issue
I setup the graphql-batch but could not figure out where should i use RecordLoader as per the way I am using(types and resolvers)
I can't seem to figure out why my PartTransactions test keep failing for updating and creating. All of my other test are successful so, to me I feel like I'm maybe doing something incorrectly in my fixtures - any suggestions would be greatly appreciated!
Here are the failure results when I run my test
Running via Spring preloader in process 62590
Started with run options --seed 23873
FAIL["test_should_create_part_transaction", #<Minitest::Reporters::Suite:0x00007f96615c1710 #name="PartTransactionsControllerTest">, 0.644004000001587]
test_should_create_part_transaction#PartTransactionsControllerTest (0.64s)
"PartTransaction.count" didn't change by 1.
Expected: 3
Actual: 2
test/controllers/part_transactions_controller_test.rb:19:in `block in <class:PartTransactionsControllerTest>'
FAIL["test_should_update_part_transaction", #<Minitest::Reporters::Suite:0x00007f966163a548 #name="PartTransactionsControllerTest">, 0.6869309999747202]
test_should_update_part_transaction#PartTransactionsControllerTest (0.69s)
Expected response to be a <3XX: redirect>, but was a <200: OK>
test/controllers/part_transactions_controller_test.rb:38:in `block in <class:PartTransactionsControllerTest>'
21/21: [===========================================================================================================================================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.77788s
21 tests, 26 assertions, 2 failures, 0 errors, 0 skips
Here is my schema.rb
ActiveRecord::Schema.define(version: 2019_01_30_150153) do
create_table "customers", force: :cascade do |t|
t.string "cust_id"
t.string "cust_name"
t.integer "cust_status"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "part_transactions", force: :cascade do |t|
t.integer "trans_id"
t.datetime "trans_date"
t.decimal "trans_qty", precision: 14, scale: 4
t.string "trans_type"
t.string "invoiced"
t.decimal "cs_trans_qty", precision: 6, scale: 2
t.integer "part_id"
t.integer "customer_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["customer_id"], name: "index_csi_part_transactions_on_customer_id"
t.index ["part_id"], name: "index_csi_part_transactions_on_part_id"
end
create_table "parts", force: :cascade do |t|
t.string "part_id"
t.string "description"
t.decimal "qty_on_hand", precision: 14, scale: 4
t.decimal "order_point", precision: 14, scale: 4
t.decimal "reorder_qty", precision: 14, scale: 4
t.string "part_type"
t.string "status"
t.string "inv_cs"
t.decimal "cs_qty", precision: 3
t.string "cs_status"
t.integer "customer_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["customer_id"], name: "index_csi_parts_on_customer_id"
end
end
Here are my models
class Customer < ApplicationRecord
has_many :parts, :dependent => :destroy
has_many :part_transactions, :dependent => :destroy
end
class Part < ApplicationRecord
belongs_to :customer
has_many :part_transactions, :dependent => :destroy
end
class PartTransaction < ApplicationRecord
belongs_to :part
belongs_to :customer
end
Here are my fixtures
#Customer -------------------------------------------------------------
one:
cust_id: one
cust_name: My Company
cust_status: 3
two:
cust_id: two
cust_name: Other Company
cust_status: 1
#Parts-------------------------------------------------------------
one:
part_id: one
description: TestA
qty_on_hand: 2
order_point: 3
reorder_qty: 1
part_type: TestAPartType
status: F
inv_cs: 2
cs_qty: 3
cs_status: F
customer: one
two:
part_id: two
description: TestB
qty_on_hand: 1
order_point: 3
reorder_qty: 6
part_type: TestBPartType
status: F
inv_cs: 2
cs_qty: 3
cs_status: C
customer: two
#PartTransactions------------------------------------------------------
one:
trans_id: one
trans_date: 2019-01-31
trans_qty: 1
trans_qty: 1
trans_type: 1
invoiced: 1
cs_trans_qty: 1
cs_trans_qty: 1
part_id: one
customer: one
two:
trans_id: 2
trans_date: 2019-01-31
trans_qty: 3
trans_qty: 3
trans_type: 3
invoiced: 1
cs_trans_qty: 1
cs_trans_qty: 1
part_id: two
customer: two
Here is my PartTransaction Test
require 'test_helper'
class PartTransactionsControllerTest < ActionDispatch::IntegrationTest
setup do
#part_transaction = part_transactions(:one)
end
test "should get index" do
get part_transactions_url
assert_response :success
end
test "should get new" do
get new_part_transaction_url
assert_response :success
end
test "should create part_transaction" do
assert_difference('PartTransaction.count') do
post part_transactions_url, params: { part_transaction: { cs_trans_qty: #part_transaction.cs_trans_qty, customer_id: #part_transaction.customer_id, invoiced: #part_transaction.invoiced, part_id: #part_transaction.part_id, trans_date: #part_transaction.trans_date, trans_id: #part_transaction.trans_id, trans_qty: #part_transaction.trans_qty, trans_type: #part_transaction.trans_type } }
end
assert_redirected_to part_transaction_url(PartTransaction.last)
end
test "should show part_transaction" do
get part_transaction_url(#part_transaction)
assert_response :success
end
test "should get edit" do
get edit_part_transaction_url(#part_transaction)
assert_response :success
end
test "should update part_transaction" do
patch part_transaction_url(#part_transaction), params: { part_transaction: { cs_trans_qty: #part_transaction.cs_trans_qty, customer_id: #part_transaction.customer_id, invoiced: #part_transaction.invoiced, part_id: #part_transaction.part_id, trans_date: #part_transaction.trans_date, trans_id: #part_transaction.trans_id, trans_qty: #part_transaction.trans_qty, trans_type: #part_transaction.trans_type } }
assert_redirected_to part_transaction_url(#part_transaction)
end
test "should destroy part_transaction" do
assert_difference('PartTransaction.count', -1) do
delete part_transaction_url(#part_transaction)
end
assert_redirected_to part_transactions_url
end
end
Here is my PartTransactionsController
class PartTransactionsController < ApplicationController
before_action :set_part_transaction, only: [:show, :edit, :update, :destroy]
# GET /part_transactions
# GET /part_transactions.json
def index
#part_transactions = PartTransaction.all
end
# GET /part_transactions/1
# GET /part_transactions/1.json
def show
end
# GET /part_transactions/new
def new
#part_transaction = PartTransaction.new
end
# GET /part_transactions/1/edit
def edit
end
# POST /part_transactions
# POST /part_transactions.json
def create
#part_transaction = PartTransaction.new(part_transaction_params)
respond_to do |format|
if #part_transaction.save
format.html { redirect_to #part_transaction, notice: 'Part transaction was successfully created.' }
format.json { render :show, status: :created, location: #part_transaction }
else
format.html { render :new }
format.json { render json: #part_transaction.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /part_transactions/1
# PATCH/PUT /part_transactions/1.json
def update
respond_to do |format|
if #part_transaction.update(part_transaction_params)
format.html { redirect_to #part_transaction, notice: 'Part transaction was successfully updated.' }
format.json { render :show, status: :ok, location: #part_transaction }
else
format.html { render :edit }
format.json { render json: #part_transaction.errors, status: :unprocessable_entity }
end
end
end
# DELETE /part_transactions/1
# DELETE /part_transactions/1.json
def destroy
#part_transaction.destroy
respond_to do |format|
format.html { redirect_to part_transactions_url, notice: 'Part transaction was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_part_transaction
#part_transaction = PartTransaction.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def part_transaction_params
params.require(:part_transaction).permit(:trans_id, :trans_date, :trans_qty, :trans_qty, :trans_type, :invoiced, :cs_trans_qty, :cs_trans_qty, :part_id, :customer_id)
end
end
I don't know how I missed this but, I figured it out and it was caused by my part_transactions fixture - see below
I had part_id in my fixture when it should of been part (*smacks self on the head)
one:
trans_id: one
trans_date: 2019-01-31
trans_qty: 1
trans_qty: 1
trans_type: 1
invoiced: 1
cs_trans_qty: 1
cs_trans_qty: 1
#should be part not part_id
#part_id: one
part: one
customer: one
two:
trans_id: 2
trans_date: 2019-01-31
trans_qty: 3
trans_qty: 3
trans_type: 3
invoiced: 1
cs_trans_qty: 1
cs_trans_qty: 1
#should be part not part_id
#part_id: two
part: two
customer: two
I can't figure out how to fix RSpec errors.
My apps is like this.
There's 3 models, CompanyBag, CompanyBagTarget, Company.
CompanyBag is a group of Companies. CompanyBagTarget is association table between CompanyBag and Company.
Probably, CompanyBagTarget doesn't match appropriate Company.
Now, RSpec error is here.
1) CompanyBagsController POST #create creates a new ComapnyBag
Failure/Error: t.save!
ActiveRecord::InvalidForeignKey:
Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails (`eiicon`.`company_bag_targets`, CONSTRAINT `fk_bag_targets_company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`)): INSERT INTO `company_bag_targets` (`company_bag_id`, `company_id`, `display_order`) VALUES (38, 13, 0)
# ./app/models/company_bag.rb:22:in `block in update_targets!'
# ./app/models/company_bag.rb:16:in `each'
# ./app/models/company_bag.rb:16:in `each_with_index'
# ./app/models/company_bag.rb:16:in `update_targets!'
# ./app/controllers/company_bags_controller.rb:52:in `create'
# ./spec/controllers/company_bag_controller_spec.rb:55:in `block (4 levels) in <top (required)>'
# ./spec/controllers/company_bag_controller_spec.rb:54:in `block (3 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Mysql2::Error:
# Cannot add or update a child row: a foreign key constraint fails (`eiicon`.`company_bag_targets`, CONSTRAINT `fk_bag_targets_company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`))
# ./app/models/company_bag.rb:22:in `block in update_targets!'
2) CompanyBagsController POST #create creates a new ComapnyBagTarget
Failure/Error: t.save!
ActiveRecord::InvalidForeignKey:
Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails (`eiicon`.`company_bag_targets`, CONSTRAINT `fk_bag_targets_company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`)): INSERT INTO `company_bag_targets` (`company_bag_id`, `company_id`, `display_order`) VALUES (39, 13, 0)
# ./app/models/company_bag.rb:22:in `block in update_targets!'
# ./app/models/company_bag.rb:16:in `each'
# ./app/models/company_bag.rb:16:in `each_with_index'
# ./app/models/company_bag.rb:16:in `update_targets!'
# ./app/controllers/company_bags_controller.rb:52:in `create'
# ./spec/controllers/company_bag_controller_spec.rb:62:in `block (4 levels) in <top (required)>'
# ./spec/controllers/company_bag_controller_spec.rb:61:in `block (3 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Mysql2::Error:
# Cannot add or update a child row: a foreign key constraint fails (`eiicon`.`company_bag_targets`, CONSTRAINT `fk_bag_targets_company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`))
# ./app/models/company_bag.rb:22:in `block in update_targets!'
Next here's model's definitions.
class CompanyBag < ApplicationRecord
has_many :targets, class_name: "CompanyBagTarget"
def update_targets!(company_ids:)
destroy_targets
company_ids.reverse.each_with_index do |id, idex|
t = CompanyBagTarget.new
t.company_bag_id = self.id
t.company_id = id
t.display_order = idex
t.save!
end
end
class CompanyBagTarget < ApplicationRecord
belongs_to :company_target
Next, here's controller.
def create
#bag = CompanyBag.new(bag_params)
#target_ids = params[:company_bag][:target_ids].split(",").map{|n| n.split("_")[0].to_i}
if bag_params[:banner].present?
filename = upload_image
#bag.banner = filename
end
if #bag.save
#bag.update_targets!(company_ids: #target_ids)
redirect_to action: 'index'
else
flash[:alert] = #bag.errors.messages.values[0][0]
#target_ids = params[:company_bag][:target_ids]
render 'new'
end
end
Finally, here's controller's spec.
require 'rails_helper'
RSpec.describe CompanyBagsController, type: :controller do
login_admin
let(:user) { #admin }
let(:company_bag) { FactoryGirl.create(:some_company_bag) }
let(:company_bag_target) { {target_ids: "1_インテリジェンステスト株式会社,21_>グローバルウォーカーズ株式会社,33_株式会社コーデセブン"} }
let(:companies) { FactoryGirl.create(:companies) }
let(:valid_attributes) {
{
label: 1,
banner: "https://s3-ap-northeast-1.amazonaws.com/eiicon.prd.contents/image/bags/6dbd5b5b-f242-4e4a-bcd3-de3edc9ae08d.png",
title: "test title",
description: "test title",
target_ids: "1_インテリジェンステスト株式会社,21_グローバルウォーカーズ株>式会社,33_株式会社コーデセブン"
}
}
describe 'POST #create' do
it 'creates a new ComapnyBag' do
expect{
post :create, params: {company_bag: valid_attributes}, session: valid_session
}.to change(CompanyBag, :count).by(1)
end
it 'creates a new ComapnyBagTarget' do
expect{
post :create, params: {company_bag: valid_attributes}, session: valid_session
}.to change(CompanyBagTarget, :count).by(1)
end
Anyone, please. Thanks in advance.
[Appendix]
Next, here's factories.
FactoryGirl.define do
factory :some_company_bag, class: CompanyBag do
label "some label"
banner "https://s3-ap-northeast-1.amazonaws.com/eiicon.prd.contents/image/bags/6dbd5b5b-f242-4e4a-bcd3-de3edc9ae08d.png"
title "Best Company Title Ever!!"
description "Some says description"
html_description "Html desc"
html_keyword "Html Kw"
end
factory :companies, class: Company do
name "複数テスト会社"
name_kana "フクスウテストカイシャ"
premium_status "free"
pr_status_id 0
is_valid 1
after(:create) do |c|
c.staff << FactoryGirl.create(:staff, company_id: c.id)
end
end
end
And tables.
create_table "company_bag_targets", primary_key: ["company_bag_id", "company_id"], force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
t.integer "company_bag_id", null: false
t.integer "company_id", null: false
t.integer "display_order", null: false
t.index ["company_id"], name: "fk_bag_targets_company", using: :btree
end
create_table "company_bags", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
t.string "label", limit: 100, null: false
t.string "banner", limit: 300
t.string "title", limit: 300
t.text "description", limit: 65535
t.string "html_description", limit: 300
t.string "html_keyword", limit: 300
end
create_table "company", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
t.string "name", null: false
t.string "name_kana"
t.integer "prefecture_id"
t.string "url", limit: 1023
t.date "establishment"
I'm building an Events app in Rails and I've hit the error above which relates to this method in my Model -
def validate_availability
errors.add(:base, 'event is fully booked') if booking.count >= event.number_of_spaces
end
The purpose of the method is to avoid over-booking of an event whereby a specific number of spaces are available. In my Controller I have the following code -
Controller#Create
def create
#event = Event.find(params[:event_id])
#booking = #event.bookings.new(booking_params)
#booking.user = current_user
if
#booking.set_booking
flash[:success] = "Your place on our event has been booked"
redirect_to event_booking_path(#event, #booking)
else
flash[:error] = "Booking unsuccessful"
render "new"
end
if #event.is_free?
#booking.save(booking_params)
end
if booking.count >= #event.number_of_spaces
flash[:error] = "Sorry, this event is now fully booked"
render "new"
end
end
I need to define booking.count in my controller but not sure what would work - tried a few things but nothings working. I have the following in my schema -
create_table "bookings", force: :cascade do |t|
t.integer "event_id"
t.integer "user_id"
t.string "stripe_token"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "quantity", default: 1
t.integer "total_amount"
t.string "stripe_charge_id"
t.string "booking_number"
end
The booking.count would rely upon the quantity of spaces/bookings a user wishes to make versus the number of spaces remaining but how do I express this? Do I need a total_bookings column in my table or a separate method?
UPDATE -
Booking.rb
class Booking < ActiveRecord::Base
belongs_to :event
belongs_to :user
before_create :set_booking_number
validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :total_amount, presence: true, numericality: { greater_than_or_equal_to: 0 }
validate(:validate_booking)
validate(:validate_availability)
def set_booking_number
self.booking_number = "MAMA" + '- ' + SecureRandom.hex(4).upcase
end
def set_booking
if self.event.is_free?
self.total_amount = 0
save!
else
self.total_amount = event.price_pennies * self.quantity
begin
charge = Stripe::Charge.create(
amount: total_amount,
currency: "gbp",
source: stripe_token,
description: "Booking created for amount #{total_amount}")
self.stripe_charge_id = charge.id
save!
rescue Stripe::CardError => e
# if this fails stripe_charge_id will be null, but in case of update we just set it to nil again
self.stripe_charge_id = nil
# we check in validatition if nil
end
end
end
def validate_booking
# stripe_charge_id must be set for not free events
unless self.event.is_free?
return !self.stripe_charge_id.nil?
end
end
private
def validate_availability
errors.add(:base, 'event is fully booked') if event.bookings.count >= event.number_of_spaces
end
end
For the counts of booking table, you should have a booking_count field in events table. Use the counter cache for this. For more details check http://guides.rubyonrails.org/association_basics.html. This is very helpful when records are large.
Your migration for adding column should be similar as below:
def change
add_column :events, :bookings_count, :integer, default: 0
Event.reset_column_information
Event.all.each do |e|
Event.update_counters e.id, :bookings_count => e.bookings.length
end
end
When running my tests in RSpec, I get these errors:
Failures:
1) User micropost associations should have the right micropost in the right order
←[31mFailure/Error:←[0m ←[31m#user.microposts.should == [newer_micropost, older_micropost]←[0m
←[31mActiveRecord::StatementInvalid:←[0m
←[31mSQLite3::SQLException: no such column: micropost.created_at: SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = 1 ORD
ER BY micropost.created_at DESC←[0m
←[36m # C:in `load_target'←[0m
←[36m # ./spec/models/user_spec.rb:153:in `block (3 levels) in <top (required)>'←[0m
2) User micropost associations should destroy associated microposts
←[31mFailure/Error:←[0m ←[31mmicroposts = #user.microposts.dup←[0m
←[31mActiveRecord::StatementInvalid:←[0m
←[31mSQLite3::SQLException: no such column: micropost.created_at: SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = 1 ORD
ER BY micropost.created_at DESC←[0m
←[36m # C:in `load_target'←[0m
←[36m # ./spec/models/user_spec.rb:157:in `block (3 levels) in <top (required)>'←[0m
Finished in 5.18 seconds
←[31m97 examples, 2 failures←[0m
user_spec.rb:
require 'spec_helper'
describe User do
before do
#user = User.new(name: "John Smith", email: "john#example.com",
password: "password", password_confirmation: "password")
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(:remember_token) }
it { should respond_to(:admin) }
it { should respond_to(:authenticate) }
it { should respond_to(:microposts) }
it { should be_valid }
it { should_not be_admin }
describe "micropost associations" do
before { #user.save }
let!(:older_micropost) do
FactoryGirl.create(:micropost, user: #user, created_at: 1.day.ago)
end
let!(:newer_micropost) do
FactoryGirl.create(:micropost, user: #user, created_at: 1.hour.ago)
end
it "should have the right micropost in the right order" do
# user.micropost returns an array
#user.microposts.should == [newer_micropost, older_micropost]
end
it "should destroy associated microposts" do
microposts = #user.microposts.dup
#user.destroy
microposts.should_not be_empty
microposts.each do |micropost|
Micropost.find_by_id(micropost.id).should be_nil
end
end
end
end
schema.rb (shortened):
ActiveRecord::Schema.define(:version => 20131002154740) do
create_table "microposts", :force => true do |t|
t.string "content"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "microposts", ["user_id", "created_at"], :name => "index_microposts_on_user_id_and_created_at"
create_table "users", :force => true do |t|
.
.
.
.
end
end
Micropost model:
class Micropost < ActiveRecord::Base
attr_accessible :content
belongs_to :user
validates :user_id, presence: true
# Ensures the microposts are in descending (DESC) order
# from newest to oldest, (SQL syntax).
default_scope order: 'micropost.created_at DESC'
end
I have run bundle exec rake db:migrate along with bundle exec rake db:test:prepare, I have also reset the database and tried it again but this didn't work.
Specifically the error reads: SQLite3::SQLException: no such column: micropost.created_at: SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = 1 ORD
ER BY micropost.created_at DESC
Well, the SQL problem is that the table name on your sort column is singular rather than plural.
i.e. "ORDER BY micropost.created_at" should read "ORDER BY microposts.created_at".
If you also post your Micropost and User model source code, I might be able to tell if this is caused by a bug in your model code or a bug in ActiveRecord.
Which version of Rails are you using?