Model
class Register < ActiveRecord::Base
attr_accessor :code
belongs_to :user
end
class User < ActiveRecord::Base
has_many :register
end
Controller
def index
#registers = Register.all
end
View
<p> All Registers </p>
<table>
<tr>
<td> User </td>
<td> Point </td>
</tr>
<% #registers.each do |u| %>
<tr>
<td> <%= u.user.name %> </td>
<td> <%= u.hour %> </td>
</tr>
<% end %>
</table>
it onlys display Name instead of the field value
and the console is giving me this error
no such column: users.register_id: SELECT "users".* FROM "users" WHERE "users"."register_id" = ? LIMIT 1
First Add user_id to registers table.
Update your index action to below.
def index
#registers = Register.all
end
and view code to following.
<% #registers.each do |u| %>
<%= u.user.name %>
<%= u.hour %>
<% end %>
Update you user model to below.
class User < ActiveRecord::Base
has_many :registers
end
To add to #Dheeresha's great answer, you need to also appreciate that you actually have to associate the two objects. To do this, you can use the following (as a test):
$ rails c
$ user = User.first
$ register = Register.first
$ user.registers << register
This will ensure you have at least one register in the user.registers collection. The way to ensure this is not an issue in production / view is to use the .try method:
<% #registers.each do |u| %>
<%= u.user.try(:name) %>
<%= u.hour %>
<% end %>
The only reason you wouldn't be able to access the user object would be that it's not associated in ActiveRecord. This issue in itself could be caused by not having the associations defined correctly (as #Dheeresha pointed out), or not associating the objects (as I've mentioned).
--
Your models should look like:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :registers
end
#app/models/register.rb
class Register < ActiveRecord::Base
belongs_to :user
end
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 %>
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
I have the following models where UserTreatment is essentially a lookup table but it has another field called instance_cost which stores an integer against each relationship.
class User < ActiveRecord::Base
has_many :user_treatments
has_many :users, :through => :user_treatments
end
class UserTreatment < ActiveRecord::Base
attr_accessible :instance_cost
belongs_to :user
belongs_to :treatment
end
class Treatment < ActiveRecord::Base
attr_accessible :name
has_many :user_treatments
has_many :users, :through => :user_treatments
end
So I can do things like this to get the first instance cost for user id 14
1.9.3p429 :181 > User.find(14).user_treatments.first.instance_cost
=> 100
and this to get the name of the treatment
1.9.3p429 :181 > User.find(14).user_treatments.first.treatment.name
=> "Sports Massage"
However I have a problem representing them in a form using simple_form_for
<% simple_form_for #user do |f| %>
# This sucessfully gives us the checkboxes of all treatments and stores them in the UserTreatments table
<%= f.collection_check_boxes(:treatment_ids, Treatment.all, :id, :name) %>
<%= f.fields_for :user_treatments do |pt| %>
<tr>
<td>
<!-- I WANT THE NAME OF THE TREATMENT HERE -->
</td>
<td><span>£</span> <%= pt.input :instance_cost, :as => :string, wrapper: false, label: false %></td>
</tr>
<% end %>
end
There are two things I need to do.
Show the name of the treatment (how do I do express User.user_treatments.treatment.name with simple_form ?)
Set the instance_cost correctly. Its currently not getting set at all.
When you do fields_for for a nested association then you need to add the following in your User model:
accepts_nested_attributes_for :user_treatments
Otherwise, it will not save the information.
And to access the name of the treatment, you could go through the object method of the form creator object, like this:
<%= f.fields_for :user_treatments do |pt| %>
<tr>
<td><%= pt.object.treatment.name %></td>
...
</tr>
<% end %>
I am new to the Rails framework and tried very long to fix this problem...
I want to display the team name a certain user belongs to, which works for the show action (user details), but not for the index action (all users)
I've created tables:
teams users
----------- ---------------
id (integer) id(integer)
name (string) fname(string)
lname(string)
team_id(integer)
I have the following classes:
class Team < ActiveRecord::Base class User < ActiveRecord::Base
attr_accessible :name, :user_id attr_accessible :fname, :lname, :team_id
has_many :users belongs_to :team
Then I have the following User controller:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def index
#users = User.paginate(page: params[:page], per_page: 15)
end
..and the code to display the user's team name is
Team: <%= #user.team[:name] %>
... which works perfectly fine... however, when I try to use the same code in the index view, like this, I get an error "undefined method `team' for nil:NilClass".
<table class="table table-striped">
<% #users.each do |user| %>
<tr>
<td>
<%= "#{user.fname} #{user.lname}" %>
</td>
<td>
Team: <%= #user.team[:name] %>
</td>
</tr>
<% end %>
</table>
What did I do wrong? Thanks for your help, I'd really appreciate it!
You're inside a block.
Instead of doing
Team: <%= #user.team[:name]
You should write
Team <%= user.team[:name]
Easy bug to overlook :)
My goal is to display select box for each relation for users and specific project.
All users need to be listed but only project users have some type of relation. Other users have none selected in theirs select box.
I have this model:
class Project < ActiveRecord::Base
belongs_to :company
has_many :tasks, :order => 'state_type_id ASC'
has_many :project_user_relations
has_many :users, :through => :project_user_relations
def t_name
name.camelcase
end
end
class User < ActiveRecord::Base
belongs_to :company
has_many :tasks , :foreign_key => :assigned_user_id
has_many :project_user_relations
has_many :projects, :through => :project_user_relations
def full_name
firstname + ' ' + lastname
end
def relation_to(project)
relation=ProjectUserRelation.find_by_project_id_and_user_id(project.id, id)
relation ||= relation=ProjectUserRelation.new
end
end
class ProjectUserRelation < ActiveRecord::Base
belongs_to :project
belongs_to :user
has_one :project_user_relation_type
end
class ProjectUserRelationType < ActiveRecord::Base
def t_name
I18n.t("app.projects.users.relation.type."+code)
end
end
I want make a form to display all users, with collection_select.
I used code:
def edit_all
#project = Project.find(params[:project_id])
#users = User.all
....
in my controler
routes works ok.
in my view:
<% #users.each do |user| %>
<%= f.fields_for :users, user do |user_fields| %>
<tr class="reference" rel="<%= parent_user_path(user) %>" >
<td class="name"><%= link_to user.full_name, parent_user_path(user) %></td>
<td class="email"><%= mail_to user.email %></td>
<td class="type">
<%= user_fields.fields_for user.relation_to #project do |relation_fields| %>
<%= relation_fields.collection_select :project_user_relation_type, ProjectUserRelationType.all, :id, :t_name, {:include_blank => false, :prompt => t("helpers.select.prompt") } %>
<% end %>
</td>
</tr>
<% end %>
<% end %>
or for test:
<%= f.fields_for :users, #users do |xuser_fields| %>
<% logger.debug "#{self.to_s} xuser_fields = #{xuser_fields.object.inspect} ;" %>
<tr>
<td><%= xuser_fields.text_field :firstname %></td>
<td></td>
<td></td>
<td></td>
</tr>
<% end %>
but notnihng woks right
first one generates wrong name in html:
select id="project_users_project_user_relation_project_user_relation_type" name="project[users][project_user_relation][project_user_relation_type]"
second one generates error:
undefined method `firstname' for # Array:0x4d03658
Can you help me to solve this situation.
PS:sorry for long code :(
SOLUTION (probably - solved by reading RoR sources)
I found sollution i thing.
A method
def name_attributes=(attributes)
# Process the attributes hash
end
in Project model was missing.
It is unbelievable sollution :].
There is also exact syntax after fields_for: :name, #some_collection, where name must be exactly same name as in the beginign of mentioned def in Model.