Rails - error while showing field from class - ruby-on-rails

i want to bring all the resources and then show the 'nombre' field that is from 'curso'. One curso has many resources.( I have all the has_many and belongs_to well configured.)
For that i do the following:
resources_controller:
def index
#resources = Resource.all
end
index.html:
<% #resources.each do |resource| %>
<tr>
<td><%= resource.title %></td>
**<td><%= resource.curso.nombre %></td>**
<td><%= resource.cantidad %></td>
<td><%= link_to 'Show ', resource %></td>
<% else %>
<% end %>
but when i test it, it gives me the following error: "undefined method `nombre' for nil:NilClass"
do you know what can it be?
thanks!

It means that this particular resource is not associated with any of your curso.
If you want to mandate that each resource should be associated with any of your curso while it's creation, you should have this in your Resource model:
class Resource < ActiveRecord::Base
belongs_to :curso
# Validate the presence of curso in every resource.
validates :curso, presence: true
end
class Curso < ActiveRecord::Base
# When any curso is destroyed, all it's associated resources should be gone.
has_many :resources, dependent: :destroy
end
Only in above case, you can ensure that resource always have a curso during it's creation.
Additionally, you can have DB level not null constraint on curso_id field of resources table.

Seems like some resources dont have acurso`.
Just check if the curso exists before calling nombre on it:
<%= resource.curso.nombre if resource.curso %>
or
<%= resource.curso && resource.curso.nombre %>
or
<%= resource.curso.try(:nombre) %>

Related

get attributes from html to controller rails

i have this .html
<% #resources.each do |resource| %>
<tr>
<!-- -1 es para mostrar todos los recursos que faltan % -->
<% if (resource.curso_id = params[:id] or params[:id] ="-1") and resource.cantidad>0 %>
<td><%= resource.title %></td>
<td><%= #curso.nombre %></td>
<td><%= #user.name %></td>
<!-- %= image_tag(resource.imagen_url, :width => 190, :height => 190) if resource.imagen.present? % -->
<td><%= resource.cantidad %></td>
<td><%= link_to 'Show ', resource %></td>
and this controller:
def index
if params[:id] != "-1"
#resources = Resource.where(:curso_id => params[:id])
#curso = Curso.find(params[:id])
#user = User.find(#curso.user_id)
else
#resources = Resource.all
# HERE IS THE ERROR. I WANT TO GET THE COURSE BUT I WANT THE FIELD CURSO_ID THAT IS IN RESOURCE TABLE
#cursos = Cursos.find(#resource.curso_id)
#user = User.find(#curso.user_id)
end
end
the part that is above the if works ok. but the part below doesnt work. i want to get an attribute from resource in html and use in my controller. how could it be possible? thank you!
It seems like your model associations are not set up.
class Resource < ActiveRecord::Base
belongs_to :curso
end
class Curso < ActiveRecord::Base
has_many :resources
belongs_to :user
end
class User < ActiveRecord::Base
has_many :cursos
end
After that, you can simply access them in view template:
<% #resources.each do |resource| %>
<% resource.curso %>
<% resource.curso.user %>
<% end %>
Lastly, I'd like to add that using localized names for your model attributes is a real bad practice.
#resource is not defined. You have defined #resources = Resource.all(notice the s).
Plus Resource.all returns an array or objects of type Resource. Please explain what you're trying to achieve.

How do I get the table column data from one model into the view of another?

I want the customer name to appear in the customer name column on one of my model view pages, but I can't seem to figure out how to do this.
Here are my associations:
Customer Model is -
class Customer < ActiveRecord::Base
has_many :appointments, :dependent => :destroy, :as => :customer
has_many :birds, :dependent => :destroy, :as => :customer
end
Bird Model is -
class Bird < ActiveRecord::Base
belongs_to :customer
has_one :appointment
end
I've also added this to the Bird model index view -
<tbody>
<% #birds.each do |bird| %>
<tr data-link="<%= bird_path(bird) %>">
<td><%= bird.customer_id %></td>
<td><%= bird.name %></td>
<td><%= bird.breed %></td>
<td><%= bird.color %></td>
<td><%= bird.age %></td>
</tr>
<% end %>
The customer parameter I'd like to pass into the customer name column on the birds index view page is customer.name, or :name. If I try that, I get an undefined methods error on my /birds page.
Thanks!
I would expect that this should work:
<%= bird.customer.name %>
Or - if you have birds without an customer - you might want avoid exceptions like this:
<%= bird.customer.try(:name) %>
Or - less error prone - add the following to your bird model:
delegate :name, to: :customer, allow_nil: true, prefix: true
And use it in your views like this:
<%= bird.customer_name %>
You need to use in your view like this :
<%= bird.customer.name %>
In your controller, for the bird index page:
when you query for Bird.all, do Bird.all.includes(:customer)
then you will have access to <%= bird.customer.name %> in the view

Ruby - ActiveRecord belongs_to and nil association

Imagine the following situation:
I have a user model and a user_group model, so:
Class User < ActiveRecord::Base
belongs_to :user_group
end
Class UserGroup < ActiveRecord::Base
has_many :users
end
Now, let say some of the user does not have group. Which mean, when I call:
<% #u.each do |item| %>
<tr>
<td><%= item.id %></td>
<td><%= item.username %></td>
<td><%= item.name %></td>
<td><%= item.user_group.name %></td>
</tr>
<% end %>
It will throw nil. Is there any way nil will be displayed as empty string (somewhat like LEFT JOIN, or DataMapper include_related in CodeIgniter) instead of showing error page?
Right now I am using
<%= item.user_group.name unless item.user_group.nil? %>
to check before calling, but doing that for all view file is somewhat not a good approach.
Thanks in advance!
use try..
class Manufacturer < ActiveRecord::Base
has_many :products
def contact
"Manufacturer has been contacted."
end
end
Product.first.try(:manufacturer).try(:contact)
#=> nil
Product.last.try(:manufacturer).try(:contact)
#=> "Manufacturer has been contacted."
You can use an helper too:
def group_name_for(item)
item.user_group.name unless item.user_group.nil?
end
And call that helper in your views:
<%= group_name_for(item) %>

Checking whether a user owns incoming and outgoing service booking requests

Use case: A user creates a service and can have many services. A user can book the service of another user through a servicebooking. A user can accept/decline the booking for their service from another user.
I am trying to display the outgoing service bookings made by the current user for another users services by checking a servicebookings model and also check/display the incoming bookings made by other users for the current users services on a myservicebookings page.
Myservicebookings view is as follows:
<h1>My Service bookings</h1>
<% if #owns_s %>
<table>
<tr>
<th><%= sortable "date" %></th>
<th><%= sortable "time" %></th>
<th><%= sortable "service name" %></th>
</tr>
<h4>Incoming requests:</h4>
<% #servicebookings.each do |servicebooking| %>
<tr>
<td><%= servicebooking.date %></td>
<td><%= servicebooking.time %></td>
<td><%= servicebooking.service_name %></td>
<td><%= link_to "View this booking", servicebooking_path(servicebooking) %></td>
</tr>
<% end %>
</table>
<%else%>
<%= "You have no incoming service booking requests"%>
<%end%>
<% if #owns_sb %>
<table>
<tr>
<th><%= sortable "date" %></th>
<th><%= sortable "time" %></th>
<th><%= sortable "service name" %></th>
</tr>
<h4>Outgoing requests:</h4>
<% #servicebookings.each do |servicebooking| %>
<tr>
<td><%= servicebooking.date %></td>
<td><%= servicebooking.time %></td>
<td><%= servicebooking.service_name %></td>
<td><%= link_to "View this booking", servicebooking_path(servicebooking) %></td>
</tr>
<% end %>
</table>
<%else%>
<%= "You have made no outgoing service booking requests"%>
<%end%>
<%= will_paginate #servicebookings %>
<%= link_to "Homepage", :controller => "welcome", :action => "index" %>
In my servicebookings controller I have the following to check whether a user owns a service or a servicebooking, currently it just returns all the services and servicebookings instead of displaying only the services created by the current user that another user has booking(incoming requests) and instead of displaying the services booked by the current user(outgoing requests). Can anyone give some tips here?? Thanks in advance guys, much appreciated.
def myservicebookings
#servicebookings = current_user.servicebookings.includes(:user).search(params[:search]).order(sort_column + " " + sort_direction).paginate(:per_page => 4, :page => params[:page])
owns_servicebooking = current_user.servicebookings.detect do |sb|
sb.user == current_user
end
owns_service = current_user.services.detect do |s|
s.user == current_user
end
#owns_sb = owns_servicebooking
#owns_s = owns_service
end
Servicebooking model:
class Servicebooking < ActiveRecord::Base
attr_accessible :service_id, :date, :time, :user_id, :service_name, :accept_booking
belongs_to :user
belongs_to :service
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
end
Services model:
class Service < ActiveRecord::Base
attr_accessible :avatar, :avatar2, :avatar3, :avatar4, :name, :date_available, :time_available, :description, :price, :size, :company_name, :company_details
has_attached_file :avatar, :default_url => "/images/:style/missing.png"
has_attached_file :avatar2, :default_url => "/images/:style/missing.png"
has_attached_file :avatar3, :default_url => "/images/:style/missing.png"
has_attached_file :avatar4, :default_url => "/images/:style/missing.png"
belongs_to :user
belongs_to :event
has_many :comments, dependent: :destroy
has_many :servicebookings
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
end
has_many :through
I think you'll benefit from the has_many :through association
Your ServiceBooking model seems to be a join model, which needs to reference booking_id and service_id
The way you've got the system set up currently is to pull directly from this model. I think you'll be better to use it in conjunction with your other models. You'll literally just have to adapt your code slightly to affect this change:
#app/models/Service.rb
Class Service < ActiveRecord::Base
belongs_to :user
has_many :service_bookings
has_many :bookings, :through => :service_bookings
end
#app/models/Booking.rb
Class Booking < ActiveRecord::Base
belongs_to :user
has_many :service_bookings
has_many :services, :through => :service_bookings
end
#app/models/ServiceBooking.rb
Class Service < ActiveRecord::Base
belongs_to :service
belongs_to :booking
end
This will allow you to pull the actual data from the relative models, rather than just relying on the ServiceBooking model
The beauty of this is that because you can add extra attributes to join models in Rails, you'll be able to include other fields, such as user_id, inbound and outbound
Your Code
I'd do it like this:
#config/routes.rb
resources :users do
resources :bookings
resources :services
end
#app/controllers/users_controller.rb
def index
user = User.find(params[:id])
#bookings = user.bookings
#services = user.services
end
#app/controllers/bookings_controller.rb
def index
user = User.find(params[:user_id])
#bookings = user.bookings
end
#app/controllers/services_controller.rb
def index
user = User.find(params[:user_id])
#services = user.services
end
This will allow you to display the actual bookings / services for each user (all the services / bookings on the user index page; all relative records on bookings and services index actions)
Validation
If you follow these ideas, validation becomes somewhat more methodical
You can either use a before_create function on your ServiceBooking model (to check if the object matches the user_id), or you could perform some controller-based validation to see if the user_id is consistent
I should also mention that checking ownership of booking or service moves to the other models with this (I.E service belongs_to :user)

Rails table joins

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 %>

Resources