Ok so I have a table orders, order_items, and items. Everything works fine except for 1 thing.
class CreateOrders < ActiveRecord::Migration[5.0]
def change
create_table :orders do |t|
t.integer :seller_id
t.integer :customer_id
t.string :shipping_method
t.string :shipping_terms
t.string :payment_method
t.date :delivery_date
t.date :due_date
t.decimal :total_discount, :precision =>8, :scale => 2
t.decimal :subtotal, :precision =>8, :scale => 2
t.decimal :sales_tax, :precision =>8, :scale => 2
t.decimal :total, :precision =>8, :scale => 2
t.timestamps
end
end
end
class CreateOrderItems < ActiveRecord::Migration[5.0]
def change
create_table :order_items do |t|
t.integer :order_id
t.integer :item_id
t.integer :quantity
t.decimal :discount, :precision =>8, :scale => 2
t.decimal :line_total, :precision =>8, :scale => 2
t.boolean :packed
t.string :packed_by
t.string :ffr
t.timestamps
end
end
end
class CreateItems < ActiveRecord::Migration[5.0]
def change
create_table :items do |t|
t.integer :sku
t.string :name
t.decimal :price, :precision =>8, :scale => 2
t.string :description
t.decimal :weight, :precision =>8, :scale => 2
t.timestamps
end
end
end
Basically there needs to be calculations done either as the items are being added to the order or before everything is saved.
On the Orders table the following needs to happen
Calculate : total_discount(dollar amount), sub_total, :sales_tax, :total
On OrderItems table the following needs to happen
Calculate : line_total, discount(dollar amount)
There has to be a sane way to do this but I have yet to figure it out. Either I really do not know what I am looking for or I am googling all the wrong things.
I'm trying to do a DB migration in Rails using PostgreSQL, but the resulting schema doesn't contain any of my table definitions. Is there something wrong with my syntax that I'm not seeing?
Here's an example of one of my migration files and the resulting schema file after I run "rake db:migrate".
Migration file:
class Fields < ActiveRecord::Migration[5.2]
def change
def up
create_table :fields do |t|
t.column :totalsalesprsn, :float, :limit => nil, :null => false
t.column :totaladmkspend, :float, :limit => nil, :null => false
t.column :totalsalescost, :float, :limit => nil, :null => false
t.column :miscsales, :float, :limit => nil, :null => false
t.column :numleads, :float, :limit => nil, :null => false
t.column :costleads, :float, :limit => nil, :null => false
t.column :totalsalescost2, :float, :limit => nil, :null => false
t.column :totalmarketspent, :float, :limit => nil, :null => false
t.column :numsales, :float, :limit => nil, :null => false
t.column :averagecost, :float, :limit => nil, :null => false
t.column :costpersale, :float, :limit => nil, :null => false
t.column :totalspending, :float, :limit => nil, :null => false
t.column :totalsalesdonate, :float, :limit => nil, :null => false
t.column :totalsales, :float, :limit => nil, :null => false
t.column :pototal, :float, :limit => nil, :null => false
t.column :posales, :float, :limit => nil, :null => false
t.column :form_id, :integer
t.column :created_at, :timestamp
end
end
def down
drop_table :fields
end
end
end
Schema file:
ActiveRecord::Schema.define(version: 2018_10_25_161515) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "fields", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "forms", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "tables", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Would it have something to do with my model files? I have no idea why it's doing this, and I can't post more code, because I would have to add more details to this post in order to avoid the warning that my question doesn't have enough details.
It's not creating columns because you are defining up and down inside the change method.
Try this
class Fields < ActiveRecord::Migration[5.2]
def up
create_table :fields do |t|
t.column :totalsalesprsn, :float, :limit => nil, :null => false
t.column :totaladmkspend, :float, :limit => nil, :null => false
t.column :totalsalescost, :float, :limit => nil, :null => false
t.column :miscsales, :float, :limit => nil, :null => false
t.column :numleads, :float, :limit => nil, :null => false
t.column :costleads, :float, :limit => nil, :null => false
t.column :totalsalescost2, :float, :limit => nil, :null => false
t.column :totalmarketspent, :float, :limit => nil, :null => false
t.column :numsales, :float, :limit => nil, :null => false
t.column :averagecost, :float, :limit => nil, :null => false
t.column :costpersale, :float, :limit => nil, :null => false
t.column :totalspending, :float, :limit => nil, :null => false
t.column :totalsalesdonate, :float, :limit => nil, :null => false
t.column :totalsales, :float, :limit => nil, :null => false
t.column :pototal, :float, :limit => nil, :null => false
t.column :posales, :float, :limit => nil, :null => false
t.column :form_id, :integer
t.column :created_at, :timestamp
end
end
def down
drop_table :fields
end
end
Please have a look at the documentation here on how to define migrations.
From the documentation
The change method is the primary way of writing migrations. It works for the majority of cases, where Active Record knows how to reverse the migration automatically.
So, alternatively you can define the migration as well by doing the following
class Fields < ActiveRecord::Migration[5.2]
def change
create_table :fields do |t|
t.column :totalsalesprsn, :float, :limit => nil, :null => false
t.column :totaladmkspend, :float, :limit => nil, :null => false
t.column :totalsalescost, :float, :limit => nil, :null => false
t.column :miscsales, :float, :limit => nil, :null => false
t.column :numleads, :float, :limit => nil, :null => false
t.column :costleads, :float, :limit => nil, :null => false
t.column :totalsalescost2, :float, :limit => nil, :null => false
t.column :totalmarketspent, :float, :limit => nil, :null => false
t.column :numsales, :float, :limit => nil, :null => false
t.column :averagecost, :float, :limit => nil, :null => false
t.column :costpersale, :float, :limit => nil, :null => false
t.column :totalspending, :float, :limit => nil, :null => false
t.column :totalsalesdonate, :float, :limit => nil, :null => false
t.column :totalsales, :float, :limit => nil, :null => false
t.column :pototal, :float, :limit => nil, :null => false
t.column :posales, :float, :limit => nil, :null => false
t.column :form_id, :integer
t.column :created_at, :timestamp
end
end
end
you have your syntax somewhat wrong:
class Fields < ActiveRecord::Migration[5.2]
def change
def up
# your table definition
end
end
def down
# delete your table
end
end
Rails is smart enough to know that the reverse of creating a table is deleting it, so you don't need to specify def down.
You don't seem to show errors on the migration, so before doing the following, run the command rails db:rollback from your console
Then change your migration file to the following and run again rails db:migrate:
class Fields < ActiveRecord::Migration[5.2]
def change
# your table definition
end
end
Other answers here are correct. However if you already ran the migration and got no error, you will likely need to roll it back, but if that fails you will need to manually rollback the migration in the database. Because any migration will increment the schema_migrations with the version number in the migration filename.
So if your migration filename is something like 20181023191125_fields.rb you'll need to do this:
rails dbconsole
#now you should be in a (pg?) console
DELETE from schema_migrations WHERE version = 20181023191125;
\q # to quit postgres
But if this is a new project and you have seeds, it might be easier to just start over with a fresh database after fixing your migration as others have already instructed you.
ONLY DO THIS IF YOU ARE FINE WITH KILLING YOUR DB and STARTING OVER!!
rake db:setup
# or
rails db:setup
See Difference between rake db:migrate db:reset and db:schema:load
class FixedLineItem < AR
belongs_to :fee_table, :class_name => 'FixedFeeTable',
:foreign_key => 'fixed_fee_table_id',
:inverse_of => :line_items,
:counter_cache => :fixed_line_items_count
end
class FixedFeeTable < AR
has_many :line_items, :class_name => 'FixedLineItem',
:inverse_of => :fee_table
end
Given the above, why does #fixed_fee_table.line_items.size still access the db? I can see it performing a COUNT operation in the console.
If i rename the has_many association to has_many :fixed_line_items, it works as expected.
Am i missing an option somewhere? I cant find any mention through googling however.
EDIT
This is on rails 3.2.14
and my schema for the two tables
create_table "fixed_fee_tables", :force => true do |t|
t.string "kind"
t.integer "total_amount_cents"
t.integer "fee_summary_id"
t.string "currency"
t.integer "final_total_amount_cents"
t.integer "fixed_line_items_count", :default => 0, :null => false
end
create_table "fixed_line_items", :force => true do |t|
t.string "description"
t.integer "quantity"
t.integer "price_cents"
t.integer "fixed_fee_table_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "amount_cents"
t.integer "position"
t.integer "total_adjustment_cents"
t.string "currency"
end
I know there are a lot of topics on this already but I couldn't find any that were what I'm trying to do. I'm just learning Rails and although I know this is probably a pretty simple fix, I'm stumped.
I'm creating a "Timeline" site. I have user accounts set up, and the user can create timelines. But, what I need to do is associate multiple timeline "events" (items to go in the timeline, the model for these is called Event) with each timeline (the model for which is called Timeline_Object). More plainly - a user has multiple timelines, and a timeline has multiple events.
The problem is that I can't get events set up with the timeline correctly. I think the association is set up correctly between users and timelines, but I'm not completely sure how to figure out what's wrong. Here are my models:
class User < ActiveRecord::Base
has_many :timeline_objects
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation,
:remember_me, :user_name
end
class TimelineObject < ActiveRecord::Base
belongs_to :user
attr_accessible :title, :user_id
has_many :events
end
class Event < ActiveRecord::Base
belongs_to :timeline_object
attr_accessible :date, :description, :time, :title, :image,
:image_width, :image_height, :timeline_objects
has_attached_file :image, :styles => { :large => "500x500>", :medium => "400x400#", :thumb => "100x100>" }
after_post_process :save_image_dimensions
validates :title, presence: true
validates :image, presence: true
validates :time, presence: true
validates :date, presence: true
def save_image_dimensions
geo = Paperclip::Geometry.from_file(image.queued_for_write[:original])
self.image_width = geo.width
self.image_height = geo.height
end
end
After running some migrations to set up the keys in the database, this is what my schema looks like:
ActiveRecord::Schema.define(:version => 20130402144923) do
create_table "events", :force => true do |t|
t.string "title"
t.string "description"
t.string "date"
t.string "time"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.integer "image_height"
t.integer "image_width"
t.integer "timeline_objects"
end
add_index "events", ["timeline_objects"], :name => "index_events_on_timeline_objects"
create_table "timeline_objects", :force => true do |t|
t.string "title"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
end
add_index "timeline_objects", ["user_id"], :name => "index_timeline_objects_on_user_id"
create_table "users", :force => true do |t|
t.string "user_name"
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
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.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
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
When I go to show the timeline (at which point all the events should be displayed), I try to loop through them with
<% #timeline_object.events.each do |event| %>
That line of code produces this error:
SQLite3::SQLException: no such column: events.timeline_object_id: SELECT "events".* FROM "events" WHERE "events"."timeline_object_id" = 4
So I realize that means I'm missing something in my database, but I'm not sure what I should change/add to make it all work.
Let me know if you need any additional info/code. Thanks in advance.
In your Events schema, you have:
t.integer "timeline_objects"
but, it should be:
t.integer "timeline_object_id"
Run a new migration to fix it:
rename_column :events, :timeline_objects, :timeline_object_id
Since each event belongs to a TimelineObject, then it needs a column that identifies the id of the object that it's associated to.
I am really under pressure and totally new to Rails. Project due in two days.
I have done a search on Rails console for a user inputted in my database user = user.find(1) and it returns.
the user has_many recipes
recipes belongs to user ....defined in user and recipe models respectively.
I am getting the error.
undefined method "recipe" for user?
This is how I created my User
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.integer "position"
t.boolean "visible", :default => false
t.string "restaurant_name", :limit => 25
t.string "username", :limit => 25
t.string "password", :limit => 50
t.string "hashed_email", :default => "", :null => false
t.string "address1", :limit => 80
t.string "address2", :limit => 80
t.string "address3", :limit => 80
t.string "county", :limit => 40
t.string "telephone", :limit => 40
t.text "web address", :limit => 60
t.string "photo_path", :limit => 100
t.text "description", :limit => 2000
t.text "salt", :string, :limit => 50
t.timestamps
end
end
def self.down
drop_table :users
end
end
Recipe
class CreateRecipes < ActiveRecord::Migration
def self.up
create_table :recipes do |t|
t.integer "user_id"
t.string "recipe_name", :limit => 100
t.integer "greedy_type", :default => 0
t.string "photo_path", :limit => 40
t.text "description", :limit => 400
t.text "recipe", :limit => 4000
t.integer "ingredient1", :limit => 40
t.integer "ingredient2", :limit => 40
t.integer "ingredient3", :limit => 40
t.integer "ingredient4", :limit => 40
t.string "permalink"
t.integer "position"
t.boolean "visible", :default => false
t.timestamps
end
add_index("recipes", "user_id")
add_index("recipes", "permalink")
end
def self.down
drop_table :recipes
end
end
users.rb
class Users < ActiveRecord::Base
has_many :recipes
end
recipe.rb
class Recipes < ActiveRecord::Base
belongs_to :users
has_many :restaurants
end
ERROR
irb(main):005:0> users.recipe
NoMethodError: undefined method `recipe' for #<Users:0x599ebc0>
from C:/RailsInstaller/Ruby1.8.7/lib/ruby/gems/1.8/gems/activemodel-3.0.9/lib/active_model/attribute_methods.rb:
392:in `method_missing'
from C:/RailsInstaller/Ruby1.8.7/lib/ruby/gems/1.8/gems/activerecord-3.0.9/lib/active_record/attribute_methods.r
b:46:in `method_missing'
If User has_many recipes, why you add field recipe_id for user? You should add user_id field to the Recipe class table. After creating recipe just store user_id and that is all you need. Cheers!
as user has many recipes,
you have to write something like to get first users recipe..
recipe = user.recipes.first
and store user_id in recipe table.