RecordNotFound error in rails ecommerce app - ruby-on-rails

i am building an eCommerce app in rails which has two products Chairs and Bookcabinets, i have created two different controllers and models for chairs and bookcabinets, it all worked now i wanted the user to be able to add these products to a cart so i created a ordering system from scratch by watching a tutorial, it worked for chairs but when i add bookcabinets to shopping_cart model it gives me an error: Couldn't find Chair with 'id'=
Server Log
Started POST "/cart/items" for 127.0.0.1 at 2018-09-26 14:16:43 +0530
(0.7ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by OrderItemsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wGAl7gZGXipKt7EzzZT1LuBgn2k8KnlaPagp0cQ3l6pIkr6mx8MdJAuhgkY7EEttrHjTSSpcRjqe0qZ0a2hrAA==", "bookcabinet_id"=>"1", "quantity"=>"40"}
Chair Load (0.8ms) SELECT "chairs".* FROM "chairs" WHERE "chairs"."id" = ? LIMIT ? [["id", nil], ["LIMIT", 1]]
Completed 404 Not Found in 106ms (ActiveRecord: 3.8ms)
ActiveRecord::RecordNotFound (Couldn't find Chair with 'id'=):
app/models/shopping_cart.rb:20:in `add_item'
app/controllers/order_items_controller.rb:8:in `create'
My Order_items_controller
class OrderItemsController < ApplicationController
def index
#items = current_cart.order.items
end
def create
current_cart.add_item(
chair_id: params[:chair_id],
bookcabinet_id: params[:bookcabinet_id],
quantity: params[:quantity]
)
redirect_to cart_path
end
def destroy
current_cart.remove_item(id: params[:id])
redirect_to cart_path
end
end
My Order_controller
class OrdersController < ApplicationController
def new
#order = current_cart.order
end
end
** My Order model**
class Order < ApplicationRecord
has_many :items, class_name: 'OrderItem'
end
My Order_item Model
class OrderItem < ApplicationRecord
belongs_to :order
belongs_to :chair
belongs_to :bookcabinet
end
My Shopping_Cart Model
class ShoppingCart
delegate :sub_total, to: :order
def initialize(token:)
#token = token
end
def order
#order ||= Order.find_or_create_by(token: #token) do |order|
order.sub_total = 0
end
end
def items_count
order.items.sum(:quantity)
end
def add_item(chair_id:, bookcabinet_id:, quantity: 1)
chair = Chair.find(chair_id),
bookcabinet = Bookcabinet.find(bookcabinet_id)
order_item = order.items.find_or_initialize_by(
chair_id: chair_id,
bookcabinet_id: bookcabinet_id
)
order_item.price = chair.price
order_item.price = bookcabinet.price
order_item.quantity = quantity
ActiveRecord::Base.transaction do
order_item.save
update_sub_total!
end
end
def remove_item(id:)
ActiveRecord::Base.transaction do
order.items.destroy(id)
update_sub_total!
end
end
private
def update_sub_total!
order.sub_total = order.items.sum('quantity*price')
order.save
end
end
My Create_order migration
class CreateOrders < ActiveRecord::Migration[5.1]
def change
create_table :orders do |t|
t.string :first_name
t.string :last_name, null: false
t.decimal :sub_total, precision: 15, scale: 2, null: false
t.timestamps
end
end
end
my CreateOrderItems migration
class CreateOrderItems < ActiveRecord::Migration[5.1]
def change
create_table :order_items do |t|
t.belongs_to :order, null: false
t.belongs_to :chair, null: false
t.belongs_to :bookcabinet
t.integer :quantity, null: false
t.decimal :price, precision: 15, scale: 2, null: false
t.timestamps
end
end
end
Routes
get '/cart', to: 'order_items#index'
resources :order_items, path: '/cart/items'
get '/cart/checkout', to: 'orders#new', as: :checkout
patch '/cart/checkout', to: 'orders#create'
Add To Cart Form
<div class="button my-2">
<%= form_tag order_items_path do %>
<%= hidden_field_tag :bookcabinet_id, #bookcabinet.id %>
<%= number_field_tag :quantity, 1 %>
<button type="submit" class="btn cart"><i class="d-inline fa fa-cart-arrow-down" aria-hidden="true"></i><p class="d-inline">Add To Cart</p></button>
<% end %>
Updated Server Log
Started POST "/cart/items" for 127.0.0.1 at 2018-09-27 00:24:13 +0530
(0.6ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by OrderItemsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"gqwsV8Z/0p74Y8WPLMmfk9vmoSPCFpP+lAtVxxH3KSvWUzYYIFtbQRkAzM5yh5HS/wAzelr90LJW64joFUpGwg==", "bookcabinet_id"=>"1", "quantity"=>"40"}
Bookcabinet Load (0.7ms) SELECT "bookcabinets".* FROM "bookcabinets" WHERE "bookcabinets"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Order Load (0.9ms) SELECT "orders".* FROM "orders" WHERE "orders"."token" = ? LIMIT ? [["token", "20897ec5db2636f5"], ["LIMIT", 1]]
OrderItem Load (0.5ms) SELECT "order_items".* FROM "order_items" WHERE "order_items"."order_id" = ? AND "order_items"."chair_id" IS NULL AND "order_items"."bookcabinet_id" = ? LIMIT ? [["order_id", 4], ["bookcabinet_id", 1], ["LIMIT", 1]]
(0.2ms) begin transaction
Bookcabinet Load (0.3ms) SELECT "bookcabinets".* FROM "bookcabinets" WHERE "bookcabinets"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.4ms) SELECT SUM(quantity*price) FROM "order_items" WHERE "order_items"."order_id" = ? [["order_id", 4]]
(0.2ms) commit transaction
Redirected to http://localhost:3000/cart
Completed 302 Found in 557ms (ActiveRecord: 10.4ms)
Started GET "/cart" for 127.0.0.1 at 2018-09-27 00:24:14 +0530
Processing by OrderItemsController#index as HTML
Order Load (0.5ms) SELECT "orders".* FROM "orders" WHERE "orders"."token" = ? LIMIT ? [["token", "20897ec5db2636f5"], ["LIMIT", 1]]
Rendering order_items/index.html.erb within layouts/application
(0.4ms) SELECT SUM("order_items"."quantity") FROM "order_items" WHERE "order_items"."order_id" = ? [["order_id", 4]]
OrderItem Load (1.1ms) SELECT "order_items".* FROM "order_items" WHERE "order_items"."order_id" = ? [["order_id", 4]]
Rendered order_items/index.html.erb within layouts/application (15.0ms)
CACHE (0.1ms) SELECT SUM("order_items"."quantity") FROM "order_items" WHERE "order_items"."order_id" = ? [["order_id", 4]]
Rendered layouts/_header.html.erb (22.0ms)
Rendered layouts/_footer.html.erb (1.9ms)
Completed 200 OK in 1313ms (Views: 1304.9ms | ActiveRecord: 2.1ms)

You are searching for chair item every time you call add_item method so its throwing an error as you are not passing chair id so you need to modify the method as below
def add_item(chair_id:, bookcabinet_id:, quantity: 1)
chair = Chair.find(chair_id) if chair_id
bookcabinet = Bookcabinet.find(bookcabinet_id) if bookcabinet_id
order_item = order.items.find_or_initialize_by(
chair_id: chair_id,
bookcabinet_id: bookcabinet_id
)
order_item.price = chair.price if chair
order_item.price = bookcabinet.price
order_item.quantity = quantity
ActiveRecord::Base.transaction do
order_item.save
update_sub_total!
end
end
Please feel free to ask if there are any questions regarding the same

Related

Preventing N+1 in Rails query with associated model

I have these models:
class KlassOccurrence < ApplicationRecord
belongs_to :klass
end
class Klass < ApplicationRecord
has_many :klass_occurrences
belongs_to :user
def next_occurrence_date
self.klass_occurrences.order(scheduled_at: :desc).first
end
end
And I have this in a controller:
#klasses = Klass.includes(:klass_occurrences).where(user_id: current_user.id)
And in a view I have this:
<% #klasses.each do |klass| %>
<tr>
<td><%= klass.next_occurrence_date %></td>
</tr>
<% end %>
I would expect that because of the includes(:klass_occurrences) I wouldn't be seeing an N+1, but this is what I see in the logs:
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/controllers/klasses_controller.rb:4:in `index'
Rendering klasses/index.html.erb within layouts/dashboard_layout
Klass Load (0.2ms) SELECT "klasses".* FROM "klasses" WHERE "klasses"."user_id" = $1 [["user_id", 3]]
↳ app/views/klasses/index.html.erb:13
KlassOccurrence Load (4.3ms) SELECT "klass_occurrences".* FROM "klass_occurrences" WHERE "klass_occurrences"."klass_id" IN ($1, $2) [["klass_id", 1], ["klass_id", 5]]
↳ app/views/klasses/index.html.erb:13
KlassOccurrence Load (1.8ms) SELECT "klass_occurrences".* FROM "klass_occurrences" WHERE "klass_occurrences"."klass_id" = $1 ORDER BY "klass_occurrences"."scheduled_at" DESC LIMIT $2 [["klass_id", 1], ["LIMIT", 1]]
↳ app/models/klass.rb:6:in `next_occurrence_date'
KlassOccurrence Load (0.3ms) SELECT "klass_occurrences".* FROM "klass_occurrences" WHERE "klass_occurrences"."klass_id" = $1 ORDER BY "klass_occurrences"."scheduled_at" DESC LIMIT $2 [["klass_id", 5], ["LIMIT", 1]]
↳ app/models/klass.rb:6:in `next_occurrence_date'
Why is it doing three queries for klass occurrences? I would expect just one query to load all the occurrences for all the klasses, but then I see two extra queries.
If you just need the highest value of that column you can also just select an aggregate off the join table:
class Klass < ApplicationRecord
has_many :klass_occurrences
belongs_to :user
def self.with_next_occurrence_date
self.select(
'klass.*',
'MAX(klass_occurrences.scheduled_at) AS next_occurrence_date'
)
.left_joins(:klass_occurrences)
.group(:id)
end
end
#klasses = Klass.with_next_occurrence_date.where(user_id: current_user.id)
<% #klasses.each do |klass| %>
<tr>
<td><%= klass.next_occurrence_date %></td>
</tr>
<% end %>
If you really need a model object you can do it by sorting the records in Ruby:
class Klass < ApplicationRecord
has_many :klass_occurrences
belongs_to :user
def next_occurrence_date
self.klass_occurrences.sort(&:scheduled_at).last
end
end
And there are also a bunch of novel tricks to get ActiveRecord to load just one record off the association that are somewhat out of scope for this question.

How to find a object and insert it in a database

I’m trying to pick up the shop_id and subscription_id from a cart and insert/save them into the purchase database.
I have a cart, line_items and subscriptions.
And this is how I’m trying to do this:
#purchase = #cart.line_items.build
#purchase = current_shop.purchases.build(purchase_params)
#purchase.save!
I got the shop_id, but the subscription_id for some reason is nil.
Any ideas what maybe wrong?
Update 1
def purchase_params
params.permit(:subscription_id, :shop_id, :created_at, :updated_at, :id, :cart_id)
end
Started POST "/line_items?subscription_id=1" for ::1 at 2017-06-18 16:45:12 +0300
Processing by LineItemsController#create as HTML
Parameters: {"authenticity_token"=>"dUonc4AnCvFTuK1b+TAKho/kmpvl7XaOM7SGcNalzdQV1+CqhY4 p7znDiL/TV12pVKeDTqlR7j5NL65X1S/75A==", "subscription_id"=>"1"}
Cart Load (0.1ms) SELECT "carts".* FROM "carts" WHERE "carts"."id" = ? LIMIT ? [["id", 14], ["LIMIT", 1]]
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "carts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", 2017-06-18 13:45:12 UTC], ["updated_at", 2017-06-18 13:45:12 UTC]]
(0.7ms) commit transaction
Subscription Load (0.2ms) SELECT "subscriptions".* FROM "subscriptions" WHERE "subscriptions"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.1ms) begin transaction
SQL (0.6ms) INSERT INTO "line_items" ("subscription_id", "cart_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["subscription_id", 1], ["cart_id", 18], ["created_at", 2017-06-18 13:45:12 UTC], ["updated_at", 2017-06-18 13:45:12 UTC]]
(0.9ms) commit transaction
Redirected to http://localhost:3000/carts/18
Completed 302 Found in 21ms (ActiveRecord: 3.2ms)
I'm implementing braintree payments via the following create method and this is where I have the small peace of code:
def create
current_shop.has_payment_info?
#result = Braintree::Transaction.sale(
amount: #cart.total_price,
payment_method_nonce: params[:payment_method_nonce],
customer: {
first_name: current_shop.first_name,
last_name: current_shop.last_name,
company: current_shop.shop_name,
email: current_shop.email,
phone: current_shop.phone_number,
website: current_shop.web_page
},
options: { store_in_vault: true })
if #result.success?
current_shop.update(braintree_customer_id: #result.transaction.customer_details.id) unless current_shop.has_payment_info?
#purchase = #cart.line_items.build
#purchase.save!
#purchase = current_shop.purchases.build(purchase_params)
#purchase.save!
#cart.destroy
redirect_to front_index_path, notice: 'Your transaction was succesfully processed'
else
gon.client_token = generate_client_token
redirect_to :back, :notice => 'Something went wrong while processing your transaction. Please try again!'
end
end
Update 2
class Purchase < ApplicationRecord
belongs_to :shop
belongs_to :cart
end
class Shop < ApplicationRecord
has_many :items
has_many :purchases
has_many :subscriptions
end
class Subscription < ApplicationRecord
has_many :line_items
belongs_to :shop
end
class Cart < ApplicationRecord
has_many :line_items, dependent: :destroy
has_many :purchases
end
class LineItem < ApplicationRecord
belongs_to :subscription
belongs_to :cart
end
Build here only links up a new line_item with #cart, like this, LineItem.new(cart_id: #cart.id). subscription_id is not linked here as #cart doesn't have a relationship with subscriptions.
#cart.line_items.build
line_item = #cart.line_items.build
fetch the desired subscription_id and assign it to 'line_item.subscription_id '
line_item.subscription_id = fetch_the_subscription_id
line_item.save!

Updating belongs_to model via accepts_nested_attributes

Unable to update state attribute of the Product model using accepts_nested_attributes. This is what JSON I post looks like:
{"auth_token"=>"x", "product"=>{"caption"=>"x","state_attributes"=>{"id"=>"1"}}, "id"=>"x"}
All I need to do is to change referenced state. Thoughts?
State Model
class State < ActiveRecord::Base
has_many :products
end
Product Model
class Product < ActiveRecord::Base
attr_accessible :state, :state_attributes
belongs_to :state
accepts_nested_attributes_for :state, :allow_destroy => false
end
Products Controller Update Action
def update
product = Product.find_by_id( params[:id])
if product && product.update_attributes(params[:product])
respond_with(product, status: :updated, location: product)
else
respond_with(product.errors, status: :unprocessable_entity)
end
end
Transaction Log
Started PUT "/products/1170.json" for 127.0.0.1 at 2014-01-13 16:21:52 -0700
Processing by ProductsController#update as JSON
Parameters: {"auth_token"=>"x", "product"=>{"caption"=>"x", "state_attributes"=>{"id"=>"3"}}}, "id"=>"1170"}
WARNING: Can't verify CSRF token authenticity
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."authentication_token" = 'x' LIMIT 1
(0.1ms) BEGIN
(0.3ms) UPDATE "users" SET "last_sign_in_at" = '2014-01-13 23:20:46.614453', "current_sign_in_at" = '2014-01-13 23:21:52.251028', "sign_in_count" = 954, "updated_at" = '2014-01-13 23:21:52.251753' WHERE "users"."id" = 536
(6.5ms) COMMIT
Product Load (0.5ms) SELECT "products".* FROM "products" WHERE "products"."user_id" = 536 AND "products"."id" = 1170 LIMIT 1
(0.1ms) BEGIN
State Load (0.2ms) SELECT "states".* FROM "states" WHERE "states"."id" = 2 LIMIT 1
(0.5ms) ROLLBACK
Completed 404 Not Found in 15ms
ActiveRecord::RecordNotFound (Couldn't find State with ID=3 for Product with ID=1170):
app/controllers/products_controller.rb:81:in `update'
Rendered /Users/me/.rvm/gems/ruby-2.0.0-p353/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.0ms)
Rendered /Users/me/.rvm/gems/ruby-2.0.0-p353/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.8ms)
Rendered /Users/me/.rvm/gems/ruby-2.0.0-p353/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (5.8ms)
As #Sergio Aristizábal pointed out, I was trying to reset associated state instead of simply updating the id
You are trying to reset the id of the associated State. I guess you just want to associate a state to product, so you should just set the state_id attribute.
With that, I updated Product model
class Product < ActiveRecord::Base
attr_accessible :state_id, :state_attributes
belongs_to :state
end
Passed state id in the json
{"auth_token"=>"x", "product"=>{"caption"=>"x","state_id"=>"1"}, "id"=>"x"}
and everything worked like a charm. Thanks #Sergio

