Hello i created 2 tables (categories and employees),both are in a relationship and i want to show category_name(Categories table) in my employees index view instead of id's
****Here is my Categories Table******
class CreateCategories < ActiveRecord::Migration
def self.up
create_table :categories do |t|
t.string :category_name
end
end
def self.down
drop_table :categories
end
end
****Here is my Enployees Table******
class CreateEmployees < ActiveRecord::Migration
def self.up
create_table :employees do |t|
t.string :name
t.string :last_name
t.integer :categories_id
end
execute "ALTER TABLE employees ADD CONSTRAINT fk_employees_categories FOREIGN KEY (categories_id) REFERENCES categories (id)"
end
def self.down
drop_table :employees
end
end
****Here is my Employee controller******
class EmployeeController < ApplicationController
def index
#employees = Employee.all
end
end
****Here is my Category controller******
class CategoryController < ApplicationController
def index
#categories = Category.all
end
end
****Here is my Category Model******
class Category < ActiveRecord::Base
has_many :employees
end
****Here is my Employee Model******
class Employee < ActiveRecord::Base
belongs_to :category
end
****Here is Employee view*******
<table>
<tr>
<th>Employee</th>
<th>Last Name</th>
<th>Category</th>
</tr>
<% #employees.each do |e| %>
<tr>
<td><%=h e.name %></td>
<td><%=h e.last_name %></td>
<td><%=h e.categories_id %>
</td>
Here in e.categories_id i want to show categories_name that is from my categories table
<td>
<%= link_to ("View" ,:controller=>"employee",:action=>"show", :id=>e.id ) %>
</td>
<td>
<%= link_to ("Edit", :controller=>"employee",:action=>"edit",:id=>e.id ) %>
</td>
<td>
<%= link_to ( "Delete",:controller=>"employee",:action=>"destroy", :id=>e.id ,:confirm=>"sure?" %>
</td>
</tr>
<% end %>
</table>
Can someone help me with this problem please?
In your employee index views,
<td><%=employee.categories.category_name %>
instead of
<td><%=h e.categories_id %>
<%= h e.category.category_name %>
will do the trick.
Note that if you just do this, it will cause an SQL query to be executed for each row that you're displaying (known as the N+1 problem).
So in your controller, you'll have to change
#employees = Employee.all
to
#employees = Employee.find(:all, :include => [:category])
This will force eager loading, and reduce the number of queries to 2.
(As a side note, you really should have moved on to Rails 3 by now. Rails 4 is current. Each version offers a lot more features than the last.)
In Your employee controller add this
It means that get category_name to appear on your index view instead of ID.
#category= Category.all()
#category_list=[]
#category.each do |c|
#category_list << [c.category_name,c.id]
end
and then in your index views
<td><%=employee.categories.category_name %>
I know this is a late answer, but for anyone who is looking for an answer, here is how I accomplished this,
I have a table realties that has a one to many association with features table. I used the railscast method for multiple checkbox selection, so for each realty it has certain features. I wanted to show the features of each realty in its row in the index view. I had in the show view, features are shown like this,
#realty.feature_ids
where #realty in the controller is
#realty = Realty.find(params[:id])
however, in the index view the realty.feature_ids only showed numbers only not the names.
To work this out here is what I did in the index view:
<% #realties.each do |realty| %>
<td>
<% realty.feature_ids.each do |feature| %>
<%= Feature.find(feature).name %>
<% end %>
</td>
<% end %>
so for the above question, loop through the ids with each loop, this will give you the id number, find it in the Category model with the .name method. So I guess the solution for you would look like this:
<% #employees.each do |employee| %>
<td>
<% employee.category_ids.each do |category| %>
<%= Category.find(category).name %>
<% end %>
</td>
<% end %>
I hope this will benefit someone.
Related
three-months-in beginner with Ruby on Rails here, so I apologize if any of my terminology is incorrect. I have a question about referencing outside models from a nested attribute.
I have three models. Tasks with nested attributes for Task Products, and a separate Items table with pre-populated products.
Each Task has many Task Products, and the Task Product has a "product_id" column which is in reference to an existing product in the Item table. In creating an table index of each Task, I am having trouble figuring out how to have the nested Task Product's product_id's list out the Item instead of just the bare id.
Here's the code I'm working with:
tasks_controller.rb -->
def dashboard
#tasks = Task.includes(:task_products, :storeorder).last(100)
#tasks.each do |task|
task.storeorder do |storeorder|
end
task.task_products.each do |task_product|
#item = Item.where(:id => task_product.product_id)
end
end
end
task.rb -->
class Task < ApplicationRecord
has_many :task_products
accepts_nested_attributes_for :task_products
end
task_product.rb -->
class TaskProduct < ApplicationRecord
belongs_to :task
has_many :items
end
item.rb -->
class Item < ActiveRecord::Base
belongs_to :task_product
def item_select
"#{vendor_name} (#{description})"
end
end
dashboard.html.erb -->
<td>
<% t.task_products.each do |tp| %>
# Existing code that lists each task product in a list on the table:
<p><%= tp.product_id %></p>
# The ideal code I would like to run:
<p><%= link_to #item.item_select, item_path(id: #item.id) %>
<% end %>
</td>
Any ideas how I can run the #item call as it pertains to the 'tp.product_id' code in the html file?
Appreciate any help I can get. Searching for this issue has left me with many purple links, but none of which address this particular issue.
EDIT: In case anybody happens upon this that was in the same predicament as me, I have one recommendation: Learn your associations.
Updated code:
tasks_controller.rb -->
def dashboard
#tasks = Task.includes(:task_products, :storeorder).last(100)
end
task.rb -->
class Task < ApplicationRecord
has_many :task_products
accepts_nested_attributes_for :task_products
end
task_product.rb -->
class TaskProduct < ApplicationRecord
belongs_to :task
belongs_to :item, foreign_key: :product_id
end
item.rb -->
class Item < ActiveRecord::Base
has_many :task_products, foreign_key: :product_id
def item_select
"#{vendor_name} (#{description})"
end
end
dashboard.html.erb -->
<td>
<% t.task_products.each do |tp| %>
<% tp.items.each do |item| %>
<p><%= link_to item.item_select, item_path(item) %></p>
<% end %>
<% end %>
</td>
First, by using Item.where in your controller, you're actually setting #item to a collection of Items. Second, by setting it inside a loop, you're overwriting it with each TaskProduct, so only the last one will be accurate in the view.
I'm assuming you want to list [a subset of] every Item for every Task. In that case, you'd be better not to set them in your controller at all:
def dashboard
#tasks = Task.includes(:task_products, :storeorder).last(100)
end
Instead, just loop through them in the view:
<% #tasks.each do |t| %>
Task <%= t %>
<% t.task_products.each do |tp| %>
TaskProduct <%= tp %>
<% tp.items.each do |item| %>
<p><%= link_to item.item_select, item_path(item) %></p>
<% end %>
<% end %>
<% end %>
I don't see any need of all the loops in your dashboard_controller.rb
#tasks.each do |task|
task.storeorder do |storeorder|
end
task.task_products.each do |task_product|
#item = Item.where(:id => task_product.product_id)
end
end
Here's what you need in html.erb:
# The ideal code I would like to run:
<% tp.items.each do |item| %>
<p><%= link_to item.item_select, item_path(item) %>
<% end %>
Rows & columns, baby. Rows & columns.
Within one table:
When a User adds a new :name & :metric I want it to create a new column.
When a User adds a new :result_value & :date_value I want it to create a new row.
This is what my table currently looks like:
For the life of me I can't figure out why something that seems so elementary is so difficult. I don't know if I'm suppose to create the rows and columns in the database, model, helper or index view and/or if I should be using some other language or gem to help me. Any direction would be greatly appreciated because a dozen google searches hasn't done it for me.
Do I use add_column in the database or something?
class CreateQuantifieds < ActiveRecord::Migration
def change
create_table :quantifieds do |t|
t.string :categories
t.string :name
t.string :metric
t.timestamps null: false
end
end
end
Or do I add columns via the model?
class Quantified < ActiveRecord::Base
belongs_to :user
has_many :results #correct
accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true #correct
scope :averaged, -> { where(categories: 'averaged') }
scope :instance, -> { where(categories: 'instance') }
CATEGORIES = ['averaged', 'instance']
end
class Result < ActiveRecord::Base
belongs_to :user
belongs_to :quantified
end
Or do I keep playing around with the index view I've tried all sorts of 's and html tags, but I could never get the code to look like above, which is why I think the answer may lie deeper.
<!-- Default bootstrap panel contents -->
<div id="values" class="panel panel-default">
<div class="panel-heading"><h4><b>AVERAGE</b></h4></div>
<table>
<% #averaged_quantifieds.each do |averaged| %>
<% if averaged.user == current_user %>
<th><%= averaged.name %> (<%= averaged.metric %>)</th>
<td><% averaged.results.each do |result| %>
<tr><td><%= result.date_value.strftime("%m-%Y") %></td>
<td><%= result.result_value %></td></tr>
<% end %></td>
<% end %>
<% end %>
</table>
</div>
<br>
<br>
<br>
<br>
<!-- Default bootstrap panel contents -->
<div id="values" class="panel panel-default">
<div class="panel-heading"><h4><b>INSTANCE</b></h4></div>
<table>
<% #instance_quantifieds.each do |instance| %>
<% if instance.user == current_user %>
<th><%= instance.name %> (<%= instance.metric %>)</th>
<td><% instance.results.each do |instance| %>
<tr><td><%= result.date_value.strftime("%m-%Y") %></td>
<td><%= result.result_value %></td></tr>
<% end %></td>
<% end %>
<% end %>
</table>
</div>
<div class="values-button">
<%= link_to new_quantified_path, class: 'btn' do %>
<b><span class="glyphicon glyphicon-plus"</span></b>
<% end %>
</div>
I think you may have a misunderstanding of how the database should be used.
I don't think you would ever want the actual database tables to be dynamic. Instead, you should set up two tables. One for the User, and one for the Metrics. Then a user can add new metrics.
# == Schema Information
# Table name: users
# id :integer
Class User < ActiveRecord::Base
has_many :metrics
end
# == Schema Information
# Table name: metrics
# id :integer
# type :string
# result :string
# user_id :integer
Class Metric < ActiveRecord::Base
belongs_to :user
end
This way, you can create as many types of metrics as you want. And you can determine who the metric belongs to by the :user_id field.
Reading this from head to toe should help: http://guides.rubyonrails.org/association_basics.html
I am developing an app in rails that requires retrieving the total number of votes per day.
I have the following migrations,
class CreateVotes < ActiveRecord::Migration
def self.up
create_table :votes, :primary_key => :vote_id do |t|
t.string :client_id
t.integer :satlevel_id
t.integer :service_id
t.date "date", :default => Date.today
t.timestamps
end
end
end
class CreateSatlevels < ActiveRecord::Migration
def self.up
create_table :satlevels, :primary_key => :satlevel_id do |t|
t.string :name
t.timestamps
end
end
end
currently, i have the following in my controller.
class AdminController < ApplicationController
def index
render :layout => 'admin'
end
def forth
#votes = Vote.all
#satlevel = Satlevel.all
#result = Satlevel.joins(:votes)
#result2 = #result.find_by_sql("select name, date, count(*) as 'total_votes' from satlevels left join votes on satlevels.satlevel_id = votes.satlevel_id group by satlevels.satlevel_id ")
end
end
and this is what i have in my view,
<tr width = "100%">
<th>DATE</th>
<% #result2.each do |result| %>
<th><%= result.name%></th>
<% end%>
</tr>
<% #result2.each do |result| %>
<tr>
<td><%= result.date %></td>
<% #result2.each do |result| %>
<td><%= result.total_votes %></td>
<% end %>
<% end %>
</tr>
<tr>
This outputs the total number of votes for each day but instead of having one row for each date, each vote has its own row and date displayed together with the total votes.
I need help to output the count of all objects created in one day into a single row
Not entirely sure what you're asking here, but it looks like you're grouping by satlevel_id instead of on the date? From your view code it looks like you're wanting to group by date AND name?
Also, are you not following Rails conventions with your naming? Is your satlevels table's id actually satlevel_id or is it just id?
Making the assumptions that you're trying to count the number of occurrences for a name and a date AND you ARE actually using Rails conventions, here's how I would write the method:
def forth
#result = Satlevel.select('satlevels.name, votes.date, count(votes.*) as total_votes')
.joins(:votes)
.group('satlevels.name, votes.date')
.order('satlevels.name, votes.date')
end
How to sort this by count of events?
I tried diffrences ways but it still doesn't work:
<tr>
<% User.all.each do |user| %>
<td> <%= user.name %></td>
<td> <%= user.events.count %></br></td>
<% end %>
</tr>
And this is a model:
class User < ActiveRecord::Base
has_many :events
Thanks for answers.
You can achieve it through counter_cache
class Event < ActiveRecord::Base
belongs_to :user, dependent: :destroy,counter_cache: true
end
Add a column events_count to your users table like this
add_column :users, :events_count, :integer, :default => 0
and use it in the view like this
<tr>
<% User.all.each do |user| %>
<td> <%= user.name %></td>
<td> <%= user.events_count %></br></td> #here
<% end %>
</tr>
I would like to suggest to look into this Railscasts,but it is old.
Look in to this plugin And here is an example how it is done.
Hope it helps.
I have two tables - positions table with the fields id, position_id, first_name and last_name. The other table is positionslist with the fields id, positions.How will i able to join that two tables?
Here's my positionscontroller:
class PositionsController < ApplicationController
def index
##positions = Position.all(:order=>'updated_at DESC')
#positions = Position.joins(:positions => :positionlists)
end
def new
#position = Position.new
end
def create
#position = Position.new(params.require(:position).permit(:position_id, :first_name, :last_name))
if #position.save
redirect_to(:controller=>'positions')
else
render 'new'
end
end
def edit
#position = Position.find(params[:id])
end
def update
#position = Position.find(params[:id])
if #position.update(params.require(:position).permit(:position_id, :first_name, :last_name))
redirect_to(:controller=>'positions')
else
render 'edit'
end
end
def destroy
#position = Position.find(params[:id])
#position.destroy
redirect_to(:controller=>'positions')
end
end
my models position.rb
class Position < ActiveRecord::Base
has_many :positionlists
has_many :positionlists , :through => :positions
validates :first_name, length: { in: 4..20}
validates :last_name, length: { in: 4..20}
end
my models positionlists.rb
class Positionlists < ActiveRecord::Base
has_many :positions
end
any my postions index.html.erb
<% content_for :title, "Positions" %>
<%= render "layouts/nav" %>
<div class="clear"></div>
<h1>Positions List</h1>
<%= link_to "Add", new_position_path, :class =>'btn btn-success' %>
<br />
<br />
<table class="table">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Position</th>
<th>Options</th>
</tr>
<% #positions.each do |positions| %>
<tr>
<td><%= positions.first_name %></td>
<td><%= positions.last_name %></td>
<td><%= positions.position_id %></td>
<td>
<%= link_to "Edit", edit_position_path(positions)%> |
<%= link_to "Delete", position_path(positions),
method: :delete, data:{confirm: 'Are you sure you want to delete this?.' }%>
</td>
</tr>
<% end %>
</table>
any help is greatly appreciated! thanks
Rails takes care of this for you.
class PositionList < ActiveRecord::Base
has_many :positions
end
class Position < ActiveRecrod::Base
belongs_to :position_list
end
Also your position needs a position_list_id column for simplicity. If I'm understanding what you are trying to do here.
Other problems: naming your class PositionLists and not PositionList will confuse Rails automagic naming conventions.
Also you have an odd set of columns in your tables. For what you want as far as I can tell your positions table needs to have the columns:
first_name
last_name
id (automatic)
You don't appear to have anything in your position_list table so there's no column you need there outside of the automatic id column. The association is automatic from the belongs_to in the Position class and the position_list_id column in the positions table.
If you want to get an idea of how simple this all can be try running an automatic scaffolding, looking at how it's done there, and learning from that. Maybe a generate a fresh Rails app and then run something like this:
rails g scaffold position_list name
rails g scaffold position first_name last_name position_list:references
This will give you position_list.positions to get all positions for any position_list or Position.all for a list of all positions.
Also it sounds like a lot of Rails is new to you. Hartl's classic is a great intro: http://ruby.railstutorial.org/ruby-on-rails-tutorial-book