I want to get the data from many to many relationship table (Tag-Service-Category) like this below in tag/show.html.erb.
class Tag < ActiveRecord::Base
has_many :service_tags
has_many :services, through: :service_tags
end
class ServiceTag < ActiveRecord::Base
belongs_to :service
belongs_to :tag
end
class Service < ActiveRecord::Base
has_many :service_tags
has_many :tags, through: :service_tags
has_many :service_categories
has_many :categories, through: :service_categories
end
class ServiceCategory < ActiveRecord::Base
belongs_to :service
belongs_to :category
end
class Category < ActiveRecord::Base
has_many :service_categories
has_many :services, through: :service_categories
end
I wrote the code like this, but it`s not working.
#tag = Tag.find(params[:id])
<% #tag.services.each do |service| %>
<% service.categories.each do |category| %>
<span class="category" class="<%= category.id %>"><%= category.name %></span>
<% end %>
<% end %>
controllers/tags_controller.rb
class TagsController < ApplicationController
def show
#tag = Tag.find(params[:id])
#tags = Tag.all
end
end
Although you have the db relationships correct, you'll still need to call out the connecting model. Because you're doing a double many to many relationship you'll need to create an in-between array. Try adding this to your view:
<% services_array = [] %>
<% #tag.service_tags each do |service_tag| %>
<% services_array << service_tag.service %>
<% end %>
<% services_array.each do |service| %>
<span class="category">
<%= service.service_category.category.id %>
<%= service.service_category.category.name %>
</span>
<% end %>
Related
I am having a problem in the eyes when presenting the data.
I have 3 user models, sponsors and pets Result that sponsors in a table join between users and pets that are nan, my problem is in the hour to show all the sponsors of the mascot in sight and achievement but in a wrong way to La time to msotrar the data. I hope you can tell me how to fix it. Thank you.
Index.html.erb
<h1>Sponsors#index</h1>
<table class="table table-bordered table-hover table-striped" id="histories">
<thead>
<tr>
<th>Mascota</th>
<th>Padrinos</th>
<th>Apadrinar</th>
</tr>
</thead>
<tbody>
<% #pets.each do |pet| %>
<tr>
<td><%= pet.name %></td>
<td>
<% #users.each do |user| %>
<% #sponsors.each do |sponsor| %>
<% if user.id == sponsor.user_id and pet.id == sponsor.pet_id %>
<%= user.email%>
<% else %>
<p>No Tengo Padinos =-( </p>
<% end %>
<% end %>
<% end %>
</td>
<td><button>Apadrinar</button></td>
</tr>
<% end %>
</tbody>
</table>
My controller has the three models that I am sending to view.
def index
#sponsors = Sponsor.all
#users = User.all
#pets = Pet.all
end
pet.rb
class Pet < ApplicationRecord
has_many :adoptions
belongs_to :race, required: false
has_many :users, through: :sponsors
end
user.rb
class User < ApplicationRecord
has_many :pets, through: :sponsors
end
sponsor.rb
class Sponsor < ApplicationRecord
belongs_to :user
belongs_to :pet
end
The output that now shows me the attachment in the image.enter image description here
I also wonder if there is a better way to make the query, to show the respective data.
Another thing is how would I do to no longer be able to sponsor pets that I have already given a sponsor?
You are using a through table to join users and pets, but your associations aren't setup properly. For a through model, you have to have_many of the through table along with a has_many: :through association. Your associations should look like this:
class Pet < ApplicationRecord
has_many :adoptions
belongs_to :race, required: false
**has_many :sponsors**
has_many :users, through: :sponsors
end
class User < ApplicationRecord
**has_many :sponsors**
has_many :pets, through: :sponsors
end
Afther working and following diferent recomendations here is my solution.
<% #pets.each do |pet| %>
<tr>
<td> <%= pet.name %></td>
<td>
<% if pet.sponsors.any? %>
<% pet.sponsors.each do |sponsor| %>
| <%= sponsor.user_email %> |
<% end %>
<% else %>
<p>No Tengo Padinos =-( </p>
<% end %>
</td>
<td>
<%= link_to "Apadrinar", {:controller => "sponsors", :action => "new", :mascot => pet.id }%>
</td>
</tr>
<% end %>
I changed also my models.
sponsor.rb
class Sponsor < ApplicationRecord
belongs_to :user
belongs_to :pet
has_many :gifts
delegate :email, to: :user, prefix: true, allow_nil: true
end
user.rb
class User < ApplicationRecord
has_many :sponsors
has_many :pets, through: :sponsors
end
pet.rb
class Pet < ApplicationRecord
has_many :sponsors
has_many :users, through: :sponsors
end
And finally mi index on Controller.
sponsors_controller.rb
def index
# #sponsors = Sponsor.all
# #users = User.all
# #pets = Pet.all
# #pets_no_sponsors = Pet.where.not(id: Sponsor.select("pet_id")).select("id")
#pets = Pet.includes(:sponsors)
end
By making a delegation now I only make a query which sends everything necessary to my index.
I have three models, ingredient, recipe_ingredient and recipy
class Ingredient < ApplicationRecord
has_many :recipe_ingredients
end
class RecipeIngredient < ApplicationRecord
belongs_to :recipy, :dependent => :destroy
belongs_to :ingredient
end
class Recipy < ApplicationRecord
has_many :recipy_steps
has_many :recipe_ingredients, :dependent => :delete_all
end
I am trying to access the ing_name attribute in the ingredients table from recipies show page.
<% #recipe_ingredients.each do |ing| %>
<p> <%= ing.amount %> <%= ing.unit %>
<%= ing.ingredient.ing_name %>
</p>
def Show from the recipies controller:
def show
#recipe_ingredients = #recipy.recipe_ingredients
end
But I keep receiving the following error msg:
undefined method `ing_name' for nil:NilClass
My ingredient_params:
def ingredient_params
params.require(:ingredient).permit(:ing_name)
end
It does seem to work like this:
<%= Ingredient.where(id: ing.ingredient_id).pluck(:ing_name) %>
But this does not use the connection between the tables if I understand correctly? Any help? Thanks.
You have ingredient nil thats why you got the error.
Must be your controller has some before_action hook to load recipy
class RecipesController < ApplicationController
before_action :load_recipy, only: :show
def show
#recipe_ingredients = #recipy.recipe_ingredients
end
private
def load_recipy
#recipy = Recipy.find(params[:id])
end
end
You can try this to avoid this nil error(undefined method 'ing_name' for nil:NilClass)
<% #recipe_ingredients.each do |ing| %>
<p> <%= ing.amount %> <%= ing.unit %>
<%= ing.try(:ingredient).try(:ing_name) %>
</p>
From Rails 5 by default you got one required option to make ingredient always not nullable
like below
belongs_to :ingredient, required: true
It will also prevent this error of
class RecipeIngredient < ApplicationRecord
belongs_to :recipy, :dependent => :destroy
belongs_to :ingredient, required: true
end
the problem is because inside your show method #recipy is nil,
here is usually code for show
controller
def show
#recipy = Recipy.find(params[:id]) # --> you missed this line
#recipe_ingredients = #recipy.recipe_ingredients # #recipy will be null without line above
end
view
<% #recipe_ingredients.each do |ing| %>
<p> <%= ing.amount %> <%= ing.unit %> <%= ing.ingredient.ing_name %> </p>
<% end %>
I would like also add some suggestion to your model relationship as follow since Ingredient and Recipy shows many to many relationship
class Ingredient < ApplicationRecord
# -> recipe_ingredients -> recipies
has_many :recipe_ingredients, :dependent => :destroy
has_many :recipies, through: :recipe_ingredients
end
class RecipeIngredient < ApplicationRecord
belongs_to :recipy
belongs_to :ingredient
end
class Recipy < ApplicationRecord
has_many :recipy_steps
# -> recipe_ingredients -> ingredients
has_many :recipe_ingredients, :dependent => :destroy
has_many :ingredients, through: :recipe_ingredients
end
Basically I have 3 different models
class Zone < ApplicationRecord
has_many :providers
end
class Provider < ApplicationRecord
has_many :referrals
belongs_to :zone
end
class Referrals < ApplicationRecord
belongs_to :provider
end
Referrals belong to Providers which then belongs to a Zone. Now the problem im having is counting how many referrals from a zone?
this is the erb tag I tried
<% #zones.each do |z| %>
<li style="color: green">
<%= link_to z.name, z %>
<% z.providers.each do |p| %>
<%= p.referrals.count %>
<% end %>
</li>
<% end %>
But that counts the referrals from each provider and displays it. I want it to just show the total only?
class Zone < ApplicationRecord
has_many :providers
has_many :referrals, through: :providers
end
This will let you do...
z.referrals.count
I want to create a multiple form for editing scores from a different model.
The main model is a Formrule model that consists of a habtm association with a Scoretype model
and has a habtm association with a Room model.
Both models are used to query a Scores model resulting in a #scores instance. It is for this instance I want to create a form, but the problem is that no field_for are being created. I know that the #scores is populated correctly, but the form does not show up.
This is the form as I have it now
<%= form_tag '/scores/update_scores' do %>
<table>
<tr>...</tr>
<% for score in #scores %>
<% fields_for :scores, score do |score| %>
<tr>
<td>
<%= score.hidden_field(:form_id) %>
<%= score.hidden_field(:team_id) %>
<%= score.hidden_field(:scoretype_id) %>
</td>
<td>
<%= score.number_field :scorevalue %>
</td>
</tr>
<% end %>
<% end %>
</table>
<%= submit_tag 'Update' %>
<% end %>
And these are the Models:
Formrule
class Formrule < ActiveRecord::Base
belongs_to :form
has_and_belongs_to_many :scoretypes
has_and_belongs_to_many :rooms
has_many :teams, :through => :rooms
end
Scoretype
class Scoretype < ActiveRecord::Base
has_many :scores
has_and_belongs_to_many :formrules
end
Room
class Room < ActiveRecord::Base
has_many :teams
has_and_belongs_to_many :formrules
end
Team
class Team < ActiveRecord::Base
has_many :scores
belongs_to :room
belongs_to :group
end
Score
class Score < ActiveRecord::Base
belongs_to :form
belongs_to :team
belongs_to :scoretype
validates_uniqueness_of :id, :scope => [:team, :scoretype]
end
And finally, the used controller (Formrule)
def show
#formrule = Formrule.find(params[:id])
#scoretypes = #formrule.scoretypes.all.collect
#rooms = #formrule.rooms.all.collect
#teams = Team.find(:all, :conditions => {:room_id => #rooms})
#scores = Score.order("team_id").all(:conditions => {:scoretype_id => #scoretypes, :team_id => #teams})
...
end
Why is the form not showing up? any suggestions?
Thank you all in advance!
Try using <%= fields_for ... %> instead of <% fields_for ...%>.
I am a Rails newbie (from PHP). So forgive this basic data structures question:
In the controller:
#games = Game.all
#players = Player.all
In the view:
<% #games.each do |game| %>
<%= game.player_id %>
<% end %>
When iterating over the #games, instead of displaying the player id with game.player_id, I'd like to display the player's name which can be found in the Player object (:name).
How do I 'find' the correct player record by the id stored in game.player_id?
In the controller:
#games = Game.all(:include => :player)
In the view:
<% #games.each do |game| %>
<%= game.player.name %>
<% end %>
Your data model looks odd to me. For the similar problem my data model might look like this:
class Game < ActiveRecord::Base
has_many :game_players
has_many :players, :through => :game_players
end
class GamePlayer < ActiveRecord::Base
belongs_to :game
belongs_to :player
end
class Player < ActiveRecord::Base
has_many :game_players
has_many :games, :through => :game_players
end
Now in the controller I would query the games:
#games = Game.all(:include => :players)
In the view:
<%#games.each do |game| %>
<% games.players.each do |player| %>
<%= player.name %>
<%end%>
<%end%>
Edit 1
If you have a concept of team then, I will introduce the team model:
class Player < ActiveRecord::Base
has_many :team_players
has_many :teams, :through => :team_players
end
class TeamPlayer < ActiveRecord::Base
belongs_to :player
belongs_to :team
end
class Team < ActiveRecord::Base
has_many :team_players
has_many :players, :through => :team_players
belongs_to :game
# attributes name, score team size constraints etc.
end
class Game
has_many :teams
has_many :players, :through => :teams.
end
Adding a new game:
#game = Game.new
#team_a = #game.teams.build(:name => "Foo")
#team_a.players << Player.find_all_by_name(["John", "Grace"])
#team_b = #game.teams.build((:name => "Bar")
#team_b.players << Player.find_all_by_name(["Kelly", "Yuvan"])
#game.save
While querying games in your controller:
#games = Game.all(:include => [{:teams => :players}])
In your view:
<%#games.each do |game| %>
<% games.teams.each do |team| %>
<% team.players.each do |team| %>
<%= player.name %>
<%end%>
<%end%>
<%end%>