Rails 4 Active record circular dependency error - ruby

These are my tables:
create_table :messages do |t|
t.integer :type
t.string :text
t.datetime :sent_date
t.string :sender
t.timestamps
end
create_table :users do |t|
t.integer :phone
t.string :fullname
t.string :profile_image
t.timestamps
end
create_table :send_tos do |t|
t.string :receiver
t.belongs_to :message
t.boolean :is_received
end
and these are the model classes:
class User < ActiveRecord::Base
has_many :send_tos, :foreign_key => 'receiver'
has_many :messages, :foreign_key => 'sender'
end
class Message < ActiveRecord::Base
belongs_to :user, :foreign_key => 'sender'
has_many :send_tos
end
class Send_to < ActiveRecord::Base
belongs_to :user, :foreign_key => "receiver"
belongs_to :message
end
When I run these commands on rails console:
m = Message.new
m.save
s = Send_to.new
s.message = m
s.save
m.send_tos
After command m.send_tos I get this error:
RuntimeError: Circular dependency detected while autoloading constant
SendTo
Why am I getting this error? What should I do to change it?

Change the name of the Send_to class to SendTo. This follows the naming convention that Rails assumes for its relationships. The name of the file it is in should be send_to.rb

Related

ActiveModel::MissingAttributeError: can't write unknown attribute `attendee_id`

