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
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.
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!
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
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.
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.