Get object of relation n:m in Ruby on Rails - ruby-on-rails

I have two models:
Perfiles
Modulos
And the relationship between them is: Many to Many, there is a table to map relation: modulos_perfiles
I need get all "modulos" that belongs to "perfil".. I have this:
<% #perfiles.each do |perfil| %>
<% #m = perfil.modulo.last %>
<%= #m.ruta %><br/>
<% end %>
but I get this error:
undefined method "ruta" for nil:NilClass
Where "ruta" is a column of "modulo" table.
I made this:
<% #perfiles.each do |perfil| %>
<% #m = perfil.modulo.last %>
<%= debug #m %><br/>
<% end %>
And I can see all attributes of #m object so:
ruby/object:Modulo
attributes:
id: 7
descripcion: Busquedas
ruta: /busquedas
created_at: 2012-11-25 02:23:51.984916000 Z
updated_at: 2012-11-25 02:23:51.984916000 Z
But I don't understand why I cannot get this attributes with:
<%= #m.ruta %>
Any idea?, thanks!
UPDATE
My model classes are:
class Perfil < ActiveRecord::Base
has_many :usuario
has_and_belongs_to_many :modulo
end
class Modulo < ActiveRecord::Base
has_and_belongs_to_many :perfiles
end
class ModulosPerfiles < ActiveRecord::Base
end
**
ANSWER
**
I don't have enough reputation to publish answer.
I've resolved:
I made this:
<% #perfiles.each do |perfil| %>
<% perfil.modulo.each do |modulo| %>
<%= modulo.ruta %><br/>
<% end %>
<% end %>
And so I can get any attribute of object "modulo".
Thanks.

<% #perfiles.each do |perfil| %>
<% perfil.modulo.each do |modulo| %>
<%= modulo.ruta %><br/>
<% end %>
<% end %>

Related

Error with instance variable in Index view

So in my tutors_controller.rb this is my index action
def index
#tutor = Tutor.all
#tutor = #tutor.fees_search(params[:fees_search]) if params[:fees_search].present?
end
and in my index.html.erb this is the view
<div class='container'>
<%= form_tag(tutors_path, method: :get) do %>
<%= label_tag 'fees_search', 'Max Fees' %>
<%= select_tag 'fees_search', options_for_select((10..50).step(10)) %>
<%= submit_tag 'Filter' %>
<% end %>
<% #tutor.each do |tutor| %>
<% unless tutor.admin? %>
<div class='row' id='tutor-listing'>
<div class='col-xs-4'>
<%= image_tag(tutor.profile.avatar.url, :class => "img-rounded" ) if tutor.profile.avatar? %>
</div>
<div class='col-xs-8'>
<h3><%= link_to tutor.full_name, tutor_path(tutor) %></h3>
<% unless tutor.subjects.nil? %>
<% tutor.subjects.each do |subs| %>
<span class='badge'id='tutor-listing-badge'>
<%= link_to subs.name, subject_path(subs) %>
</span>
<% end %>
<% end %>
<% unless current_tutor %>
<%= button_to "Shortlist Tutor", add_to_cart_path(tutor.id), :method => :post %>
<% end %>
</div>
</div>
<% end %>
<% end %>
</div>
So i understand that when the index view first renders, #tutor would simply be Tutor.all so it renders each individual tutor perfectly.
After trying to filter it though, i start receiving errors. The exact error is NoMethodError in Tutors#indexand the highlighted line is <% unless tutor.admin? %>
profile.rb model
class Profile < ActiveRecord::Base
belongs_to :tutor
scope :fees_to, -> (fees_to) { where("fees_to <= ?", "#{fees_to}") }
end
tutor.rb model
class Tutor < ActiveRecord::Base
has_one :profile, dependent: :destroy
def self.fees_search(n)
#profile = Profile.fees_to(n)
if #profile.empty?
return Tutor.none
else
#profile.each do |y|
y.tutor
end
end
end
end
I get that now my #tutor instance variable has obviously changed. But how do i go about resolving this problem? Should i be rendering a partial instead? Obviously my index action in my controller could be "better" also but i'm quite confused now as to what i should be doing.
Would appreciate any advice! Thank you!
#profile.each do |y|
y.tutor
end
Seems to be a problem. All the other outcomes are a Tutor.something scope, whereas this will return the last tutor only. Change each to map to get an array of Tutors instead.

