I would like to join more than three tables in Rails 3.
My code is
class offer < ActiveRecord::Base
belongs_to :user
has_many :usercomments, :dependent => :destroy
has_many :comments, :through => :usercomments, :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :usercomments, :dependent =>:destroy
has_many :comments,:through => :usercomments, :dependent => :destroy
has_many :offers, :dependent => :destroy
end
class Usercomment < ActiveRecord::Base
belongs_to :user
belongs_to :comment
belongs_to :offer
end
class Comment < ActiveRecord::Base
has_one :usercomment, :dependent => :destroy
has_one :offer, :through => :usercomments
has_one :user, :through => :usercomments
end
My schema is:
create_table "offers", :force => true do |t|
t.integer "step_id"
t.integer "user_id"
t.date "offerdate"
end
create_table "users", :force => true do |t|
t.string "firstname", :limit => 100, :default => ""
t.string "lastname", :limit => 100, :default => ""
t.string "email", :limit => 100
end
create_table "usercomments", :force => true do |t|
t.integer "user_id"
t.integer "airoffer_id"
t.integer "comment_id"
t.boolean "shared"
end
create_table "comments", :force => true do |t|
t.string "comment"
t.datetime "created_at"
t.datetime "updated_at"
end
and index.html.erb is:
<% airoffers.each do |airoffer| %>
???
<% end %>
In my html.erb page I would like to find a comment for an offer (offer_id) and an user (user_id).
It looks to me like what you want is:
class User < ActiveRecord::Base
has_many :comments
has_many :offers
end
class Offer < ActiveRecord::Base
has_many :comments
belongs_to :user
end
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :offer
end
If you want all the Comments that belong to a specific User and a specific Offer, just do Comment.where(:user_id => # :offer_id => #) and pass in the User and Offer you want.
Does this help?
This will give you an array of comments for User#123 en Offer#456
UserComment.find(:all, :conditions => {
:user_id => 123,
:offer_id => 456
}).collect(&:comment)
I would use it this way:
Comment.find(
:all,
:conditions => {
:user_id => 123,
:offer_id => 456
},
:join => :usercomment
)
OR:
Comment.find(
:all,
:conditions => [
"usercomments.user_id = ? AND usercomments.offer_id = ?",
123,
456
],
:join => :usercomment
)
Rails have a lot of beautiful ways to write queries.
Finally, i chose this solution
my code
class offer < ActiveRecord::Base
belongs_to :user
has_many :comments, :dependent => :destroy, :order => "updated_at DESC"
end
class User < ActiveRecord::Base
has_many :comments,:dependent => :destroy
has_many :offers, :dependent => :destroy
end
class Comment < ActiveRecord::Base
has_one :user, :dependent => :destroy
has_one :airoffer, :dependent => :destroy
end
schema
create_table "offers", :force => true do |t|
t.integer "user_id"
t.date "offerdate"
end
create_table "users", :force => true do |t|
t.string "firstname", :limit => 100, :default => ""
t.string "lastname", :limit => 100, :default => ""
t.string "email", :limit => 100
end
create_table "comments", :force => true do |t|
t.integer "user_id"
t.integer "offer_id"
t.string "comment"
t.datetime "created_at"
t.datetime "updated_at"
end
in offer_controller.rb
#offers = User.find(current_user.id).offers.includes(:comments)
and in my index.html.erb
<% #offers.each do |airoffer| %>
<% airoffer.comments[0].comment %>
<% end %>
I know, it's not the better solution, but in the first time i will use it.
Related
I've been running with some issues with adding a new record on my students table. Basically I have 3 tables that are associated with each other: Students, Teachers, Enrolled Subjects and Subjects.
The main issue here is that the subjects table was declared :string on both students and teachers table upon migration but is asking for an array instead:
Class CreateStudents < ActiveRecord::Migration[5.0]
def up
create_table :students, :id => false do |t|
t.integer "student_id", :auto_increment => true, :primary_key => true
t.string "first_name", :limit => 25
t.string "last_name", :limit => 50
t.string "email", :default => ' ', :null => false
t.string "birthday"
t.string "subjects"
t.string "username", :limit => 25
t.string "password_digest"
t.timestamps
end
end
class CreateTeachers < ActiveRecord::Migration[5.0]
def up
create_table :teachers, :id => false do |t|
t.integer "teacher_id", :auto_increment => true, :primary_key => true
t.string "first_name"
t.string "last_name"
t.string "email", :default => ' ', :null => false
t.string "birthday"
t.string "subjects"
t.string "username", :limit => 25
t.string "password_digest"
t.timestamps
end
end
class CreateSubjects < ActiveRecord::Migration[5.0]
def up
create_table :subjects, :id => false do |t|
t.integer "subject_id", :auto_increment => true, :primary_key => true
t.string "subject_name"
t.timestamps
end
end
class CreateEnrolledSubjects < ActiveRecord::Migration[5.0]
def up
create_table :enrolled_subjects, :id => false do |t|
t.integer "subject_id"
t.integer "teacher_id"
t.integer "student_id"
end
end
Below is my code when adding a record inside rails console:
new_studend = Student.create(:student_id => 1, :first_name => 'Karl', :last_name => 'Geek', :email => 'ss.norton#gmail.com', :birthday => '12/04/1995', :subjects => ["English"], :username => 'samnorton2', :password => 'Grace02112')
I also tried:
new_student = Student.create(:student_id => 1, :first_name => 'Jos', :last_name => 'Norton', :email => 'ss.norton#gmail.com', :birthday => '12/05/1995', :subjects => 'English', :username => 'samnorton2', :password => 'Grace02112')
But I got an error both:
When I used string 'English':
NoMethodError: undefined method `each' for "English":String
When I used array: :subjects => ['English']
ActiveRecord::AssociationTypeMismatch: Subject(#70237743894000) expected, got String(#70237706174560)
I am not sure what's happening here. But it's taking time for me to resolve. For my models I simply put the ff codes:
class Student < ApplicationRecord
has_many :enrolled_subjects
has_many :subjects, through: :enrolled_subjects
has_many :teachers, through: :enrolled_subjects
def teacher_names
self.teachers.map(&:name).join(", ")
end
has_many :admin_users
has_secure_password
self.primary_key = :student_id
scope :newest_first, lambda { order("created_at ASC") }
scope :oldest_first, lambda { order("created_at DESC") }
# scope :search, lambda { |query| where(["name LIKE ?", "%#{query}%"])}
end
class AdminUser < ApplicationRecord
has_secure_password
scope :newest_first, lambda { order("created_at ASC") }
scope :oldest_first, lambda { order("created_at DESC") }
# scope :search, lambda { |query| where(["name LIKE ?", "%#{query}%"])}
end
class EnrolledSubject < ApplicationRecord
belongs_to :student
belongs_to :subject
belongs_to :teacher
end
class Teacher < ApplicationRecord
has_many :enrolled_subjects
has_many :subjects, through: :enrolled_subjects
has_many :students, through: :enrolled_subjects
has_many :admin_users
has_secure_password
scope :newest_first, lambda { order("created_at ASC") }
scope :oldest_first, lambda { order("created_at DESC") }
# scope :search, lambda { |query| where(["name LIKE ?", "%#{query}%"])}
end
Any idea? Sorry I am new ROR. Hope someone can help me and explain in layman's term what's happening on this.
The subjects string column on teachers and students is conflicting with what rails gives you in a has_many association. You'll want to drop these columns.
def change
remove_column :students, :subjects
remove_column :teachers, :subjects
end
How in rails 4.1 enum prescribe in migration something like this?
class CreateFriendsUsers < ActiveRecord::Migration
def change
create_table :friends_users, id: false do |t|
t.integer :friend_id
t.integer :user_id
t.integer :status, [:active, :deactive]
end
end
end
this is join table for user and user
has_and_belongs_to_many :friends,
:class_name => "User",
:foreign_key => "user_id",
:association_foreign_key => "friend_id",
:join_table => "friends_users",
:after_add => :add_friend,
:after_remove => :remove_friend
Ok so I have this relationship in Rails:
class Position < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
class User < ActiveRecord::Base
has_many :companies, :through => :positions
has_many :positions
class Company < ActiveRecord::Base
has_many :positions
has_many :users, :through => :positions
Here is the schema for positions:
create_table "positions", :force => true do |t|
t.integer "company_id"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "regular_user", :default => true
end
The regular_user is signaling the admins and the employees so my question is how do set the regular_user to 0 or false from this data:
#user = User.find(params[:user_id])
#company = Company.find(params[:company_id])
#user.companies << #company
Is there a better way to do this? I was thinking:
Position.create(user_id: params[:user_id], company_id: params[:company_id], regular_user: 0)
But is there a standard for setting associations?
Try this:
class User < ActiveRecord::Base
has_many :positions
has_many :companies, :through => :positions
has_many :companies_as_non_regular_user, :through => :positions,
:conditions => {:"positions.regular_user" => false}
...
end
#user = User.find(params[:user_id])
#company = Company.find(params[:company_id])
#user.companies_as_non_regular_user << #company
I've read lots about self referential classes in Rails, but am still having problems getting them working.
I have a class of Articles and I want them to be able to refer to each other, from a source article to an outcome article - and then be able to find the reverse. So I'm trying to do a has_many through, using another class called Links.
My schema is
create_table "articles", :force => true do |t|
t.string "name"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "links", :force => true do |t|
t.integer "source_id"
t.integer "outcome_id"
t.string "question"
t.datetime "created_at"
t.datetime "updated_at"
end
The models are
class Article < ActiveRecord::Base
has_many :links_as_source, :foreign_key => "source_id", :class_name => "Link"
has_many :sources, :through => :links_as_source
has_many :links_as_outcome, :foreign_key => "outcome_id", :class_name => "Link"
has_many :outcomes, :through => :links_as_outcome
end
and
class Link < ActiveRecord::Base
belongs_to :source, :foreign_key => "source_id", :class_name => "Article"
belongs_to :outcome, :foreign_key => "outcome_id", :class_name => "Article"
end
I can create articles in the console, and I can link articles together, using a.outcomes << b but the link table is only storing the outcome_id, not the source_id.
What am I doing wrong?
I got this to work in the end. I changed the names - I don't know if that mattered. I did read somewhere that source was a silly name to use for something.
So this is what works:
My schema
create_table "article_relationships", :force => true do |t|
t.integer "parent_id"
t.integer "child_id"
...
end
create_table "articles", :force => true do |t|
t.string "name"
...
end
My article model
has_many :parent_child_relationships,
:class_name => "ArticleRelationship",
:foreign_key => :child_id,
:dependent => :destroy
has_many :parents,
:through => :parent_child_relationships,
:source => :parent
has_many :child_parent_relationships,
:class_name => "ArticleRelationship",
:foreign_key => :parent_id,
:dependent => :destroy
has_many :children,
:through => :child_parent_relationships,
:source => :child
I am trying to create search form when user search for a course it returns list of user's names who are taking that course.So i have user table,course table and user-course join table.I want o use metasearch or ransack.But i wonder how i would use these in my case.Thank you in advance.
create_table "users", :force => true do |t|
t.string "firstname"
t.string "email"
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "password_salt", :default => "", :null => false
end
create_table "courses", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "school_id", :null => false
end
create_table "user_courses", :force => true do |t|
t.integer "user_id", :null => false
t.integer "course_id", :null => false
t.boolean "active", :null => false
end
class User < ActiveRecord::Base
has_many :user_courses
has_many :courses, :through => :user_courses
has_many :active_courses, :through => :user_courses, :source => :course, :conditions => {'user_courses.active' => true}
has_many :taken_courses, :through => :user_courses, :source => :course, :conditions => {'user_courses.active' => false}
end
class UserCourse < ActiveRecord::Base
belongs_to :user
belongs_to :course
end
class Course < ActiveRecord::Base
validates_presence_of :name
has_many :user_courses
belongs_to :school
end
You can add this to your Course model:
has_many :users, :through => :user_courses
Then you can get the users from a course like so
Course.find(1).users