Improving Query/View Load-Time [Ruby on Rails]

I'm experiencing some pretty slow load times with one of the pages of my Rails app. I have made some headway in my attempts to improve performance, but not as much as I had hoped. I'm wondering if I'm doing something silly to cause myself this grief or if anyone could offer me advice to better optimize my models/migrations/queries/views. I'm running Rails 3.1 and using PostgreSQL. This is what I've tried so far:
added includes(:items => :category) to the controller's query, as an attempt to fetch all the ItemCategories in advance, rather than running additional queries when outfits_helper requires them.
rendering partials as collections, rather than iterating through arrays/relations manually
added indexes to tables that are being accessed by the problematic controller action / view
outfits table: indexes for user_id and category_id
items table: indexes for user_id and category_id
outfit_items table: indexes for item_id, outfit_id, and [outfit_id, item_id]
Below are the relevant parts of my code:
Controller
# outfits_controller.rb
NUM_OUTFITS_PER_PAGE = 8
def other_users_outfits
# using Kaminari for pagination
#outfits = Outfit.does_not_belong_to_user(current_user).in_category_with_id(category_id).includes(:items => :category).page(params[:page]).per(NUM_OUTFITS_PER_PAGE)
end
Models
# outfit.rb
has_many :items, :through => :outfit_items
belongs_to :category, :class_name => 'OutfitCategory'
scope :does_not_belong_to_user, proc {|user| where('user_id != ?', user.id) }
scope :in_category_with_id, proc {|cat_id|
if cat_id.blank?
scoped
else
where(:category_id => cat_id)
end
}
.
# outfit_item.rb
belongs_to :item
belongs_to :outfit
.
# item.rb
has_many :outfit_items
has_many :outfits, :through => :outfit_items
belongs_to :category, :class_name => 'ItemCategory'
.
# item_category.rb
has_many :items, :foreign_key => 'category_id'
.
outfit_category.rb
has_many :outfits, :foreign_key => 'outfit_id'
Migrations
# create_outfits.rb
def self.up
create_table :outfits do |t|
t.column :category_id, :integer
t.column :user_id, :integer
t.timestamps
end
add_index :outfits, :category_id
add_index :outfits, :user_id
end
.
# create_outfit_items.rb
def self.up
create_table :outfit_items, :id => false do |t|
t.column :item_id, :integer
t.column :outfit_id, :integer
t.timestamps
end
add_index :outfit_items, :item_id
add_index :outfit_items, :outfit_id
add_index :outfit_items, [:outfit_id, :item_id]
end
.
# create_items.rb
def self.up
create_table :items do |t|
t.column :category_id, :integer
t.column :user_id, :integer
t.timestamps
end
add_index :items, :category_id
add_index :items, :user_id
end
.
# create_item_categories.rb
def self.up
create_table :item_categories do |t|
t.column :name, :string
t.column :category_type, :string
t.timestamps
end
end
.
# create_outfit_categories.rb
def self.up
create_table :outfit_categories do |t|
t.column :name, :string, :limit => 100, :null => false
t.timestamps
end
end
Views
# other_users_outfits.html.haml
= render :partial => 'other_users_outfit', :collection => outfits, :as => :outfit
.
# _other_users_outfit.html.haml
.outfit
.primary-items
= render :partial => 'other_users_outfit_primary_item', :collection => primary_outfit_items_top_to_bottom(outfit), :as => :item
.secondary-items
= render :partial => 'other_users_outfit_secondary_item', :collection => secondary_outfit_items(outfit), :as => :item
.
# _other_users_outfit_primary_item.html.haml
= image_tag item.image_url(:outfit_item), :class => 'primary-outfit-item'
.
# _other_users_outfit_secondary_item.html.haml
= image_tag item.image_url(:baby_thumb), :class => 'secondary-outfit-item'
Helper
# outfits_helper.rb
def primary_outfit_items_top_to_bottom(outfit)
primary_items = []
primary_items.push(outfit_item_in_category(outfit, 'Tops'))
primary_items.push(outfit_item_in_category(outfit, 'Full-lengths'))
primary_items.push(outfit_item_in_category(outfit, 'Bottoms'))
primary_items.push(outfit_item_in_category(outfit, 'Footwear'))
primary_items.compact
end
def secondary_outfit_items(outfit)
outfit.items.select{|item| item.category.category_type == 'secondary' }
end
def outfit_item_in_category(outfit, cat_name)
outfit.items.select{|item| item.category.name == cat_name }.first
end
Console Output
User Load (1.0ms) SELECT DISTINCT users.id, users.* FROM "users" WHERE "users"."id" = 3 LIMIT 1
(0.5ms) SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "outfits" WHERE (user_id != 3) LIMIT 8 OFFSET 0) subquery_for_count
Outfit Load (0.7ms) SELECT DISTINCT outfits.id, outfits.* FROM "outfits" WHERE (user_id != 3) ORDER BY outfits.created_at DESC LIMIT 8 OFFSET 0
OutfitItem Load (0.6ms) SELECT "outfit_items".* FROM "outfit_items" WHERE "outfit_items"."outfit_id" IN (28, 27, 26, 25, 24, 23, 22, 21)
Item Load (2.2ms) SELECT DISTINCT items.id, items.*, "items".* FROM "items" WHERE "items"."id" IN (18, 20, 23, 7, 6, 30, 4, 1, 17, 5, 15, 12, 9, 29, 10, 19, 3, 8, 13) ORDER BY items.created_at DESC
ItemCategory Load (0.5ms) SELECT "item_categories".* FROM "item_categories" WHERE "item_categories"."id" IN (4, 6, 2, 1, 3, 7)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (1.2ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.1ms)
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.8ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (1.4ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.9ms)
Rendered outfits/_other_users_outfit_primary_item.html.haml (1.2ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.9ms)
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.7ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.8ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.7ms)
Rendered outfits/_other_users_outfit_primary_item.html.haml (1.2ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (1.1ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms)
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.2ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.8ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms)
Rendered outfits/_other_users_outfit_primary_item.html.haml (3.4ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.0ms)
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.6ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms)
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms)
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.1ms)
Rendered outfits/_other_users_outfit.html.haml (56.3ms)
(0.5ms) SELECT COUNT(*) FROM "outfits" WHERE (user_id != 3)
Rendered outfits/other_users.html.haml within layouts/application (2073.5ms)
Role Load (0.4ms) SELECT "roles".* FROM "roles" WHERE "roles"."name" = 'admin' LIMIT 1
(0.4ms) SELECT 1 FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles_users"."user_id" = 3 AND "roles"."id" = 1 LIMIT 1
Rendered layouts/_top_nav.html.haml (1.0ms)
(0.6ms) SELECT COUNT(*) FROM "items" WHERE "items"."user_id" = 3
Rendered layouts/_points_display.html.haml (5.7ms)
Outfit Load (0.6ms) SELECT DISTINCT outfits.id, outfits.* FROM "outfits" WHERE "outfits"."user_id" = 3 ORDER BY outfits.created_at DESC
OutfitCategory Load (0.3ms) SELECT "outfit_categories".* FROM "outfit_categories"
.
Any help would be much appreciated!
The only thing I see that could stand improvement is the code in the helper. Is there a reason why you're doing this:
def outfit_item_in_category(outfit, cat_name)
outfit.items.select{|item| item.category.name == cat_name }.first
end
instead of pushing this code to a scope in the Item model? If you have a lot of items, you're basically doing a SELECT * on them and then filtering in Ruby.