Using associations in Ruby on Rails

I'm learning RoR and I'm trying to understand associations. I've got two models - Company [name] and Note [company_id, notes]. As shown, the Note model has a company_id field to reference the primary key in the Company model.
Within a Notes view, I'm trying to display the Company name but I can't seem to get this to work.
I want to display
(SELECT name FROM Company WHERE Company.id=Note.company_id)
instead of note.company_id in the code below.
company.rb
class Company < ActiveRecord::Base
has_many :notes
end
note.rb:
class Note < ActiveRecord::Base
belongs_to :company
default_scope -> { order(date: :desc) }
end
notes/index.html.erb
....
<% #notes.each do |note| %>
<% if note.active %>
<p>
<%= note.date %>
</br>
<%= note.company_id %> - <%= note.contact %>
</br>
<%= note.notes %>
<!-- <td><%= note.active %></td> -->
</p>
<% end %>
<% end %>
....
To answer your specific question, try:
note.company.name
I would also recommend reading up on Rails partials, particularly how to render a collection: http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials

Make a loop in a rails scope

Here is my structure:
Villa model with a belong_to association with a destination model (destination_id).
User model with a habtm association with destination model.
Today in my index view, I use :
<% current_user.destinations.each do |destination| %>
<% #villas.each do |villa| %>
<% if destination == villa.destination %>
<%= villa.name %>
<%end%>
<%end%>
<%end%>
It's not very clear, so can I make a kind of scope in my villa model to select Villas where destination_id == current_user.destinations ?
Thanks a lot
Why don't you list the children villas from the destination itself?
<% current_user.destinations.each do |destination| %>
<% destination.villas.each do |villa| %>
<%= villa.name %>
<%end%>
<%end%>
If you want to forgo this built-in functionality, or if you're scoping a query further from your #villas relation, here's how you do the scope as per these docs
class Villa < ActiveRecord::Base
# ...
scope :by_destinations, -> (destinations) { where(destination: destinations) }
# alternatively...
def self.by_destinations(destinations)
where(destination: destinations)
end
end
Then refer to it with
<% #villas.by_destinations(current_user.destinations) do |villa| %>
<%= villa.name %>
<%end%>

