Rails Multiple Associations - ruby-on-rails

I'm having trouble setting up my associations. I'm trying to set up Courses to have different Prices depending on the Season and amount of alumns. It gets even more complicated when Seasons have different date ranges for the same Season, like for instance the first Season is from 12/24/2014 to 12/31/2014 but also from 01/07/2015 to 01/14/2015. For this I created another model Season_dates.
I can't figure out how to set up my associations, here's what I have got so far:
class Season < ActiveRecord::Base
has_many :season_dates
has_many :prices, through: :season_dates
end
class SeasonDate < ActiveRecord::Base
belongs_to :price
belongs_to :seasons
end
class Price < ActiveRecord::Base
belongs_to :course
has_many :season_dates
has_many :seasons, through: :season_dates
accepts_nested_attributes_for :season_dates
end
class Course < ActiveRecord::Base
has_many :prices
end
Form:
<%= form_for #price do |f| %>
<div class="field">
<%= f.fields_for :couse do |course_f| %>
<%= course_f.label :course %><br>
<%= course_f.collection_select :course_id, Course.all, :id, :name, {}, {class: 'form-control'} %>
<% end %>
</div>
<div class="field">
<%= f.label :alumn %><br>
<%= f.number_field :alumn, in: 1...11, step: 1, class: 'form-control' %>
</div>
<div class="field">
<%= f.fields_for :season_date do |season_f| %>
<%= season_f.label :season %><br>
<%= season_f.select :season_id, options_from_collection_for_select(Season.all, :id, :name), {}, {class: 'form-control'} %>
<% end %>
</div>
<div class="field form-group">
<%= f.label :price %><br>
<%= f.number_field :price, in: 0.01..999.99, step: 0.01, placeholder: "0.00€", class: 'form-control' %>
</div>
<div class="actions">
<%= f.submit class: 'btn btn-default' %>
</div>
<% end %>
I want to be able to call price.season.name or price.course.name. I'm not sure how to proceed, any help is appreciated.

I think you might be complicating the scenario a bit. Is there a reason that SeasonDate is its own class? Is there a way you can model like this?
class Season < ActiveRecord::Base
has_many :courses
# I would have on this model the attributes of from_date and
# to_date removing the need for a SeasonDate class
end
class Course < ActiveRecord::Base
belongs_to :season
# You might need to model this as a has_and_belongs_to_many relationship
# with a Season if a Course can belong to many seasons
end
class Price < ActiveRecord::Base
belongs_to :course
belongs_to :season
end
These models would give you methods such as:
#season.courses # would return all courses in a particular season
#price.season.name
#price.course.name
#course.prices # would return all prices associated with a particular course
If you do go for the habtm association, meaning a course can belong to many seasons, you could do something like this (guessing at your price attribute names) in your views.
<%= #course.name %>
<% #course.prices.each do |price| %>
<%= price.season.name %> : <%= price.price_in_dollars %>
<% end
This would allow you to iterate over all prices for a course and display which season they are applicable for so each person can find the best price for them.

Related

rails grouped collection select for a join table

I am creating a form for a "Review" model and i am trying to generate a nested select tag with professors and the courses they teach.
The association between professors and courses is many-to-many through the join table "Offering".
The review belongs to an offering and I want to get the IDs of the offerings inside the nested select tag.
Here are my models:
class Professor < ApplicationRecord
has_many :offerings, :dependent => :destroy
has_many :courses, :through => :offerings
has_many :reviews, :through => :offerings
end
class Course < ApplicationRecord
has_many :offerings, :dependent => :destroy
has_many :professors, :through => :offerings
end
class Offering < ApplicationRecord
belongs_to :professor
belongs_to :course
has_many :reviews
end
class Review < ApplicationRecord
belongs_to :offering
belongs_to :user
end
And here is the Review form:
<%= form_with(model: review, local: true) do |form| %>
<%= render 'shared/error_messages', locals: {resource: review} %>
<div class="form-group">
<%= form.label :body %>
<%= form.text_area :body, id: :review_body, class: 'form-control' %>
</div>
<div class="form-group">
<%= form.label :teaching_rating %>
<%= form.range_field :teaching_rating, in: 1..5, id: :review_teaching_rating, class: 'form-control slider' %>
</div>
<div class="form-group">
<%= form.label :offering %>
<%= form.grouped_collection_select :offering_id, Professor.order(:name), :courses, :name, :id, :name, class: 'form-control' %>
</div>
<div class="actions">
<%= form.submit "Submit", class: "btn btn-primary" %>
</div>
What should I pass as option_key_method parameter to the grouped_collection_select method to obtain the keys of the offerings correctly?
If there is a better approach like using two separate drop down lists for professors and courses (with the courses lists updating when the professor is selected) or using a different collection or any other approach please suggest it. I am new to rails.

