Can not call my associate table in my view - ruby-on-rails

Can not call my associate table in my view. have tried this. it is an application that only adds to the players. after the press "start game" and then he should come to the result view where the results of all players. then I will of course have the name of the "players" table and then the binding results from the "results" table. now in quire, I enter bidningen in the background as long as
view:
<% #playersname.each do |p|%>
<ul>
<li><%= p.name %></li>
<li><%= p.results.try(:result) %></li>
</ul>
<%end%>
Controller:
class ResultsController < ApplicationController
def index
#playersname = Player.all
end
end
Model:
class Result < ActiveRecord::Base
# attr_accessible :title, :body
has_many :players
end
migration:
class CreateResults < ActiveRecord::Migration
def change
create_table :results do |t|
t.string "result", :limit => 40
t.string "cal", :limit => 40
t.string "sum",:limit => 300
t.timestamps
end
end
end

The CreateResults migration miss the player_id column.
Do belongs_to :player in your Result class and correct the migration (or do another one).
[Edit] I wasn't clear enough : I think you inverted the relationship logic.
You actually did the "one result has several players".
I suppose you want that a player has several results ?
class Player
has_many :results
end
class Result
belongs_to :player
end
So you can do :
#myplayer = Player.all.first
#myplayer.results #it is an array of player's results
#myplayerresult = #myplayer.results.first
puts #myplayerresult.result
If you want a one-to-one relationship, consider replacing has_many :results by has_one :result and so you can do #myplayer.result to get your result.

Related

Trouble establishing a has_and_belongs_to_many relationship in Rails