ActionView::Template::Error (undefined method `city' for nil:NilClass):

I'm having belongs_to / has_many relationship between Trainer and Sportists. I'm trying to loop through their values in view like this:
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.city %>
<% end %>
and the Sportist related information works fine, but the trainers - doesn't. I get the error given in the title. If I try to do this in rails console everything works, so relationships should be set fine.
Things I've tried:
<% s.trainers.each do |t| %>
<%= t.city %>
<% end %>
that gives me undefined method 'trainers' error, and if I try s.trainer I get
#<TRAINER:0X00000004CE7CB0>
So what could be the fix?
EDIT
My models:
Trainer
has_many :sportists
belongs_to :team
accepts_nested_attributes_for :sportists, :reject_if => :all_blank, :allow_destroy => true
Sportist
belongs_to :trainer
Controller
#sportists = Sportist.all
You are getting undefined method 'city' for nil:NilClass in below code:
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.city %>
<% end %>
which means that there is a sportists record which doesn't have trainer associated to it.
So, for that particular sportlist record s.trainer is nil and you cannot call city on nil object.
To identify the sportist record for which you don't have an associated trainer, just update the view code as below:
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.try(:city) %>
<% end %>
This way even if you don't have an associated trainer record, error would not be raised.
In the rendered view, just look for sportlist record which doesn't show any city, that would be the sportlist record without an associated trainer.
As for the second error undefined method 'trainers' that you received on
<% s.trainers.each do |t| %>
<%= t.city %>
<% end %>
sportlist belongs_to trainer, you only have dynamic method trainer (NOTE singular) available and NOT trainers (NOTE plural). Also, s.trainer would return a single trainer record so you cannot iterate over it with each method as it is not a collection BUT a single record.
UPDATE
Ideally, you should not have allowed creation of sportist records without a trainer.
You should have added an index on the foreign key trainer_id created on sportlists table. With this you don't even have to use try method and your current code would work as it is.
You can make use of delegate and avoid use of try, if and terniary operator.
Sportist
belongs_to :trainer
delegate :city, to: :trainer, :allow_nil => true
You need to make small change to your existing code and it will work smoothly :)
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.city %>
<% end %>
Seems like you have a sportists that doesn't have a trainer. To avoid this make an if condition like this.
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.city if s.trianer.present?%>
<% end %>
And also setting the validation in the Sportist model should resolve the empty trainer_id values
Class Sportist < ActiveRecord::Base
belongs_to :trainer
validates :trainer_id, presence: true
end
You can update your code
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.city %>
<% end %>
with
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.present? ? s.trainer.city : "No City Found" %>
<% end %>
This will stop the code to throw nil errors

rails - displaying nested find hash

I am trying to display the output of this find -
#test = User.joins(:plans => [:categories => [:project => :presentations]]).where(current_user.id)
Here is my output loop
<% #test.each do |p| %>
<%= p.plans %>
<% p.plans.each do |d| %>
<%= debug(d) %>
<% d.categories.each do |e| %>
<% e.project.each do |r| %>
<%= debug(r) %>
<% end %>
<% end %>
<% end %>
<% end %>
The loop works until it gets to project when it throws this error
undefined method `each' for "#<Project:0x000001033d91c8>":Project
If I change it to projects in the loop it gives this error
undefined method `projects' for #<Plan:0x000001033da320>
The debug at categories level shows this
--- !ruby/object:Category
attributes:
id: 2
name: test
short_name: tst
created_at:
updated_at:
category_id: 2
plan_id: 5
My relationships look like this
User
has_many :user_plans
Plan
has_many :user_plans
has_and_belongs_to_many :categories
Category
has_one :project
has_and_belongs_to_many :plans
Project
has_many :presentations, :dependent => :delete_all
Presentation
belongs_to :project
Do I need to changed my find ?
Thanks, Alex
Category has_one :project
so it is single object not collection thus no each method.
According to your relationship definitions, Category only has_one project, so why do you want to iterate over e.project? If you just want to show debugging output, replace
<% e.project.each do |r| %>
<%= debug(r) %>
<% end %>
with
<%= debug(e.project) %>
But if you want to go deeper, into presentations, do:
<%= debug(e.project) %>
<% e.project.presentations.each do |presentation| %>
<%= debug(presentation) %>
<% end %>
Your problem is that you are calling the array method .each on a single object.
category.project will give you a single Project object right? That's not an array, so you can't call each on it.
Replace this:
<% e.project.each do |r| %>
<%= debug(r) %>
<% end %>
with
debug(e.project)
While you're at it, here's some other advice: use descriptive variable names. Why does 'p' represent a test, 'd' represent a plan, 'e' represent a category, etc? Variable names should tell you what the object is. Similarly, i'd expect the variable #test to hold a Test object. In your code it seems to be an array. Use plural variable names for a variable that holds a collection of that type of object - eg #plans would be an array of Plan objects.
eg
<% #tests.each do |test| %>
<% test.plans.each do |plan| %>
<%= debug(plan) %>
<% plan.categories.each do |category| %>
<%= debug(category.project) %>
<% end %>
<% end %>
<% end %>
Isn't that more readable?

Resources