My project consists of People, Events and Comments.
Users can post comments ( accounts are not necessary ) and can attend events.
I'm using a has_many: through association between the people and events but whatever I try, I can't add people to events.
I don't have a clue how I can select someone and add this person to the event_people table.
The models
class EventPeople < ActiveRecord::Base
belongs_to :event
belongs_to :people
end
class Event < ActiveRecord::Base
validates :title, presence:true, length: {minimum: 3}
validates :date_from, presence:true
validates :date_to, presence:true
validates :time_from, presence:true
validates :time_to, presence:true
has_many :comments, dependent: :destroy
has_many :people, :through => :event_people
has_many :event_people
end
class People < ActiveRecord::Base
validates :name, presence: true
validates :email, presence: true, length: { minimum: 5}
validates :birthdate, presence: true
has_many :comments
has_many :events, :through => :event_people
has_many :event_people
end
show method from the eventcontroller
def show
#event = Event.find(params[:id])
end
the table
create_table "event_people", force: true do |t|
t.integer "event_id"
t.integer "people_id"
t.datetime "created_at"
t.datetime "updated_at"
end
Delete the
has_many :event_people
in your People and Event Class
and your migration should look like:
create_table "event_people" do |t|
t.belongs_to :event
t.belongs_to :people
t.timestamps
end
You can either add them individually as klausinho is suggesting, have a from for EventPeople where you'd add one person at a time.
Or the has_many association will give you the people_ids= method on events. So you can then use collection check boxes
<%= form_for #event do |f| %>
<div class="field">
<%= f.collection_check_boxes(:people_ids, People.order(:name), :id, :name)
</div>
<% end %>
Or you could use a multiple select instead.
Related
I am trying to create a movies app where a movie can have multiple categories and a category can have multiple movies. I want to access categories of a movie like this:
aMovie.categories
I expect this query to return ActiveRecord_Associations_CollectionProxy
and the reverse also applies
aCategory.movies
Below are my models and migrations
class Movie < ApplicationRecord
validates :name, presence: true
end
class Category < ApplicationRecord
validates :name, presence: true
end
class CreateMovies < ActiveRecord::Migration[5.2]
def change
create_table :movies do |t|
t.string :name
t.text :description
t.integer :year
t.float :rating
t.timestamps
end
end
end
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
end
end
How should i adjust my migrations and models?
Thanks in advance
You should create intermediate join table
Movie_categories
belongs_to :movie
belongs_to :category
Movie
has_many :movie_categories
has_many :categories, through: :movie_categories
Category
has_many :movie_categories
has_many :movies, through: :movie_categories
You can refer to has_many through relationship in https://guides.rubyonrails.org/association_basics.html
I'm trying to build a rating system into my app and currently stuck on the associations and indices. I'm quite new to this so I need all the help I can get...
User model
class User < ActiveRecord::Base
has_many :demos
has_many :ratings
has_many :reviewed, through: :ratings, source: :reviewed'Demo'
That's part of it.
Demo model
class Demo < ActiveRecord::Base
belongs_to :user
belongs_to :subject
has_many :ratings
has_many :reviewers, through: :ratings, source: :reviewer
The subject is irrelevant.
Rating model
class Rating < ActiveRecord::Base
belongs_to :reviewed
belongs_to :reviewer
validates :rating, presence: true, numericality: { :greater_than_or_equal_to => 0, :less_than_or_equal_to => 5}
end
end
And now you can tell I'm not really sure what I'm doing.
Ratings Migration Table
class CreateRatings < ActiveRecord::Migration
def change
create_table :ratings do |t|
t.float :rating, default: 2.5
t.belongs_to :reviewed, index: true
t.belongs_to :reviewer, index: true
t.timestamps null: false
end
end
end
Demos Migration Table
class CreateDemos < ActiveRecord::Migration
def change
create_table :demos do |t|
t.references :user, index: true
t.references :subject, index: true
t.string :name
t.text :content
t.string :materials
t.timestamps null: false
end
add_index :demos, [:user_id, :subject_id, :created_at]
end
end
I haven't built a controller for ratings yet since I'm just testing the relationships using the sandbox console.
I've successfully created a Rating, but #user.reviewed and #user.ratings returns a blank array in the Active Record even though #rating has all the Demo and User ids.
This question already has an answer here:
Need help on join table, limiting results to only the resource ID
(1 answer)
Closed 8 years ago.
I have a data model that looks like so;
class Tran < ActiveRecord::Base
belongs_to :buyer
validates :buyer_id, presence: true
belongs_to :seller
validates :seller_id, presence: true
end
class Seller < ActiveRecord::Base
has_many :trans
has_many :buyers, through: :trans
validates :seller_id, presence: true
end
class Buyer < ActiveRecord::Base
has_many :trans, :foreign_key => "buyer_id"
has_many :sellers, through: :trans
validates :buyer_id, presence: true
end
And then on each Seller page I have the following code that I can successfully give a list of the seller's top Buyers descending based on their total spend.
<ol>
<% #seller.buyers.uniq{|t| t.buyer_id }.sort_by {|su| su.trans.sum(:sum)}.reverse.each do |su| %>
<li><%= su.name %> <%= su.trans.sum(:sum) %></li>
<% end %>
</ol>
This code works in that it validates only Buyers that that have bought a product from the Seller, however it does not currently validate only the Trans made with the Seller (e.g. pulls in data between ALL the Sellers).
I have tried putting in a second validation around seller.id too, but unsure how to it.
Does anyone have a solution?
So essentially the list needs to validate that on the Tran, both the seller_id is owned by the Seller, plus present in the Trans join table, and that it also pulls in the buyer_id, but only the transactions that both supplier_id and buyer_id are present.
Rather than getting the Seller and the Seller's Buyers, and then the Buyer's Trans, how about getting the Seller and the Seller's Trans(es), and then the Buyer's information from each Seller's Trans?
Remove the unwanted code..its just pure has many through association...it should be
class Buyer< ActiveRecord::Base
has_many :trans
has_many :sellers, through: :trans
validates_presence_of :sellers
##or you can use blocks also such as below for validation(not null)
has_many :sellers,through :trans,:reject_if => proc { |a| a['name'].blank? }
end
class Tran< ActiveRecord::Base
belongs_to :buyers
belongs_to :sellers
end
class Seller< ActiveRecord::Base
has_many :trans
has_many :buyers, through: :trans
validates_presence_of :buyers
end
###to get all sellers of a buyer
#buyer.sellers
##to get all buyers from a seller
#seller.buyers
To make this work..you need to have three migration files including trans table with just two column-buyer_id and seller_id which will prevent any fallback in joins between buyer/seller and hence you dont need to validate the buyer_id/seller_id
class CreateBuyersSellersTrans < ActiveRecord::Migration
def change
create_table :buyers do |t|
##ensures uniqueness
t.string :name, unique: true
t.timestamps
end
create_table :sellers do |t|
##ensures uniqueness
t.string :name, unique: true
t.timestamps
end
create_table :trans do |t|
t.belongs_to :buyer
t.belongs_to :seller t.timestamps
end
end
end
in your controller
#get all uniq buyers of a seller in array format removing empty even if exits
#sellers=#seller.buyers.flatten.compact.uniq.delete_if(&:blank?)
in your view
<ol>
<% #sellers.sort_by {|su| su.trans.sum(:sum)}.reverse.each do |su| %>
<li><%= su.name %> <%= su.trans.sum(:sum) %></li>
<% end %>
</ol>
I have a problem with a many to many relation. I've set up the relation via a third party called rtimespans.
Just like in the tutorials told:
The timespan-model:
class Timespan < ActiveRecord::Base
validates :name, presence: true
has_many :rtimespans
has_many :subgroups, through: :rtimespans
validates :start_h, presence: true
validates :start_m, presence: true
validates :end_h, presence: true
validates :end_m, presence: true
validate :e_must_be_0_60
validate :e_must_be_0_24
validate :s_must_be_0_60
validate :s_must_be_0_24
validate :e_bigger_s
def e_must_be_0_60
errors.add(:end_m,"must be 0-60") unless 0 < end_m.to_i
errors.add(:end_m,"must be 0-60") unless 60 > end_m.to_i
end
def e_must_be_0_24
errors.add(:end_h,"must be 0-24") unless 0 < end_h.to_i
errors.add(:end_h,"must be 0-24") unless 24 > end_h.to_i
end
def s_must_be_0_60
errors.add(:start_m,"must be 0-60") unless 0 < start_m.to_i
errors.add(:start_m,"must be 0-60") unless start_m.to_i < 60
end
def s_must_be_0_24
errors.add(:start_h,"must be 0-24") unless 0 < start_h.to_i
errors.add(:start_h,"must be 0-24") unless start_h.to_i < 24
end
def e_bigger_s
s=start_h.to_i*60+start_m.to_i
e=end_h.to_i*60+end_m.to_i
errors.add(:end_h,"End must be bigger than start") unless e > s
end
end
The rtimespan-model:
class Rtimespan < ActiveRecord::Base
belongs_to :timespan
belongs_to :subgroup
validates :subgroup, presence: true
validates :subgroup, presence: true
end
And the subgroup-model:
class Subgroup < ActiveRecord::Base
belongs_to :group
has_many :timespans
has_many :memberships
has_many :users, through: :memberships
has_many :translations
has_many :actioncodes, through: :translations
has_many :entries
has_many :rules
validates :name, presence: true, uniqueness: true
validates :group_id, presence: true
has_many :rtimespans
has_many :timespans, through: :rtimespans
end
Anyways, when I want to call something over the relationship, I get this Error.
ActiveRecord::StatementInvalid in Subgroups#show
Showing C:/xampp/htdocs/fluxcapacitor/app/views/subgroups/show.html.erb where line #40 raised:
SQLite3::SQLException: no such column: rtimespans.subgroup_id: SELECT "timespans".* FROM "timespans" INNER JOIN "rtimespans" ON "timespans"."id" = "rtimespans"."timespan_id" WHERE "rtimespans"."subgroup_id" = ?
Can anyone tell me, how to fix this, or at least tell me, where this error comes from?
I would check migrations as the error indicates. To find out if there's a missing column, please check your schema.rb to make sure the column exist
I Suppose the error is due to you mentioned relation to timespans two times in your Subgroup model.
You have defined
has_many :timespans and
has_many :timespans, through: :rtimespans
Please correct it in the model and check.
Found my Error! I have a "double ID":
create_table "rtimespans", force: true do |t|
t.integer "subgroup_id_id"
t.integer "timespan_id_id"
end
I created a wrong migration:
class CreateRtimespans < ActiveRecord::Migration
def change
create_table :rtimespans do |t|
t.belongs_to :subgroup_id
t.belongs_to :timespan_id
end
end
end
It should have been:
class CreateRtimespans < ActiveRecord::Migration
def change
create_table :rtimespans do |t|
t.belongs_to :subgroup
t.belongs_to :timespan
end
end
end
First time working on ruby on rails and I have an app with the following 3 models:
class User < ActiveRecord::Base
attr_accessible :username, :name, :email, :password
has_many :comments
has_many :ideas, :inverse_of => :user
end
class Idea < ActiveRecord::Base
attr_accessible :title, :description, :rank, :user_id, :status, :privacy, :created_on, :updated_on
belongs_to :user, :inverse_of => :ideas
has_many :comments
end
class Comment < ActiveRecord::Base
attr_accessible :text, :rank, :user_id, :idea_id, :created_on
belongs_to :user
belongs_to :idea
end
I have a table for Comments created like:
create_table :comments do |t|
t.string :comment_id
t.string :text
t.string :rank
t.timestamps
end
I am trying to seed for these. What I'm trying to understand is how a single comment with a parent idea and a parent user is stored in the database, since the columns can only hold one parent at a time. Should I create a separate table that holds comment_id, user_id and idea_type, where a single comment gets entered in twice for each parent?
Thanks!
It sounds like you are trying to implement Comment as a join model which indicates that a particular User's comment on an Idea. If so, you should be able to accomplish that as follows:
class User < ActiveRecord::Base
attr_accessible :username, :name, :email, :password
has_many :comments
has_many :commented_ideas, :class_name => 'Idea', :through => :comments, :source => :comment
end
class Idea < ActiveRecord::Base
attr_accessible :title, :description, :rank, :user_id, :status, :privacy, :created_on, :updated_on
belongs_to :user # the user who created the Idea
has_many :comments
has_many :commented_users, :class_name => 'User', :through => :comments, :source => :user
end
class Comment < ActiveRecord::Base
attr_accessible :text, :rank, :user_id, :idea_id, :created_on
belongs_to :user
belongs_to :idea
end
create_table :comments do |t|
t.string :text
t.string :rank
t.integer :user_id
t.integer :idea_id
t.timestamps
end