I have tried every possible suggestion I could find on here to make this work but still can't get it to happen.
I have two models: districts and former_offices -- a district can have many former offices and a former office has a district.
Districts:
class District < ApplicationRecord
has_and_belongs_to_many :former_office
end
Former Office:
class FormerOffice < ApplicationRecord
has_and_belongs_to_many :districts
end
Join Model:
class DistrictFormerOffice < ApplicationRecord
belongs_to :district
belongs_to :former_office
end
Here is my form setup for creating a new former office:
<%= bootstrap_form_for(#former_office, label_errors: true) do |f| %>
<%= f.select(:district_ids, District.all.collect { |v| ["#{v.jurisdiction.name} - #{v.name} (District #{v.district}) #{v.term_expires}", v.id ] }, { :include_blank => true}) %></div>
<% end %>
Former Offices controller:
def former_office_params
params.require(:former_office).permit(district_ids: [])
end
Migration:
class CreateJoinTableDistrictFormerOffices < ActiveRecord::Migration[5.2]
def change
create_table :districts_former_offices, id: false do |t|
t.bigint :district_id
t.bigint :former_office_id
end
add_index :districts_former_offices, :district_id
add_index :districts_former_offices, :former_office_id
end
end
I am able to create the Former Office without any errors. All the other fields populate just find, except for "districts." When I pull up the object in the console and type former_office.districts, it comes up as "nil." So it appears either data isn't being added to the database, or is added in the wrong manner.
In the views, if I set it to display #former_office.districts, it just shows up blank.
Let me know if you need further information from my end. I sense this is an easy fix...but just can't figure it out.
I don't think you can add "district_ids" directly into your FormerOffice model. Instead you need to load all the districts from the district model, like #districts = District.find(former_office[:district_ids)), and then do something like #former_office.districts = #districts

Rails 4 how to populate join table using seeds.rb

I'm practicing Rails. I want to have messages and tags for them (There should be many tags for single message and many messages for single tags). I have 2 relevant models: Messages and Tags. They are associated using has_and_belongs_to_many. I'm using ffaker to populate tables
Models:
Message:
class Message < ActiveRecord::Base
has_many :comments, dependent: :destroy
has_and_belongs_to_many :tags
end
Tag:
class Tag < ActiveRecord::Base
has_and_belongs_to_many :messages
end
Migrations:
Messages:
class CreateMessages < ActiveRecord::Migration
def change
create_table :messages do |t|
t.text :content
t.timestamps
end
end
end
Tags:
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :title
end
end
end
Join table:
class CreateMessagesTagsJoinTable < ActiveRecord::Migration
def change
create_table :messages_tags, id: false do |t|
t.references :tag, index: true
t.references :message, index: true
end
end
end
Seeds file:
5.times { Message.create([content: FFaker::CheesyLingo.paragraph]) }
Message.all.each do |msg|
rand(4).times { Comment.create([content: FFaker::CheesyLingo.sentence, message_id: msg.id]) }
2.times { msg.tags.create([title: FFaker::HipsterIpsum.word.gsub(' ','-').downcase]) }
end
Comments are irrelevant. So firstly I'm populating messages table here. Secondly I'm populating tags table from inside of messages. What I end up is populated messages and tags table where every message has 2 tags.
Now, here is the question:
How do I associate already created tags to messages and vice-versa? I know how to do so by creating them, but now I want to associate few tags to single message. I also would like to associate few messages to single, already created tag.
How to do that, what is the syntax?
This should work
Message.all.each do |msg|
rand(4).times { Comment.create([content: FFaker::CheesyLingo.sentence, message_id: msg.id]) }
tags = 2.times { msg.tags.create([title: FFaker::HipsterIpsum.word.gsub(' ','-').downcase]) }
msg.tags = tags
end
or you can do it manually
msg = Message.first
tag = Tag.first
tag.messages << msg
# or
msg.tags << tag

Count the amount of records are associated to another record

In my Ruby on Rails application I am creating a cinema system, and on the bookings/new page I am allowing the user to choose the amount of seats they require through a drop down menu. But what I want to do is display the number of seats that are currently free in the screen, for example if a screen has 50 seats and 7 have been booked I want the system to display: "There are 43 seats available." I know I will need a method for this but am unsure about how I would implement it and how I would show this message.
It is worth noting that a seat would only be booked for one showing, so it would be free for others, which means that the method would have to be able to count the amount of seats available for that showing.
Can someone please help.
bookings/form.html.erb:
<%= form_for #booking do |f| %>
<%= f.hidden_field :user_id %>
<%= f.hidden_field :showing_id %>
<%= image_tag "thor_hammer.jpg",:size => "900x250" %>
<h1>NEW BOOKING:</h1>
<tr>
<td width="350px">
<br><%= f.label :seats_quantity, 'Please Select The Amount of Seats Required:' %>
</td>
<td width="300px">
<br><%= f.select :seats_quantity, '1'..'10' %><br>
</td>
<td width="300px">
<div class="actions">
<br><%= f.submit 'Book Showing' %>
</div>
<br><%= render "/error_messages", :message_header => "Cannot save: ", :target => #booking %>
</td>
</tr>
<% end %>
Screen.rb:
class Screen < ActiveRecord::Base
has_many :seats
has_many :showings
def screens_info
"#{name}"
end
end
Seat.rb:
class Seat < ActiveRecord::Base
belongs_to :screen
end
Booking.rb:
class Booking < ActiveRecord::Base
belongs_to :user
belongs_to :showing
end
Showing.rb:
class Showing < ActiveRecord::Base
belongs_to :film
has_many :bookings
belongs_to :screen
end
Schema:
create_table "bookings", force: :cascade do |t|
t.integer "user_id"
t.integer "showing_id"
t.integer "seats_quantity"
end
create_table "screens", force: :cascade do |t|
t.string "name"
end
create_table "showings", force: :cascade do |t|
t.date "show_date"
t.time "show_time"
t.integer "film_id"
t.integer "screen_id"
end
create_table "seats", force: :cascade do |t|
t.string "row_letter"
t.integer "row_number"
t.integer "screen_id"
end
It is worth noting that whilst the seats table contains the attributes row_letter and row_number a user IS NOT booking a specific seat, just the quantity of seats they require.
In your Screen class add:
has_many :bookings, through: :showings
And then your code becomes something like:
def remaining_seats
seats.count - bookings.sum(:seats_quantity) # <-- edited when I realized there was a quantity in a booking
end
def screens_info
"#{name} (#{remaining_seats}/#{seats.count} remaining)"
end
You need to figure out two values: the total seats for a specific showing and how many of those seats are already booked. Supposing you have two variables called scr_id and shw_id where the first represents the Screen Id and the second the Showing Id.
Total seats:
total_seats = Seat.where(screen_id: scr_id).count
Total bookings:
total_bookings = Booking.where(showing_id: shw_id).count
And then you only need to compute the differente between both.
available_seats = total_seats - total_bookings
EDIT: SPECIFIC IMPLEMENTATION
It should be implemented as a method in the screen model:
def available_seatings(shw_id)
total_seats = Seat.where(screen_id: this.id).count
total_bookings = Booking.where(showing_id: shw_id).count
return total_seats - total_bookings
end
Then in the controller
#available_seatings = screen.available_seatings(shw_id)
You can then use the #available_seatings variable in the view
EDIT
The manual way of doing this would be like so:
class Showing < ActiveRecord::Base
def booked_seats
bookings.pluck(:seats_quantity).sum
end
def available_seats
seats.count - booked_seats
end
end
OLD
This looks like a good use of Rails' counter_cache.
class Booking < ActiveRecord::Base
belongs_to :showing, counter_cache: true
end
This will store the count in a column on the Showing model (which you have to add). Then when you do #showing.bookings.size (not count), it will refer to that column.
"With this declaration, Rails will keep the cache value up to date, and then return that value in response to the size method." http://guides.rubyonrails.org/association_basics.html

has_and_belongs_to_many relationship in ruby on rails

I am trying to make a website for a tennis coach using ruby on rails. I am completely new to this and I am struggling with some of the terminology. The website has a login system where users can sign in and then sign up for different events that the tennis coach has created. So basically the users can go to many events and the events can have many users attending. I have made a has_and_belongs_to_many relationship between my users table and events table and the code is below:
Here is my migration:
class CreateEventsUsers < ActiveRecord::Migration
def change
create_table :events_users, :id => false do |t|
t.integer :event_id
t.integer :user_id
end
add_index :events_users, :event_id
add_index :events_users, :user_id
add_index :events_users, [:event_id, :user_id]
end
def self.down
drop_table :events_users
end
end
Here are my models:
class User < ActiveRecord::Base
has_and_belongs_to_many :events
end
class Event < ActiveRecord::Base
has_and_belongs_to_many :users
end
Here is my event form:
<li>
<%= link_to event.title, event %>
| <%= link_to "delete", event, method: :delete %>
| *insert sign up here*
</li>
Basically my question is, how would I make a form and a controller that would let a signed in user, sign up for one of the events in the database? I have been stuck on this for days. Any help would be greatly appreciated.
I would suggest using a has_many through instead of using has_and_belongs_to for scalability issues and is a suggested practice. Coming to your requirement, I did a similar thing but with users following other users and tried to adopt some of them for your requirement.
class Event < ActiveRecord::Base
has_many : Relationship
has_many : users, :through => :Relationships
end
class User < ActiveRecord::Base
has_many :Relationship
has_many :events, :through => :Relationships
//define other methods//
def follow!(event_id)
relationships.create!(event_id: event.id)
end
end
class Relationship < ActiveRecord::Base
attr_accessible :event_id
belongs_to :events
belongs_to :users
end
You need to create the relationship migration like this
class CreateRelationships < ActiveRecord::Migration
def change
create_table :relationships do |t|
t.integer :user_id
t.integer :event_id
t.timestamps
end
add_index :relationships, :user_id
add_index :relationships, :event_id
add_index :relationships, [:user_id, :event_id], unique: true
end
end
You can try adding a button on the events page view like this.
<%= form_for(current_user.relationships.build(evnt_id: #user.id)) do |f| %>
<div><%= f.hidden_field :event_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
Relationship controller can be something like this.
class RelationshipsController < ApplicationController
def create
#user = User.find(params[:relationship][:event_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
end
end
end
This tutorial was very helpful for me in developing the application for users to follow other users. Hope it will help you too. Good luck !!
http://ruby.railstutorial.org/chapters/following-users#top
If you haven't discovered it already, you are in for a real treat if you checkout railscasts from Ryan Bates. Here is a tutorial on using checkboxes in a form with a HABTM association--actually he suggests, and you should consider it, moving to has_many, through relationship instead of HABTM.
Regardless, it should at least give you an idea of how you can make it work in your app. http://railscasts.com/episodes/17-habtm-checkboxes-revised. That episode may require a membership, however, the $9 bux/month is totally reasonable for what you're getting.

how to use array variables inside action in controller

I want to fetch all posts posted by those users who have gone to same college as the current users...So inside my welcome controller i have written following code..
class WelcomesController < ApplicationController
def index
#col = Education.select(:college_id).where(:user_id => #current_user)
#user = Education.select(:user_id).where(:college_id => #col)
#welcome = Welcome.where(:user_id => #user)
end
end
Following is my shema code for welcome and education model:
create_table "welcomes", :force => true do |t|
t.text "message"
t.integer "user_id"
end
create_table "educations", :force => true do |t|
t.integer "college_id"
t.integer "user_id"
end
#col = Education.select(:college_id).where(:user_id => #current_user)....this line returns college ids associated with current logged in user.This is working perfectly on my console which is returning following output..
[#<Education college_id: 1>, #<Education college_id: 2>]
but i dont know how to use this output in my next line,so i have written this statement which should return all the users whose college id is the output of prevous statement
#user = Education.select(:user_id).where(:college_id => #col)
and my last line should return all the posts posted by those users whose ids are inside the #user array:
#welcome = Welcome.where(:user_id => #user)
but this is not working.When i run my project i cant see any output on my page and on console i am getting following output :
SELECT welcomes.* FROM welcomes WHERE (welcomes.user_id IN (NULL))
which means its not getting any user ids..
How can i solve this ...
You can try this:
#col = Education.select(:college_id).where(:user_id => #current_user.id).all
#users = Education.select(:user_id).where(:college_id => #col.collect(&:college_id)).all
#welcome = Welcome.where(:user_id => #users.collect(&:user_id)).all
The best way I see to accomplish this is to set up a has_many_and_belongs_to_many relationship between your User and Education models. (Each Education will have many Users and each User may have multiple Eductions.) You will need to create a joining table in your database to support this type of relationship - see the Rails Guide for more information on this.
I would set up your models in this manner:
class User < ActiveRecord::Base
has_one :welcome
has_and_belongs_to_many :educations
end
class Education < ActiveRecord::Base
has_and_belongs_to_many :users
end
class Welcome < ActiveRecord::Base
belongs_to :user
end
The join table for the has_many_and_belongs_to_many join table migration (be sure to double check this code, not sure I got this exactly right):
def self.up
create_table 'education_user', :id => false do |t|
t.column :education_id, :integer
t.column :user_id, :integer
end
end
Your controller code is now much simpler and looks like this:
#welcomes = #current_user.eductions.users.welcome.all
In your view:
<% #welcomes.each do |welcome| %>
<p><%= welcome.message %></p>
<% end %>
One of the more powerful features of Ruby on Rails is the model relationships. They are a little more work up front, but if you take the time to set them up correctly they can make your life much easier, as is evidenced by the simplified #welcomes query above.
I'd recommend you to make relation between User and Collage
class User < ActiveRecord::Base
has_many :educations
has_many :colleges, :through => :educations
has_many :posts
scope :by_college_id, lambda {|cid| where("exists (select educations.id from educations where educations.user_id = users.id AND educations.college_id in (?) limit 1)", Array.wrap(cid)) }
def college_mates
self.class.by_college_id(self.college_ids).where("users.id != ?", id)
end :through => :educations
end
class Education < ActiveRecord::Base
belongs_to :user
belongs_to :college
end
So now in your controller you can write
class WelcomesController < ApplicationController
def index
#posts = #current_user.college_mates.includes(:posts).map(&:posts).flatten
# or
#posts = Post.where(user_id: #current_user.college_mates.map(&:id))
end
end
Second variant generates 3 sql-requests, first variant - only two. But this is same work with data, I think time will be also same. Usually controllers contain only few lines of code, all logic written in models. Ideally controller should contain only Post.by_college_mates_for(#curren_user.id)

Resources