Schema for Online Store? (ActiveRecord, React) - ruby

Right now, I am trying to create a short simple online store using ActiveRecord and React (not using Rails at the moment). My set up is this: a user clicks on the item which adds it to the cart. When the user checks out, the user then provides the basic information: name, phone number, credit card.
I have three tables with a many-to-many relationship, cart being the joint table. My set up look like this:
Carts table:
create_table "carts", force: :cascade do |t|
t.integer "quantity"
t.float "total"
t.integer "item_id"
t.integer "order_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["order_id"], name: "index_carts_on_order_id"
t.index ["item_id"], name: "index_carts_on_item_id"
end
Orders table:
create_table "orders", force: :cascade do |t|
t.string "name"
t.integer "phone"
t.integer "credit_card"
t.datetime "purchased_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
Items
create_table "items", force: :cascade do |t|
t.string "item"
t.float "price"
t.integer "quantity"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
I'm not quite sure if the backend that needs another column at cart and order table that'll connect the two, or just the front end.
My thought process is that, for a particular order I would pass the information from its parent component from the last page where the form submit is. If the information from that page matches the values in the database, then I would retrieve the id from the orders table. However, to distinguish a particular cart id to update the order id is where I'm stuck.
Thanks for the help.

Related

Ancestry gem gives error "The scope body needs to be callable." in rails 4?

models/message.rb
class Message < ActiveRecord::Base
has_ancestry
end
schema.rb
create_table "messages", force: :cascade do |t|
t.text "content"
t.integer "parent_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "ancestry"
end
after adding has_ancestry in model it gives error Argument Error.
"The scope body needs to be callable."
Please help me
Thanks

ActiveRecord::StatementInvalid at /category/5

I am a new developer working on a Sinatra/Ruby/ActiveRecord app. I have established a 1:many (postgres) relationship between Category and Recipe. When I try to list the recipes in a category I get the error:
ActiveRecord::StatementInvalid at /category/5
PG::UndefinedColumn: ERROR: column recipes.category_id does not exist LINE 1: SELECT 1 AS one FROM "recipes" WHERE "recipes"."category_id... ^ : SELECT 1 AS one FROM "recipes" WHERE "recipes"."category_id" = $1 LIMIT 1
file: postgresql_adapter.rb location: prepare line: 637
app.rb
get('/category/:id') do
#category = Category.find(params.fetch('id'))
#recipes = #category.recipes
erb(:category)
end
category.erb
<% if #recipes.any?() %>
<% #recipes.each() do |recipe| %>
<ul>
<li><a href='/recipe/<%=recipe.id%>'> <%=recipe.recipe_name%></a></li>
</ul>
<%end%>
<%else %>
<p>You have no recipes!</p>
<%end%>
schema
ActiveRecord::Schema.define(version: 20150930234556) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "categories", force: :cascade do |t|
t.string "cat_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "images", force: :cascade do |t|
t.string "image_name"
t.string "url"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "alt"
t.integer "width"
t.integer "height"
t.integer "recipe_id"
end
create_table "ingredients", force: :cascade do |t|
t.string "ingredient_name"
t.integer "recipe_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "instructions", force: :cascade do |t|
t.string "instruction_name"
t.integer "recipe_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "recipes", force: :cascade do |t|
t.string "recipe_name"
t.string "source"
t.string "servings"
t.string "comment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "cat_id"
end
end
I have searched my project folders and cannot find category_id. Don't know why it's looking for that, my field names are category.id and recipe.cat_id.
This:
#recipes = #category.recipes
suggests that you have
has_many :recipes
in your Category model. That has_many will be looking for a category_id column in your recipes table (i.e. a category_id attribute in your Recipe model). But you don't have a recipes.category_id column, you have a recipes.cat_id column:
create_table "recipes", force: :cascade do |t|
#...
t.integer "cat_id"
end
I'd recommend renaming the recipes.cat_id column to recipes.category_id to match the conventions that Rails has a very strong preference for. If you can't rename the column then add a :foreign_key option to that has_many to tell Category how to resolve the relationship:
has_many :recipes, :foreign_key => :cat_id

Add column to schema before created_at column

I'm trying to add a column to my table.
Here is my migration file:
class AddEmail < ActiveRecord::Migration
def change
add_column :apps, :email, :string, after: :website
end
end
However, when I run it, the newly created email column goes all the way to the last column after updated_at:
ActiveRecord::Schema.define(version: 20141217210326) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "apps", force: true do |t|
t.string "name"
t.string "iTunes"
t.string "website"
t.datetime "created_at"
t.datetime "updated_at"
t.string "email"
end
end
What I want is for the new email column to go in between the website and created_at column. How do I do that?
Postgres doesn't support the ordering of columns in tables. If you don't have any code in production, just alter the original migration that creates the apps table.

SQLite3::SQLException: duplicate column name: User_id: ALTER TABLE "comments" ADD "User_id" integer/