I am trying to create an association between a User model and an Attendance model in which an attendee_id references a user. The association is a many to many relationship between users and concerts. The join table attendances has two fields
:attendee and :concert.
seed.rb file:
require 'faker'
Concert.destroy_all
User.destroy_all
Attendance.destroy_all
15.times do
Concert.create(band: Faker::RockBand.name, venue: "#{Faker::LordOfTheRings.location}", date: Faker::Date.forward(rand(30)), start_time: "8:00 PM")
end
5.times do |number|
User.create(first_name: Faker::Name.first_name, last_name: Faker::Name.last_name, email: "#{number}#email.com", password: "password")
end
concerts = Concert.all
users = User.all
15.times do
Attendance.create(attendee: users.sample, concert: concerts.sample)
end
Here are the models:
class Attendance < ApplicationRecord
belongs_to :attendee, class_name: "User"
belongs_to :concert
end
class Concert < ApplicationRecord
validates :band, :venue, :date, :start_time, presence: true
has_many :attendances
has_many :attendees, through: :attendances
end
class User < ApplicationRecord
validates :first_name, :last_name, :email, presence: true
validates_format_of :email, with: /#/
has_secure_password
has_many :attendances, foreign_key: :attendee_id
has_many :concerts, through: :attendances
end
Here are the migrations:
class CreateAttendances < ActiveRecord::Migration[5.0]
def change
create_table :attendances do |t|
t.references :attendee
t.references :concert, index: true
t.timestamps
end
end
end
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :email
t.string :password_digest
t.timestamps
end
end
end
class CreateConcerts < ActiveRecord::Migration[5.0]
def change
create_table :concerts do |t|
t.string :band
t.string :venue
t.datetime :date
t.time :start_time
t.timestamps
end
end
end
Looks like there are no attendee_id column
bundle exec rails db:reset (same as db:drop + db:create + db:migrate + db:seed)
And for tests bundle exec rails db:test:prepare
If it`s not solve the problem, i think, we need moar stacktraces)
I run bundle exec rake db:drop and then I created the database bundle exec rake db:create and bundle exec rake db:migrate I was then able to seed the database.
Please try to change t.references to special alias t.belongs_to.
It worked for me with Rails 5.2.1

Trying to make associations with Rails

i'm learning Rails and i'm doing an exercise to practice associations and migration files.
Currently, trying to make a models between users, auction item, and bids.
So far for the migrate files I have the following:
class CreateItem < ActiveRecord::Migration
def change
create_table :auction do |t|
t.string :item_name
t.string :condition
t.date :start_date
t.date :end_date
t.text :description
t.timestamps
end
end
end
class CreateBids < ActiveRecord::Migration
def change
create_table :bids do |t|
t.integer :user_id
t.integer :auction_id
t.timestamps
end
end
end
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
t.string :username
t.string :password_digest
t.timestamps
end
end
end
These are the following models:
class Bid < ActiveRecord::Base
belongs_to :bidder, class_name: "User", foreign_key: "bidder_id"
belongs_to :auction
end
class User < ActiveRecord::Base
has_many :bids
has_many :auctions, :foreign_key => 'bidder_id'
has_secure_password
end
class Auction < ActiveRecord::Base
belongs_to :seller, class_name: "User", foreign_key: :user_id
has_many :bids
has_many :bidders, through: :bids
end
Any suggestions or opinions? I'm currently trying to test the tables but auctions doesn't seem to be working...
Specifically, my auction table can't seem to find a user_id and therefore a user doesn't have any auctions.
foreign_key refers to the _id (by default) or any unique attribute used to associate the models.
I can't see bidder model, you need to replace them with user_id as they are associated to user model.
Refer for more details belongs_to
class CreateBids < ActiveRecord::Migration
def change
create_table :bids do |t|
t.integer :user_id **do not think this is correct**
t.integer :auction_id **or this one**
t.timestamps
end
end
end
You want to use something more along the lines of the following
class CreateGames < ActiveRecord::Migration[5.0]
def change
create_table :games do |t|
t.integer :total_time
t.references :version, foreign_key: true **#this is how a foreign key should be declared**
t.integer :total_points
t.timestamps
end
end
end
Alternatively, if you want to change things in future migrations you can always add a reference:
def change
add_reference :levels, :version, foreign_key: true
end

Mysql2::Error: after updating to Rails 4.1

I recently updated my Rails app from 4.0 to 4.1. Everything seems to work fine, except this one line in my Search Model that was working before.
Essentially, I want to search/find District_Resources by Tag Name and by the District_Resource Name.
**ex.**
If I search the word "Tutoring"
*I should get all District_Resources with the Resource_Tag "Tutoring"
*And all District Resources that include the word Tutoring in it's Name.
(i.e Tutoring Services)
For some reason, I keep getting this error:
(Mysql2::Error: Unknown column 'resource_tags.name' in 'where
clause': SELECT `district_resources`.* FROM `district_resources`
WHERE (resource_tags.name like '%Tutoring%' OR district_resources.name like '%Tutoring%')
ORDER BY `district_resources`.`name` ASC):
But that column does exist in the Resource_Tags table.
MODELS
class DistrictResource < ActiveRecord::Base
has_many :district_mappings, dependent: :destroy
has_many :resource_tags, through: :district_mappings
accepts_nested_attributes_for :resource_tags
end
class ResourceTag < ActiveRecord::Base
has_many :district_mappings, dependent: :destroy
has_many :district_resources, through: :district_mappings
end
class Search < ActiveRecord::Base
def district_resources
#district_resources ||= find_district_resources
end
def find_district_resources
district_resources = DistrictResource.order(:name)
district_resources = district_resources.includes(:resource_tags).where("resource_tags.name like :name OR district_resources.name like :name", {:name => "%#{name}%" })
district_resources
end
end
SCHEMA
create_table "district_resources", force: true do |t|
t.string "name"
t.string "description"
t.string "website"
t.string "phone"
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "district_mappings", force: true do |t|
t.integer "district_resource_id"
t.integer "resource_tag_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "resource_tags", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
You are referencing district_resources in where clause but this is not joined in query as you are eager loading resource_tags so here are two solutions for this
1.
district_resources = district_resources.joins(:resource_tags).where("resource_tags.name like :name OR district_resources.name like :name", {:name => "%#{name}%" })
2.
district_resources = district_resources.includes(:resource_tags).refereces(resource_tags).where("resource_tags.name like :name OR district_resources.name like :name", {:name => "%#{name}%" })
In both of these cases we are telling rails that we are using resource_tags table in where clause so join district_resources with it
Fixed it!!
district_resources = district_resources.includes(:resource_tags).where("resource_tags.name like :name OR district_resources.name like :name", {:name => "%#{name}%" }).references(:resource_tags)
I had to reference the Resource_Tags Model

Ruby on Rails Associate pairs of one model to a second model

I'm building a rails app where I have models users, images, and image_pairs. I want each image_pair to have 2 images, named :before_image and :after_image.
So:
users have many images (many to one)
users have many image_pairs (many to one)
images may have only one image_pair
image_pairs always have 2 images
I have everything working, except I can't call #image.image_pair. I get:
PG::UndefinedColumn: ERROR: column image_pairs.image_id does not exist
How can I set this up so I can get an image_pair from its image?
schema.rb (some irrelevant fields removed)
create_table "image_pairs", force: true do |t|
t.integer "before_image_id"
t.integer "after_image_id"
end
add_index "image_pairs", ["before_image_id"], name: "index_image_pairs_on_before_image_id", using: :btree
add_index "image_pairs", ["after_image_id"], name: "index_image_pairs_on_after_image_id", using: :btree
add_index "image_pairs", ["user_id"], name: "index_image_pairs_on_user_id", using: :btree
create_table "images", force: true do |t|
t.integer "user_id"
t.integer "image_pair_id"
end
add_index "images", ["image_pair_id"], name: "index_images_on_image_pair_id", using: :btree
add_index "images", ["user_id"], name: "index_images_on_user_id", using: :btree
create_table "users", force: true do |t|
t.string "name"
end
user.rb
class User < ActiveRecord::Base
has_many :images, dependent: :destroy
has_many :image_pairs, dependent: :destroy
end
image.rb
class Image < ActiveRecord::Base
belongs_to :user
has_one :image_pair
end
image_pair.rb
class ImagePair < ActiveRecord::Base
belongs_to :user
belongs_to :before_image, :class_name => "image"
belongs_to :after_image, :class_name => "image"
end
You might add a field to image_pairs called image_id that points to the original image id. Or rename the before_image to image_id and add an alias or a method if you want to call it by the name before_image.
def before_image
self.image_id
end

Undefined method error when using "has_many :through" relationship on Rails3

I am working on a small Android project with RoR server.
Here are the three models:
class User < ActiveRecord::Base
has_many :relations
has_many :friends, :through => :relations
attr_accessor :friend_ids
end
class Relation < ActiveRecord::Base
belongs_to :user
belongs_to :friend
end
class Friend < ActiveRecord::Base
has_many :relations
has_many :users, :through => :relations
end
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :user_name
t.string :password
t.integer :city_id
t.integer :travelstyle_id
t.boolean :online
t.string :self_description
t.string :sex
t.integer :head_id
t.timestamps
end
end
def self.down
drop_table :users
end
end
class CreateFriends < ActiveRecord::Migration
def self.up
create_table :friends do |t|
t.string :user_name
t.integer :city_id
t.integer :travelstyle_id
t.string :self_description
t.string :sex
t.integer :head_id
t.timestamps
end
end
class CreateRelations < ActiveRecord::Migration
def self.up
create_table :relations do |t|
t.integer :user_id
t.integer :friend_id
t.timestamps
end
end
Model User uses model Relation to connect with model Friend. I use scaffold to creat the three models and add the relationship code in their model files. I also create a API controller to send xml file to Android application. Here is the controller code:
def find_friend
#user=User.where("id=?",params[:id])
#friend=#user.friends
respond_to do |format|
format.html
format.xml
end
end
Here is the problem, when I use the api(type in http://localhost:3000/api/find_friend/1.xml), the server throws a mistake:
NoMethodError in ApiController#find_friend
undefined method `friends' for #<ActiveRecord::Relation:0x3478a28>
app/controllers/api_controller.rb:21:in `find_friend'
I am new to Rails and have no idea where the wrong is. Do I have to add something in the "route.rb" or change the migration file?
In the rails console mode, I type in "user=User.find(1), friend=user.friends" and get the correct result.
~~~~(>_<)~~~~
The problem is the controller method "#user=User.where("id=?",params[:id])". The "where" method can not tell whether the result is an array or actually one object. If I use "#user=User.find(params[:id])", rails will be "smart enough" to know that "Oh, yes, this is just one object and it has a method called Friends because someone connects the two models together".
Learning Rails likes a marriage, you think you know well about her but sometimes you think "God actually I know nothing about the mysterious guy."

Resources