Good afternoon,
First post here. I have done a bit of research into this error and not finding anything helpful to me, and because stackoverflow community is my number 1 place to find a answer. I thought why not ask here.
I have created a new rails app, and have created a relation between the order and order_item model.
app/models/order.rb
class Order < ActiveRecord::Base
belongs_to :customer, foreign_key: 'customer_id'
belongs_to :shop
has_many :order_items, dependent: :destroy
end
app/models/order_item.rb
class OrderItem < ActiveRecord::Base
belongs_to :order
end
The relationship between customer and order is working because I have created a record for both.
eg
Customer.create(:customer_attributes).orders.create
but when I try to access or create a order item
Customer.first.orders.first.order_items.first || Customer.first.orders.first.order_items.create
I get the following error
ActiveRecord::StatementInvalid: Could not find table 'order_order_items'
my question is, why is it looking for the table name with the prefix twice?
below is what my migration files look like for both models
db/migrate/orders
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders do |t|
t.integer :shop_id
t.integer :customer_id
t.string :status
t.string :additional_info
t.timestamps null: false
end
end
end
db/migrate/order_items
class CreateOrderItems < ActiveRecord::Migration
def change
create_table :order_items do |t|
t.integer :order_id
t.integer :menu_item_id
t.timestamps null: false
end
end
end
Any help will be greatly appreciated. New to ruby and rails, so please excuse my lack of knowledge.
Cheers
EDITED
Hey guys! Thank for fast replies, I figured out what the problem was. Earlier in the project I had tried to implement namespacing into the models and this is what was causing the trouble. Once i moved all models directly under the app/models dir and restarted the console all worked 100%. So im guessing I dont understand enough yet of how rails handles the namespacing, but im going to try the namespacing at later stage. For now I just need a quick prototype up an running to demo to a few clients.
Once again thanks for the fast replies.
Related
Ok so what I have been doing for categories is I have had 2 tables Categories(id, name) and SubCategories(id, name, category_id) that are related through the models. I set inverse_of as you will see below.
My question is when I use to code in PHP years ago we use to have one table "Categories" and it had id, name, parent_id(0 by default) we then used that one table to control the outputs of navigations, breadcrumbs, and other navigational elements.
class CreateCategories < ActiveRecord::Migration[5.1]
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
end
end
class CreateSubCategories < ActiveRecord::Migration[5.1]
def change
create_table :sub_categories do |t|
t.string :name
t.integer :category_id
t.timestamps
end
end
end
class Category < ApplicationRecord
has_many :sub_categories, inverse_of: :category
end
class SubCategory < ApplicationRecord
belongs_to :categories, inverse_of: :sub_category
end
I have been programming in Ruby on Rails now for over 4 years and I have yet to find a real nice "Rubyway" to achieve this. Over the years I have seen examples of using what I am already using with the 2 table method, however this does not seem very intuitive because when the system gets many categories and sub categories like 100's the page load time will be impacted in processing. Is anyone useing or know of a one table method like
class CreateCategories < ActiveRecord::Migration[5.1] def change
create_table :categories do |t|
t.string :name
t.integer :parent_id
t.timestamps
end
end
end
The problem I have always had is the model and how to get the system to realize that a record can belong to a record on the same table. I have been able to achieve it manually but I have not found a way to set it up where formtastic and other gems like rails admin would play nice with it.
Seems that you're looking for a tree structure. acts_as_tree has been around for some time. If you're using PostgreSQL, the ltree extension may be of interest as well (along with the pg_ltree gem).
I've done about a billion searches and tried a number of things here but I'm still getting errors. I've recently changed to a has many through via a model called joinable(maybe thats the problem) and I can't seem to get things working straight. Part of me thinks it something small as I get the idea of it all but I'm not sure I've done it correctly. I'm also using devise.
Here is what I think are all the relevant portions
User
class User < ActiveRecord::Base
acts_as_voter
has_many :joinables
has_many :pits, through: :joinables
has_many :comments
enum role: [:user, :vip, :admin]
after_initialize :set_default_role, :if => :new_record?
class Pit < ActiveRecord::Base
validates :topic, :author, :summary, presence: true
acts_as_taggable
acts_as_votable
has_many :comments
has_many :joinables
has_many :users, through: :joinables
mount_uploader :image, ImageUploader
I created a separate table called "joinable" and now I'm stuck figuring out how to populate it. I can create a user, but can't create a pit. Do I need to revamp my controllers or is their something small I may be missing? I get the idea but some of the little details are fuzzy based on all that I've read so far. I even tried a HABTM with a join table called Pit_Users.
I'm currently getting "Could not find table 'joinables"
coming from here in my controller
def create
#pit = current_user.pits.create(pit_params)
recent migration
class Joinable < ActiveRecord::Migration
create_table :joinable do |t|
t.integer :pit_id, :user_id
t.timestamps
end
end
I've tried a number of combinations all with similar errors. Many of the tutorials/guides are good with the basics but then seem to be leaving out a few details. That or I'm just missing them. Anyways. Would love it if someone more knowledgeable could point out what are probably obvious mistakes. Thanks.
In the migration file, it should be:
class Joinables < ActiveRecord::Migration
create_table :joinables do |t|
t.integer :pit_id
t.integer :user_id
end
end
And in the app/models/joinable.rb, there should be:
class Joinable < ActiveRecord::Base
belongs_to :user
belongs_to :pit
end
You can verify if it is working at the Rails console. Try this to get a Pit record with the association:
user_1 = User.create( ... )
pit_1 = user_1.pits.create!( ... )
pit_1.users.first # should give you user as user_1
Solution is to run rails generator for model
Run from console
rails generate model Joinable pit:references user:references
And delete your migration file for
class Joinable < ActiveRecord::Migration
create_table :joinable do |t|
t.integer :pit_id, :user_id
t.timestamps
end
end
After running rails generator you will get model named Joinable that is required for relations when using through and it will create appropriate migration for you.
I've looked for many solutions on the web and I can't seem to find my answer.
I have a polymorphic association for a table links that it linked to many other tables.
Here is my models a bit simplified:
links.rb
class Links < ActiveRecord::Base
belongs_to :linkable, polymorphic: true
end
events.rb
class Event < ActiveRecord::Base
has_many :links, as: :linkable
accepts_nested_attributes_for :links
end
here is the admin form
events.rb
ActiveAdmin.register Event do
form do |f|
f.has_many :links do |link_f|
link_f.inputs "links" do
link_f.input :url
end
end
f.actions
end
end
Here's what in my schema.rb
create_table "links", force: true do |t|
t.string "url"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "linkable_id"
t.string "linkable_type"
end
It throws me that error: uninitialized constant Event::Link
I can't seem to find the problem and it is driving me nuts...
It seems like a relation is missing or something but I can't find it.
Thanks a lot for every one that can help!
I think the problem is in the way you named your models. Models are always declared as singular entities, not plural.
You should:
Rename links.rb to link.rb
Rename events.rb to event.rb
Rename class Links < ActiveRecord::Base to class Link < ActiveRecord::Base
and see if that helps.
I created a many-to-many relationship in rails, here's my models and migrations
class Channel < ActiveRecord::Base
has_and_belongs_to_many :packages
validates_presence_of :name
end
class Package < ActiveRecord::Base
has_and_belongs_to_many :channels
validates_presence_of :name
end
class CreateChannelsPackages < ActiveRecord::Migration
def change
create_table :channels_packages, :id => false do |t|
t.references :channel
t.references :package
t.timestamps
end
add_index :channels_packages, :channel_id
add_index :channels_packages, :package_id
end
end
Then i have a multiple select, but when i try to save i get this error
SQLite3::ConstraintException: constraint failed: INSERT INTO "channels_packages" ("package_id", "channel_id") VALUES (1, 1)
I tried to remove the indexes from the migration but it didn't solve it, did somebody else have this problem?
Btw i'm using Rails 3.2.6 and sqlite3 1.3.6
I think gabrielhilal's answer is not quite correct: use of extra attributes in the join table is deprecated, thus you need to remove the timestamp in your migration, then it should work just fine with the has_and_belongs_to_many wich itself is not deprecated.
If you do need additional attributes in your join table, though, has_many :through is the way to go.
There is also another question with good answers on this topic:
Rails migration for has_and_belongs_to_many join table
I don't know if it is the reason of your problem, but the has_and_belongs_to_many association is deprecated.
According to the Rails Guide:
The use of extra attributes on the join table in a has_and_belongs_to_many association is deprecated. If you require this sort of complex behavior on the table that joins two models in a many-to-many relationship, you should use a has_many :through association instead of has_and_belongs_to_many.
I know that you are not adding any extra attribute to the join table, but try changing your migration to the below, which I think is the default:
class CreateChannelPackageJoinTable < ActiveRecord::Migration
def change
create_table :channels_packages, :id => false do |t|
t.integer :channel_id
t.integer :package_id
t.timestamps
end
end
end
I created a simple example as a sanity check and still can not seem to destroy an item on either side of a has_and_belongs_to_many relationship in rails.
Whenever I try to delete an object from either table, I get the dreaded NameError / "uninitialized constant" error message.
To demonstrate, I created a sample rails app with a Boy class and Dog class. I used the basic scaffold for each and created a linking table called boys_dogs. I then added a simple before_save routine to create a new 'dog' any time a boy was created and establish a relationship, just to get things setup easily.
dog.rb
class Dog < ActiveRecord::Base
has_and_belongs_to_many :Boys
end
boy.rb
class Boy < ActiveRecord::Base
has_and_belongs_to_many :Dogs
def before_save
self.Dogs.build( :name => "Rover" )
end
end
schema.rb
ActiveRecord::Schema.define(:version => 20100118034401) do
create_table "boys", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "boys_dogs", :id => false, :force => true do |t|
t.integer "boy_id"
t.integer "dog_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "dogs", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
end
I've seen lots of posts here and elsewhere about similar problems, but the solutions are normally using belongs_to and the plural/singular class names being confused. I don't think that is the case here, but I tried switching the habtm statement to use the singular name just to see if it helped (with no luck). I seem to be missing something simple here.
The actual error message is:
NameError in BoysController#destroy
uninitialized constant Boy::Dogs
The trace looks like:
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/dependencies.rb:105:in const_missing'
(eval):3:indestroy_without_callbacks'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/callbacks.rb:337:in destroy_without_transactions'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:229:insend'
...
Thanks.
I don't see your destroy callback, but I do see a couple of problems. First, your associations need to be lowercase. So dog.rb should be:
class Dog < ActiveRecord::Base
has_and_belongs_to_many :boys
end
and boy.rb should be:
class Boy < ActiveRecord::Base
has_and_belongs_to_many :dogs
def before_save
self.dogs.build( :name => "Rover" )
end
end
Second, I believe you want to use self.dogs.create instead of self.dogs.build above, since build won't actually save the new dog object.
The accepted answer here solved my problem, only to create another one.
Here are my model objects:
class Complex < ActiveRecord::Base
set_table_name "Complexes"
set_primary_key "ComplexID"
has_and_belongs_to_many :amenities
end
class Amenity < ActiveRecord::Base
set_table_name "Amenities"
set_primary_key "AmenityID"
end
Rails uses the name of the association as the table name when creating the select query. My application runs on Unix against a legacy MySQL database and my table names are case-sensitive and don't conform to Rails conventions. Whenever my app actually tried to load the association, I would get an exception that MySQL couldn't find table amenities:
SELECT * FROM `amenities`
INNER JOIN `ComplexAmenities` ON `amenities`.AmenityID = `ComplexAmenities`.AmenityID
WHERE (`ComplexAmenities`.ComplexID = 147 )
I searched and searched and could not find a way to tell Rails to use the correct case for the table name. Out of desperation, I tried passing a :table_name option to habtm and it worked. My new Complex model looks like this:
class Complex < ActiveRecord::Base
set_table_name "Complexes"
set_primary_key "ComplexID"
has_and_belongs_to_many :amenities, :table_name => 'Amenities'
end
This works under Rails 2.3.5.
This option is not mentioned in the Ruby on Rails docs.