Unable to implement has_one relationship

I am trying to create an account management system that allows an account to have one billing address. I want the account and address to have their own controller and model. An admin user would create a new account then be redirected to create a new billing address for this account. The first part works, I am able to create the account, but the second only saves the account_id attribute to the addresses table. Below is my code:
accounts_controller
class AccountsController < ApplicationController
def new
#account = Account.new
end
def create
#account = Account.new(params[:account])
#account.build_address
if #account.save
flash[:success] = "Customer Account has been successfully created!"
redirect_to '/newaddress'
else
render 'new'
end
end
end
addresses_controller
class AddressesController < ApplicationController
def new
#address = Address.new
end
def create
#account = Account.find(params[:account])
#address = #account.create_address(params[:address])
redirect_to root_path
end
end
account_model
class Account < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
attr_accessible :contactFirstName, :contactLastName, :contactEmail, :contactPhone, :business_name
end
address_model
class Address < ActiveRecord::Base
attr_accessible :city, :state, :street, :zipCode
belongs_to :account
end
I also added the following to my routes.rb file
resources :accounts do
resources :addresses
end
Last, below is the schema for the relavant tables
create_table "accounts", :force => true do |t|
t.string "contactEmail"
t.string "contactFirstName"
t.string "contactLastName"
t.string "contactPhone"
t.datetime "joinDate"
t.string "business_name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "addresses", :force => true do |t|
t.string "city"
t.string "state"
t.string "street"
t.string "zipCode"
t.integer "account_id"
t.datetime "created_at"
t.datetime "updated_at"
end
(I am still new to programming and rails so I posted as much as I thought would be relevant.)
Added Log from when I open the new account page and then proceed to the new address page.
Started GET "/newaccount" for 127.0.0.1 at Tue Sep 20 17:21:56 -0500 2011
Processing by AccountsController#new as HTML
Rendered shared/_error_messages.html.erb (0.6ms)
Rendered accounts/_account_fields.html.erb (13.0ms)
Rendered layouts/_stylesheets.html.erb (1.2ms)
User Load (2.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
CACHE (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
Rendered layouts/_header.html.erb (19.4ms)
Rendered layouts/_footer.html.erb (1.0ms)
Rendered accounts/new.html.erb within layouts/application (50.3ms)
Completed 200 OK in 168ms (Views: 64.6ms | ActiveRecord: 2.5ms)
Started POST "/accounts" for 127.0.0.1 at Tue Sep 20 17:22:11 -0500 2011
Processing by AccountsController#create as HTML
Parameters: {"commit"=>"Next", "account"=>{"business_name"=>"FooBar", "contactLastName"=>"Bar", "contactPhone"=>"1231231234", "contactEmail"=>"foo#bar.com", "contactFirstName"=>"Foo"}, "authenticity_token"=>"lJG89TIjcJighmFUWLg1uR9sJq0CHLvceeLH9QNocGY=", "utf8"=>"✓"}
SQL (0.1ms) BEGIN
SQL (0.3ms) SELECT 1 FROM `accounts` WHERE (LOWER(`accounts`.`contactEmail`) = LOWER('foo#bar.com')) LIMIT 1
SQL (1.2ms) describe `accounts`
AREL (0.4ms) INSERT INTO `accounts` (`created_at`, `contactFirstName`, `business_name`, `contactPhone`, `updated_at`, `contactEmail`, `contactLastName`, `joinDate`) VALUES ('2011-09-20 22:22:11', 'Foo', 'FooBar', '1231231234', '2011-09-20 22:22:11', 'foo#bar.com', 'Bar', NULL)
SQL (1.5ms) describe `addresses`
AREL (0.2ms) INSERT INTO `addresses` (`zipCode`, `state`, `city`, `updated_at`, `account_id`, `street`, `created_at`) VALUES (NULL, NULL, NULL, '2011-09-20 22:22:11', 31, NULL, '2011-09-20 22:22:11')
SQL (26.3ms) COMMIT
Redirected to http://localhost:3500/newaddress
Completed 302 Found in 85ms
Started GET "/newaddress" for 127.0.0.1 at Tue Sep 20 17:22:11 -0500 2011
Processing by AddressesController#new as HTML
Rendered addresses/_address_fields.html.erb (83.4ms)
Rendered layouts/_stylesheets.html.erb (1.4ms)
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
CACHE (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
Rendered layouts/_header.html.erb (17.1ms)
Rendered layouts/_footer.html.erb (0.9ms)
Rendered addresses/new.html.erb within layouts/application (113.6ms)
Completed 200 OK in 126ms (Views: 119.6ms | ActiveRecord: 30.3ms)
Started POST "/newaddress" for 127.0.0.1 at Tue Sep 20 17:22:29 -0500 2011
Processing by AddressesController#new as HTML
Parameters: {"address"=>{"city"=>"Boston", "street"=>"123 Main St", "zipCode"=>"02222", "state"=>"MA"}, "commit"=>"Create", "authenticity_token"=>"lJG89TIjcJighmFUWLg1uR9sJq0CHLvceeLH9QNocGY=", "utf8"=>"✓"}
Rendered addresses/_address_fields.html.erb (10.3ms)
Rendered layouts/_stylesheets.html.erb (1.2ms)
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
CACHE (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
Rendered layouts/_header.html.erb (17.2ms)
Rendered layouts/_footer.html.erb (0.9ms)
Rendered addresses/new.html.erb within layouts/application (40.1ms)
Completed 200 OK in 54ms (Views: 47.3ms | ActiveRecord: 0.2ms)
The line in in the Address class looks wrong to me (take out the _attributes):
class Address < ActiveRecord::Base
attr_accessible :city, :state, :street, :zipCode
belongs_to :account
end
As quick look, you are passing only params[:account], tail log and see what you need
class AddressesController < ApplicationController
def new
#address = Address.new
end
def create
#account = Account.find(params[:account])
#address = #account.create_address(params[:address])
redirect_to root_path
end
end
Ass you added log, you can see now that when you post newaddress
Parameters: {"address"=>{"city"=>"Boston", "street"=>"123 Main St", "zipCode"=>"02222", "state"=>"MA"}, "commit"=>"Create", "authenticity_token"=>"lJG89TIjcJighmFUWLg1uR9sJq0CHLvceeLH9QNocGY=", "utf8"=>"✓"}
and your controller have
def create
#account = Account.find(params[:account])
#address = #account.create_address(params[:address])
redirect_to root_path
end
As you can see there are no #account = Account.find(params[:account])
So you account is null, you may add hidden field with account_id to form or catch other way depends of of your app.

Resources