Rails nested form with three models

I have three models
class Property < ActiveRecord::Base
has_many :contact
accepts_nested_attributes_for :contact
has_many :business
accepts_nested_attributes_for :business
end
class Business < ActiveRecord::Base
belongs_to :property
has_many :contact
end
class Contact < ActiveRecord::Base
belongs_to :property
belongs_to :business
end
I created a form that creates the Property with a nested contact and a nested business, how can I get that business to have a nested contact?
Here is my form
<%= form_for(#property) do |f| %>
<div class="field">
<%= f.label :address %><br>
<%= f.text_field :address %>
</div>
<% end %>
<%= f.fields_for :contact do |contact_form| %>
<div class="field">
<%= f.label :contact_title, "Title" %><br>
<%= contact_form.text_field :title %><br>
<%= f.label :contact_name, "Name" %><br>
<%= contact_form.text_field :name %><br>
</div>
<% end %>
<%= f.fields_for :business do | business_form| %>
<div class="indv-biz field">
<%= f.label :business_name, "Name" %><br>
<%= business_form.text_field :name %><br>
</div>
<div class="business-contact">
<p>Business Contact</p>
<%= f.fields_for :business_contact do | business_contact | %>
<div class="field">
<%= business_contact.label :contact_title, "Title" %><br>
<%= business_contact.text_field :title %><br>
<% end %>
<% end %>
I can get it to save so the business is connected to the property and the contact is connected to the property but I can't figure out how to get a contact connected to the business
Thanks
You should try deep nesting like this. your requirement is a property have many business which in-turn have many contacts. In this case, you actually should do is setting nested form for property with business and that business should have nested form of contacts. The below one will work for you.
Form
nested_form_for #property do |f|
...
f.fields_for :bussiness do |bussiness_form|
...
bussiness_form.fields_for :contact_form do |contact_form|
....
end
end
end
end
Models
class Property < ActiveRecord::Base
has_many :contact
has_many :business
accepts_nested_attributes_for :business
end
class Business < ActiveRecord::Base
belongs_to :property
has_many :contacts
accepts_nested_attributes_for :contacts
end
class Contact < ActiveRecord::Base
belongs_to :property
belongs_to :business
end
controller
def property_params
params.require(:property).permit(:id,.., :bussiness_attributes => [:id,.., , :contacts_attributes => [:id, ..]])
end

Provide another model's fields for nested form in Rails

I have a Rails app I'm building to manage a fantasy tennis bracket game.
Here are my models.
The game where the players will submit their picks:
class Game < ActiveRecord::Base
belongs_to :user
belongs_to :event
has_many :picks, dependent: :destroy
accepts_nested_attributes_for :picks
The matches where I match up two tennis players:
class Match < ActiveRecord::Base
belongs_to :event
belongs_to :player_1, class_name: "Player"
belongs_to :player_2, class_name: "Player"
has_many :picks, dependent: :destroy
The pick model.
class Pick < ActiveRecord::Base
belongs_to :game
belongs_to :match
I am using a nested form inside of another form which I have working.
<%= form_for(#game) do |f| %>
<% if #game.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#game.errors.count, "error") %> prohibited this game from being saved:</h2>
<ul>
<% #game.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :user_id %><br>
<%= f.collection_select(:user_id, User.all, :id, :name) %>
</div>
<div class="field">
<%= f.label :event_id %><br>
<%= f.collection_select(:event_id, Event.all, :id, :title) %>
</div>
<div class="field">
<%= f.label :score %><br>
<%= f.number_field :score %>
</div>
<% #matches.each do |g| %>
<%= f.fields_for :picks do |ff| %>
<fieldset>
<%= ff.label :match_id %>
<%= ff.text_field :match_id %>
<%= ff.label :winner, "Select the Winner" %>
<%= ff.text_field :winner %>
</fieldset>
<br>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I would like to use the fields from the Match model to populate the fields on the Pick model. For example, the Match has two players, I want to be able to pull the player's names into the :picks form, and will probably use an f.select on them.
I have some player data on the Match model I want to dynamically pull into the Pick model. Can't figure out how to query the database and get the field attributes to be accessed by the Pick nested form. Any help would be appreciated.
Here's what I'd do.
Get rid of "games"
Make "picks" the model to store "game" information
I think the major issue you have currently is the Game and Pick models are trying to do the same thing.
#app/models/match.rb
class Match < ActiveRecord::Base
# columns id | event_id | name | player_1 | player_2
belongs_to :event
has_many :picks
belongs_to :player_1, class_name: "Player", primary_key: :player_1
belongs_to :player_2, class_name: "Player", primary_key: :player_2
def players
[player_1, player_2]
end
end
#app/models/pick.rb
class Pick < ActiveRecord::Base
# columns id | user_id | match | winner | etc
belongs_to :user
belongs_to :match, primary_key: :match
has_one :winner, primary_key: :winner
end
This means you'll be able to do the following:
#app/views/picks/new.html.erb
<% #matches.each do |match| %>
<%= match.name %>
<%= form_for match.picks.new do |f| %>
<%= f.hidden_field :match, match.id %>
<%= f.collection_select :winner, match.players, :id, :name, prompt: "Who will win?" %>
<%= f.submit %>
<% end %>
<% end %>
#app/controllers/picks_controller.rb
class PicksController < ActionController::Base
def new
#matches = Match.all
end
def create
#pick = Pick.new pick_params
#pick.save
end
private
def pick_params
params.require(:pick).permit(:match, :winner).merge(user_id: current_user)
end
end
This will give you the ability to "pick" the players in the most simple & extensible way.

Rails uninitialized constant for an association

So there is a plethora of questions about the "uninitialized constant" error, and it's almost always due to an incorrectly specified association (e.g. plural model names instead of singular, incorrectly writing your association inside the model, etc). My models and form look spotless, so maybe this is something new (or I'm blind)?
A "user" has one "move". A "move" has many "neighborhood_preferences", and through this, many "neighborhoods".
Models:
class User < ActiveRecord::Base
has_one :move
accepts_nested_attributes_for :move, allow_destroy: true
end
class Move < ActiveRecord::Base
belongs_to :user
has_many :neighborhood_preferences
has_many :neighborhoods, through: :neighborhood_preferences
accepts_nested_attributes_for :neighborhood_preferences, allow_destroy: true
end
class NeighbhoodPreference < ActiveRecord::Base
belongs_to :neighborhood
belongs_to :move
end
class Neighborhood < ActiveRecord::Base
belongs_to :city
has_many :neighborhood_preferences
has_many :moves, through: :neighborhood_preferences
end
View:
<%= simple_form_for(#user, :html => { class: :form } ) do |u| %>
<%= u.fields_for :move do |m| %>
<div>
<%= m.label :start_date %>
<%= m.date_field :start_date %>
</div>
<div>
<%= m.label :end_date %>
<%= m.date_field :end_date %>
</div>
<div>
<%= m.label :min_price %>
<%= m.text_field :min_price %>
</div>
<div>
<%= m.label :max_price %>
<%= m.text_field :max_price %>
</div>
<%= m.association :neighborhood_preferences %>
<% end %>
<%= u.submit "Save Changes" %>
<% end %>
There is a typo in class name NeighbhoodPreference.

Nested attributes don't afford me access to associated model data

Im looking for the proper way to build a form for the following data structure:
class Profile < ActiveRecord::Base
attr_accessible :name
has_many :weights
accepts_nested_attributes_for :weights
end
class Tag < ActiveRecord::Base
attr_accessible :name
has_many :weights
end
class Weight < ActiveRecord::Base
attr_accessible :weight, :profile_id, :tag_id
belongs_to :profile
belongs_to :tag
end
In the edit profile form I want to pull in all the weights and allow users to update them. I've been able to do this with nested attributes like so:
<%= form_for [:admin, #profile] do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<div class='weights'>
<%= f.fields_for :weights do |ff| %>
<%= ff.label :weight %>
<%= ff.text_field :weight %>
<% end %>
</div>
<%= f.submit %>
<% end %>
The thing is that I actually want to pull in the title of the associated tag_id on each weights row as well (so people know which weight's tag they are changing). I don't see a way to pull this info in, should I be doing some sort of join before I write this form out? Is this a silly approach?
Thanks everyone
-Neil
You should be able to get at the weight through ff.object and tag through ff.object.tag.title. Have you tried this?

Resources