Easy for anyone but this newbie, I'm sure, but I can't find the answer anywhere. I have a User model and a Role model, with role_id in the users table; I want to show the actual role (Admin, Visitor, etc) which resides in the roles table, on my users index page.
The pertinent section of the index.html.erb:
<% #users.each do |user| %>
<tr>
<td><%= user.username %></td>
<td><%= user.email %></td>
<td><%= user.role_id %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
So what do I put in place of user.role.id?
role.rb:
class Role < ActiveRecord::Base
end
user.rb:
class User < ActiveRecord::Base
has_one :role
end
I'm using Rails 3, fwiw.
TIA
Your models are indeed configured incorrectly, but from what I can understand of the question you want the following.
class User < ActiveRecord::Base
belongs_to :role
end
class Role < ActiveRecord::Base
has_many :users
end
And then you can do the following:
<%= user.role.name_field %>
This will allow multiple Users to all have the same role. Instead of enforcing a one to one relationship. No schema change is needed.
Related
i'll start how my models looks:
User -> has_one :customer, has_one :employee, has_many :appointments
Customer -> belongs_to :user
Employee -> belongs_to :user
Appointment -> belongs_to :user
And now in view:
<% #appointments.order(:appointment_date).each do |appointment| %>
<% if appointment.confirmation == wait_or_confirmed?(#status) %>
<tr>
<td><%= appointment.purpose %></td>
<td><%= appointment.appointment_date %></td>
<td><%= appointment.appointment_time %></td>
<td><%= Employee.find(appointment.employee_id).first_name %> <%= Employee.find(appointment.employee_id).last_name %></td>
<td><%= Customer.find(appointment.customer_id).first_name %> <%= Customer.find(appointment.customer_id).last_name %></td>
<td><%= link_to 'Show', appointment_path(appointment), class: "btn btn-primary" %></td>
</tr>
<% end %>
<% end %>
My brother told me i shouldnt pick up informtaions from database in views so i tried using includes:
#appointments = Appointment.all
#users = User.includes(:appointments)
And after combination in view it still doesn't work. Can someone help me?
Instead of this:
Employee.find(appointment.employee_id).first_name
Do this:
appointment.employee.first_name
For performance, in the controller, you can also replace this:
#appointments = Appointment.all
With this:
#appointments = Appointment.all.includes(:employee, :customer)
By doing so, you are eager-loading all associated employee and customer data from the database in a single query, rather than one at a time.
I'm trying to use recursive association in Ruby on Rails and I'm not getting the expected output :) I want to have match with two players (winner and loser) and I thought about recursive association.
I used scaffolds to get the basics done:
rails g scaffold Player firstname:string lastname:string
rails g scaffold Match date:date result:integer winner:references loser:references
And then modified Match model:
class Match < ActiveRecord::Base
has_one :winner, class_name: 'Player', foreign_key: 'id'
has_one :loser, class_name: 'Player', foreign_key: 'id'
end
However if I add manually some players and go to match#index both winner and loser are the same (even if I set them to be different).
Part of view is like this:
<tbody>
<% #matches.each do |match| %>
<tr>
<td><%= match.date %></td>
<td><%= match.result %></td>
<td><%= match.winner %></td>
<td><%= match.loser %></td>
<td><%= link_to 'Show', match %></td>
<td><%= link_to 'Edit', edit_match_path(match) %></td>
<td><%= link_to 'Destroy', match, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
When I edit Match, then I clearly see that there are different IDs of players, but in show or index both players are the same.
What am I doing wrong?
Thank you :)
You are using an "has_one" association, which is actually setting the database link on the other class/table (here, Player). This is not what you want: you want to have two foreign keys (winner_id and loser_id) on the Match table.
This can be done using the much more common "belongs_to" association:
class Match < ActiveRecord::Base
belongs_to :winner, class_name: "Player"
belongs_to :loser, class_name: "Player"
end
I got a small app where I got a simple user model, and I'm currently trying to add some soft delete functionality (yes, I know there are some gems for this). Works fine for users, however when I delete a user, the associated topic view collapses as it cannot find the deleted user anymore due to the default scope I guess.
Any idea how to get arround this?
class User < ActiveRecord::Base
has_many :topics
has_many :comments
default_scope { where(active: true) }
end
def index
#topics=Topic.all
end
class UsersController < ApplicationController
def index
if current_user and current_user.role == "admin"
#users=User.unscoped.all
else
#users=User.all
end
end
Part of the view (topic.user.name is where it stops working):
<% #topics.each do |topic| %>
<tr>
<td><%=link_to topic.title, topic %></td>
<td><%=h topic.description %></td>
<td><%= topic.user.name %></td>
<td><%=h topic.created_at.strftime('%Y %b %d %H:%M:%S') %></td>
<td><%=h topic.updated_at.strftime('%Y %b %d %H:%M:%S') %></td>
</tr>
<% end %>
This is why default_scope is evil. By now you've realized that having a default_scope can lead to a wild goose chase.
You can change user.rb to this:
class User < ActiveRecord::Base
has_many :topics
has_many :comments
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) } # can be used in future when you want to show a list of deleted user in a report or on admin panel.
end
then controller:
class UsersController < ApplicationController
def index
#users = User.scoped
#users = #users.active if current_user && current_user.role != 'admin'
end
end
view will have no problem of your topics#index now:
<% #topics.each do |topic| %>
<tr>
<td><%=link_to topic.title, topic %></td>
<td><%=h topic.description %></td>
<td><%= topic.user.name %></td>
<td><%=h topic.created_at.strftime('%Y %b %d %H:%M:%S') %></td>
<td><%=h topic.updated_at.strftime('%Y %b %d %H:%M:%S') %></td>
</tr>
<% end %>
Whenever you want to display active users just do: #users = User.active.
Use this, and leave the associations as it is.
<td><%= topic.user.try(:name) %></td>
I have several models in nested attributes that I'm working with.
I have "teams" (has many constests), and "contests" (belongs to Team). But I also want contests to reference "categories" as a child object (a contest can only have one category, and a category can have may contests).
The way the logic works is that a team is created first, then a contest, and after that I want to be able to select from a list of categories (in a partial) and establish the association (set the category_id in contest to the id value in a category). It makes sense to me how this is done when creating a new contest as a child of team, but I am hitting my head agains the wall when it comes to creating the second relationship (existing contest to an existing parent category).
The controller that gives me the show view for a contest is:
def show
#team = Team.find(params[:team_id])
#contest = Contest.find(params[:id])
#categories = Category.all
respond_to do |format|
format.html # show.html.erb
format.json { render json: [#contest] }
end
end
In the show view I have this code:
<p><b>Name:</b><%= #contest.name %></p>
<%= link_to 'Edit', edit_team_contest_path(#team, #contest) %> |
<%= link_to 'Back', team_contests_path %>
<br />
<%= render 'categories/index'%>
And my partial _index for categories contains this code:
<table>
<% #categories.each do |category| %>
<tr>
<td><%= category.level1 %></td>
<td><%= category.level2 %></td>
<td><%= category.level3 %></td>
<td><%= category.level4 %></td>
<td><%= link_to 'Show', category %></td>
<td><%= link_to 'Edit', edit_category_path(category) %></td>
<td><%= link_to 'Destroy', category, confirm: 'Are you sure?', method: :delete %></td>
<%end%>
</table>
Where I am so flummoxed is where to place the code (in the Contest or Category controller?) for setting the category-contest parent-child relationship, as well as which view (the Contest show view, or the Category _index partial?). I am pretty certain that I am not understanding something fundamental about Rails here, so if anyone could point me to the docs that might clear up my befuddlement I'd very much appreciate it.
Okay, here's how I ended up solving my problem (in case anyone finds it later and uses the same search terms I tried):
Models:
team.rb
has_many :contests, :dependent => :destroy
category.rb
has_many :contests
contest.rb
belongs_to :team, :foreign_key => "team_id"
belongs_to :category, :class_name => 'Category', :foreign_key =>"category_id"
accepts_nested_attributes_for :category
Controller:
contests_controller
def update
#contest = Contest.find(params[:id])
#team = #contest.team
if !params[:category_id].nil?
#category = Category.find(params[:category_id])
#contest.update_attributes(:category_id => #category.id)
end
respond_to do |format|
if #contest.update_attributes(params[:contest])
blah
else
blah
end
end
end
Categories View (_index), a partial in the contests/show view, includes these three bits of code:
<table>
<% #categories.each do |category| %>
<tr>
<td><%= form_for [category, #contest] do |f| %>
<% f.submit "Select" %>
<% end %></td>
</tr>
<%end%>
</table>
And that is what it takes to associate a record that belong to another parent with another parent in a different model (after the first relationship has been created).
I'm trying to figure out how to do a table join in one of my models.
There are points, questions, and users.
point.rb
class Point < ActiveRecord::Base
belongs_to :user
belongs_to :question
end
question.rb
class Question < ActiveRecord::Base
has_many :points
end
user.rb
class User < ActiveRecord::Base
In my Points controller I am doing this:
def index
#points = Point.all
#user_points = Point.where('user_id' => current_user)
end
And in my points/index view:
<% #user_points.each do |user_point| %>
<tr>
<td><%= current_user.name %></td>
<td><%= user_point.question_id %></td>
<td><%= user_point.correct_answer %></td>
<td><%= user_point.user_answer %></td>
</tr>
<% end %>
I need to access the name of each question in the questions table (I have the question id available in my view. I'm a n00b to rails, and can't figure out how to this with the documentation.
If you read my previous answer ignore it. I misread your question. This should work.
In your view:
<% user_points.questions.each do |question| %>
...Do whatever...
<% end %>
Take a look at the Rails Guides, especially these two:
http://guides.rubyonrails.org/association_basics.html
http://guides.rubyonrails.org/active_record_querying.html
I think you should be able to set this in your model:
class User < ActiveRecord::Base
has_many :points, :through => :questions
end
in your controller say #user_points = current_user.points
in your view. This should already work with your current code!
<% #user_points.each do |user_point| %>
<td><%= user_point.question.name %></td>
<% end %>