I ran the command
rails g migration AddUser_idToComments User_id:string
and then I figured out that User_id should be an integer and so I ran
rails g migration AddUser_idToComments User_id:integer --force thinking that it would overwrite the initial command.
But now, I'm getting this error:
```
louismorin$ rake db:migrate
== 20140910155248 AddIndexToComments: migrating ===============================
-- add_column(:comments, :Index, :string)
-> 0.0069s
== 20140910155248 AddIndexToComments: migrated (0.0070s) ======================
== 20140910181022 AddUserIdToComments: migrating ==============================
-- add_column(:comments, :User_id, :integer)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: duplicate column name: User_id: ALTER TABLE "comments" ADD "User_id" integer/Users/louismorin/code/CP299/db/migrate/20140910181022_add_user_id_to_comments.rb:3:in change'
ActiveRecord::StatementInvalid: SQLite3::SQLException: duplicate column name: User_id: ALTER TABLE "comments" ADD "User_id" integer
/Users/louismorin/code/CP299/db/migrate/20140910181022_add_user_id_to_comments.rb:3:inchange'
SQLite3::SQLException: duplicate column name: User_id
/Users/louismorin/code/CP299/db/migrate/20140910181022_add_user_id_to_comments.rb:3:in `change'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
```
Here's my schema.rb file
```
ActiveRecord::Schema.define(version: 20140910155210) do
create_table "comments", force: true do |t|
t.text "body"
t.integer "post_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "User_Id"
end
add_index "comments", ["post_id"], name: "index_comments_on_post_id"
create_table "posts", force: true do |t|
t.string "title"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.integer "topic_id"
end
add_index "posts", ["topic_id"], name: "index_posts_on_topic_id"
add_index "posts", ["user_id"], name: "index_posts_on_user_id"
create_table "topics", force: true do |t|
t.string "name"
t.boolean "public", default: true
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.string "role"
t.string "avatar"
t.string "Image"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
```
Because of the error, your second migration -- changing the column type -- didn't run. If that migration was only intended to change that one column, we could then delete the file it generated and try again.
If you don't yet have any data in that column that you care about, that's pretty easy:
rails g migration ChangeTypeOfUserIdOnComments
This migration name isn't special. Might as well have been DoWhateverIWant
Then, edit the created migration's change method to something like this:
def change
remove_column :comments, :user_id
add_column :comments, :user_id, :integer
add_index :comments, :user_id
end
When you then run your un-run migrations rake db:migrate, it shouldn't trip up on the one which errored (because we deleted it), and then it should run this one, which removes the column and adds it back with the correct type.
If you DO have data you want to save, the procedure is more complicated. Your change method would have to grab the current user_id's for each comment, and then assign them to the new comments when we create the new column. The below should hopefully work:
def change
user_ids = {}
Comment.find_each{ |c| user_ids[c.id] = c.user_id.to_i }
remove_column :comments, :user_id
add_column :comments, :user_id, :integer
add_index :comments, :user_id
Comment.each{ |c| c.update_attribute(:user_id, user_ids[c.id])
end
Also note that the names of the migration in the command are generally all CamelCase or all snake_case. So: AddColumnUserIdToComments or add_column_user_id_to_comments. Naming as you did might cause problems.
** EDIT **
Modify a Column's Type in sqlite3
It appears that SQLite has NO good way to modify/drop a column. I'd suggest either:
Dropping and restarting a SQLITe table
Drop the table, drop the original user_id migration and the line in the new one about removing the old user_id column, and then create a new table with the new migrations. Should work fine if you don't care about your data
Switching to Postgres, which is the database Heroku uses.
It's probably a good idea (because you want your production and local databases to behave identically), but can be bug-prone to switch to.
Look here for guidance -- Change from SQLite to PostgreSQL in a fresh Rails project

Devise login validation failure

I rails3.0.4 and devise installed with following users table
create_table "users", :force => true do |t|
t.string "login"
t.string "email"
t.string "crypted_password", :null => false
t.string "password_salt", :null => false
t.string "persistence_token", :null => false
t.string "single_access_token", :null => false
t.string "perishable_token", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.string "database_authenticatable", :null => false
t.string "recoverable"
t.string "rememberable"
t.string "trackable"
t.string "reset_password_token"
end
The users table was not created by devise but I added the necessary
columns in migration.
And following settings in config/initializers/devise.rb
config.authentication_keys = [ :email]
But every time I try to sign up as a new user it throws:
2 errors prohibited this user from being saved:
Login is too short (minimum is 3 characters)
Login should use only letters, numbers, spaces, and .-_# please.
Any ideas why it could happen?
Yes, the login is too short and/or contains the wrong characters :)
You enabled the devise built-in validations, and that's what they validate. To use your own validations remove :validatable from your devise inclusion in app/models/user.rb
If you're interested, the validation used by devise is defined in lib/devise/models/validatable.rb in the devise gem.
Should the validation not be the problem you'll have to show the log of a user creation request, so that we can see what parameters are submitted.
EDIT: Oh I see, I misread - it's about "login". Well, see comments below.

Resources