Rails 4 - Object reference output when displaying value from different model - ruby-on-rails

I have three models, team, player, and ownerships. Their relationships look like this:
team.rb
class Team < ActiveRecord::Base
has_many :ownerships
has_many :players, through: :ownerships
validates :name, presence: true
validates :division, presence: true
end
player.rb:
class Player < ActiveRecord::Base
has_one :team, through: :ownership
has_one :ownership
validates :name, presence: true
validates :position, presence: true
end
ownership.rb
class Ownership < ActiveRecord::Base
belongs_to :player
belongs_to :team
validates :round, :pick, :team_id, presence: true
end
Ownerships is indexed off both player_id and team_id:
add_index "ownerships", ["player_id"], name: "index_ownerships_on_player_id"
add_index "ownerships", ["team_id"], name: "index_ownerships_on_team_id"
When I update an ownership, the player(s) show up fine when I show the team(show.html.erb). But when I display the players index view, I get weird output from <%= player.team %>. The team assignments are working, but, the team names get displayed as things like
#<Team:0x007f8f37a76f20> and #<Team:0x007f8f37a4c360>.
I've tried <%= player.team.name %>, but that throws an undefined method error.
How can I get the team names to display correctly? And what are those values I'm seeing above?
Thank you in advance.
This the pertinent part of the players index.html.erb page:
<% #players.each do |player| %>
<tr>
<td></td>
<td><%= player.name %></td>
<td><%= player.position %></td>
<td><%= player.team %></td>
</tr>
<% end %>
EDIT:
When I user <%= player.team.name %>, I get:
undefined method `name' for nil:NilClass
The index action from the players_controller.rb is basic:
def index
#players = Player.all
end
Would the way I'm selecting the players matter? I'm using a drop down menu in the ownership edit form that looks like this:
<%= form_for #ownership do |f| %>
<p>
<%= f.label :team_id %><br>
<%= #ownership.team.name %>
</p>
<p><%= f.label :player_id %><br>
<%= f.collection_select(:player_id, Player.all, :id, :name)%>
</p>
<p>
<%= f.submit %>
</p>
<% end %>

Related

simple_forms with two classes

I have one controller for Property and other one for Country one property has one country
My Property model
class Property < ApplicationRecord
acts_as_paranoid
has_one :country, class_name: Country
belongs_to :company
accepts_nested_attributes_for :country
validates :name, presence: true
validates :address, presence: true
My Country model
class Country < ApplicationRecord
acts_as_paranoid
belongs_to :property
validates :name, presence: true
validates :isoalpha2, presence: true
validates :isolapha3, presence: true
And when I want to add one property with my view (new.html.erb)
<%= simple_form_for [#property, #country], url: property_new_path do |f| %>
<% if #property.errors.any? %>
<%= pluralize(#property.errors.count, "error") %> prohibited
this property from being saved:
<% #property.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<% end %>
<%= f.input :name %>
<%= f.input :description %>
<%= f.input :address %>
<%= f.submit %>
I receive the following error:
undefined method `description' for #<Country:0x8de0b20>
I don't know why is taking the Country class instead of Property , because description is part of the Property controller
Thanks
That should be like
<%= simple_form_for [ #country, #property] do |f| %>
and routes should be in nested form
resources :countries do
resources :properties, except: [:index]
end
Hope this will work for you

Rails - checkbox form from array

I have a admin controller to create "Locations", inside of which is a form. In the form you can create a new "Location" and give it a name, description, and "exits".
<%= form_for #location do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description %><br>
<%= f.text_area :description %>
</p>
<p>
Exits:
<br/>
<% #locations.each do |e| %>
<%= f.label :locations %>
<%= f.check_box :locations %>
<% end %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
#locations is all of the available locations to set up as an "exit". I'm trying to create an array of locations inside of the new location using checkboxes to check whether or not they should be set as "exits", but not really sure how to proceed since i'm just teaching myself and it's day one.
I'm also wondering how to set up the "exits" in the Location model. Right now i have:
class Location < ActiveRecord::Base
has_many :locations
validates :name, presence: true, length: { minimum: 1 }
validates :description, presence: true
end
created with:
class CreateLocations < ActiveRecord::Migration
def change
create_table :locations do |t|
t.string :name
t.text :description
t.references :location, index: true, foreign_key: true
t.timestamps null: false
end
end
end
But i would like to have them referenced as "exits" not "locations" (ie Location.exits instead of Location.locations).
UPDATE
I've updated the form to use the collection_check_boxes helper
<%= f.collection_check_boxes(:exit_ids, #locations, :id, :name) do |cb| %>
<%= cb.label %> <%= cb.check_box %> <br/>
<% end %>
So I have this in the create action now
def create
#location = Location.new(location_params)
if #location.save
params[:location][:exit_ids].each do |e|
if e.to_i > 0
tempLocation = Location.find(e.to_i)
#location.allowExitTo(tempLocation)
end
end
redirect_to #location
else
render 'new'
end
end
Which goes allows exits through:
def allowExitTo(other_location)
exit_locations.create(to_id: other_location.id)
end
creating an exit relationship with:
class Exit < ActiveRecord::Base
belongs_to :from, class_name: 'Location'
belongs_to :to, class_name: 'Location'
validates :from_id, presence: true
validates :to_id, presence: true
end
Hope I'm on the right track. It seems to work so I guess so.
Edit: Sorry, I must have had a brain-fart or something. You're not doing a simple has-many and belongs-to relationship, you want a has-many-and-belongs-to-many relationship. That's more complicated than I know how to explain. But this answer explained it very well: Many-to-many relationship with the same model in rails?
You can get Location#exits instead of Location#locations by changing the name of the has_many relation like this:
class Location < ActiveRecord::Base
# has_many :locations Instead of this...
has_many :exits, :class_name => 'Location' # ...Do this
validates :name, presence: true, length: { minimum: 1 }
validates :description, presence: true
end
This is called a self-join. You're associating a model with itself.
Keep in mind that this will make Location#locations unavailable.
Then in your form you would do something like:
<% #locations.each do |e| %>
<%= f.label :exit %>
<%= f.check_box :exit %>
<% end %>
The Ruby on Rails site has a nice guide about associations, includeing self-joins like what you're asking about: http://guides.rubyonrails.org/association_basics.html#self-joins
If you like RailsCasts: http://railscasts.com/episodes/163-self-referential-association

Has Many Through. How to get the access?

Here is my models:
class Item < ActiveRecord::Base
has_many :price_group_lines
has_many :price_groups, through: :price_group_lines
attr_accessible :item_name, :item_id
validates :item_name, presence: true
def to_label
"#{item_name}"
end
end
class PriceGroup < ActiveRecord::Base
has_many :customers
has_many :price_group_lines
has_many :items, through: :price_group_lines
attr_accessible :price_group_name
validates :price_group_name, presence: true
def to_label
"#{price_group_name}"
end
end
class PriceGroupLine < ActiveRecord::Base
belongs_to :item
belongs_to :price_group
attr_accessible :item_id, :price_group_id, :price, :item, :price_group
validates :price, :item_id, :price_group_id, presence: true
end
View (show.html.erb) for Price Group controller
<h1> PRICE GROUP </h1>
<p> <%= #pg.price_group_name %> </p> <br>
<% #pg.items.each do |i|%>
<%= i.item_name %>
<% end %>
<br>
<%= link_to "PRICE GROUP List", price_groups_path %>
So, I have the access to item_name in show.html.erb, but i don't know how to get the access to "price" attribute in PriceGroupLine model. Something, like
i.items.price not working. Please, help!
Problem is because you have association of price, better said prices.
Your variable i is already item just call price_group_lines on it and you will get association on which you can call each and get each price.
<% #pg.items.each do |i|%>
<%= i.item_name %> # will display item name
<% i.price_group_lines.each do |pgl| %>
<%= pgl.price %> # will display price
<% end %>
<% end %>

rails: Updating a record nested two join tables deep

I have a problem that's really confusing me.
I have four models, a Workout model, an Exercise model, a workout_exercise join model, and a workout_exercise_set model.
I can add exercises to workouts through the workout_exercises join table. Now I'm trying to add sets to exercises in workouts, which is what the workout_exercises_sets table is for.
Here's an example.
Workout
Exercise 1
Set 1
Set 2
Set 3
Exercise 2
Set 1
Set 2
Set 3
Exercise 3
etc.
In workouts/edit.html.erb I have a form where I can see all the exercises in the workout, and edit the number of sets by using form_for and fields_for, but when I try to update an exercise or the entire workout I get a MassAssignmentSecurity::Error in WorkoutsController#update that says Can't mass-assign protected attributes: workout_exercise_sets. I can't figure out how to get past this. I know I'm editing a workout, but I'm not trying to write to a field called workout_exercise_sets, so I'm really confused here. I really appreciate any guidance. All relevant code is below.
workout/edit.html.erb:
<%= form_for(#workout) do |f| %>
<%= f.label :name %><br />
<%= f.text_field :name %><br />
<%= f.label :description %><br>
<%= f.text_area :description %></br>
<%= f.fields_for :workout_exercises do |s| %>
<%= s.object.exercise.name %></b>
<%= s.fields_for :workout_exercise_sets do |set| %>
<%= set.label :set_number %>:
<%= set.number_field :set_number %>
<%= set.label :reps %>:
<%= set.number_field :repetitions %>
<%= set.label :rest_time %>(seconds):
<%= set.number_field :rest_time %>
<%= set.submit %>
<% end %>
<%= s.hidden_field :_destroy %>
<%= link_to "Remove exercise?", '#', class: "remove_fields" %>
<% end %>
<%= f.submit %>
<% end %>
Here is the workout model:
class Workout < ActiveRecord::Base
attr_accessible :name, :exercises_attributes, :workout_exercises_attributes, :exercise_order, :description
has_many :workout_exercises, dependent: :destroy, :order => "exercise_order DESC"
has_many :exercises, through: :workout_exercises
accepts_nested_attributes_for :exercises
accepts_nested_attributes_for :workout_exercises, allow_destroy: :true
end
Here is the exercise model:
class Exercise < ActiveRecord::Base
attr_accessible :name, :description
has_many :workout_exercises
has_many :workouts, through: :workout_exercises
validates :name, uniqueness: :true, presence: :true
validates :description, uniqueness: :true, presence: :true
end
Here is the workout_exercise model:
class WorkoutExercise < ActiveRecord::Base
attr_accessible :exercise_id, :workout_id
belongs_to :exercise
belongs_to :workout
has_many :workout_exercise_sets, dependent: :destroy
accepts_nested_attributes_for :workout_exercise_sets, allow_destroy: :true
end
and finally, here is the workout_exercise_sets model:
class WorkoutExerciseSet < ActiveRecord::Base
attr_accessible :repetitions, :rest_time, :set_number, :workout_exercise_id
belongs_to :workout_exercise
end
And for good measure, here is a diagram of the DB:
I think in your workout_excercise.rb file, you should add :workout_exercise_sets_attributes to your attr_accessible list.
class WorkoutExercise < ActiveRecord::Base
attr_accessible :exercise_id, :workout_id, :workout_exercise_sets_attributes
belongs_to :exercise
belongs_to :workout
has_many :workout_exercise_sets, dependent: :destroy
accepts_nested_attributes_for :workout_exercise_sets, allow_destroy: :true
end

Rails Nested Form - Can't mass-assign protected attributes:

I've used the nested_form gem, whenever i try and submit something to my form i get the Can't mass-assign protected attributes:items message, even though i've already put attr_accessible in my models.
Form:
<%= nested_form_for(#goods_in) do |f| %>
...
<%= f.fields_for :items do |i| %>
<td><%= i.text_field :description, :autocomplete => :off%></td>
<td><%= i.text_field :quantity, :autocomplete => :off %></td>
<th><%= i.link_to_remove "Remove this item" %></th>
<% end %>
<%= f.submit :"Submit Delivery" %>
<% end %>
Goods In Model:class GoodsIn < ActiveRecord::Base
belongs_to :supplier
has_many :items
attr_accessible :c4lpono,
:courier,
:deliverydate,
:deliverynoteno,
:destination,
:notes,
:quantity,
:signedby,
:supplier_id,
:partcode_ids
accepts_nested_attributes_for :supplier
validates :c4lpono,
:deliverydate,
:deliverynoteno,
:destination,
:quantity,
:signedby,
:presence =>true
end
Item Model
class Item < ActiveRecord::Base
belongs_to :goods_in
attr_accessible :quantity,
:partcode,
:description,
:goods_in_id
accepts_nested_attributes_for :goods_in
end
Goods In Controller:
def create
#goods_in = GoodsIn.new(params[:goods_in])
end
you have to add
attr_accessible :items_attributes
And here's a link to the documentation :)
I think there's an error in your Goods model.
It should read has_many :items instead of has_many :item.
It's hard to tell what you are trying to achieve with your models but I think you want the folllowing:
Your GoodsIn needs to have the relationship for accepts_nested_attributes_for :items . The belongs_to and accepts_nested_attributes_for is off.

Resources