Can't link to correct route using link_to - ruby-on-rails

I am trying to link to the existing route /clients/:client_id/invoices/:id
from my /clients/:client_id show page and cant work out how to do so.
I have a has_many through: relationship and here are my models
class Client < ActiveRecord::Base
has_many :invoices
has_many :items, through: :invoices
class Invoice < ActiveRecord::Base
belongs_to :user
belongs_to :client
has_many :items, :dependent => :destroy
accepts_nested_attributes_for :items, :reject_if => :all_blank, :allow_destroy => true
class Item < ActiveRecord::Base
belongs_to :invoice
belongs_to :client
My routes
resources :clients do
resources :invoices
end
resources :invoices
my client controllers show action
def show
#client = Client.find(params[:id])
#invoices = #client.invoices.build
end
And my clients show.html.erb
<div class="panel-body">
<table class="table table-hover">
<thead>
<tr>
<th>Sender</th>
<th>Reciever</th>
<th>Amount</th>
<th>Currency</th>
<th>Date</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #client.invoices.each do |invoice| %>
<tr>
<td><%= invoice.sender %></td>
<td><%= invoice.reciever %></td>
<td><%= invoice.amount %></td>
<td><%= invoice.currency %></td>
<td><%= invoice.date %></td>
<td><%= link_to 'Show', invoices_path(#clients, #invoice) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
everytime I click the link_to show it routes me to /invoices
I have tried a bunch of different link_to formats but I haven't been able to figure it out.

You are using wrong url_helper with wrong parameters. You should have:
<td><%= link_to 'Show', client_invoice_path(#client, invoice) %></td>
or
<td><%= link_to 'Show', invoice_path(invoice) %></td>
invoices_path is an url_helper generated by resources :invoices (the most outside one) and will route you to the index path for your InvoicesController (/invoices). If you pass an argument, it will be used for the format (/invoices.10 - quite common issue).
All the routes generated by nested resources have a name consisting of both resources, like new_user_profile_path or client_invoice_type_path (triple nested).
Note that your current route structure (same resources with two different paths) might make your controller logic more complex. It is usually sufficient to have a single route, pick one.

Related

Rails association loop display same primary key in row

I have a loop using associations. I'm looking to group by treatment and display in a row.
Each loop has three records for each treatment. The code below this is what i'm producing.
VIEW
<table>
<tr>
<td>Treatment</td>
<td>Date</td>
<td>Count</td>
</tr>
<% #trial.establishmentMethods.order(:treatment_selection_id).each do |data| %>
<tr>
<td><%= data.treatmentSelection.treatment.name %></td> This is reference by treatment_selection_id.
<td><%= data.date %></td>
<td><%= data.count %></td>
</tr>
<% end %>
</table>
This is what i'm hoping to produce. Display the treatment once, then loop the related treatment_selection_id's on the same row.
Here are my models and associations.
class Trial < ApplicationRecord
has_many :assessments, primary_key: 'trial_id'
has_many :establishmentMethods, through: :assessments
end
class EstablishmentMethod < ApplicationRecord
belongs_to :treatmentSelection, primary_key: 'treatment_selection_id', foreign_key: 'treatment_selection_id'
has_many :treatments, through: :treatmentSelection
end
class TreatmentSelection < ApplicationRecord
belongs_to :treatment, primary_key: 'treatment_id'
end
It seems like TreatmentSelection has_many establishmentMethods, so you should add that to the TreatmentSelection model. Then you can do something like:
<% treatment_selections.each do |treatment_selection| %>
<tr>
<td><%= treatment_selection.treatment.name %></td>
<% treatment_selection.establishmentMethods.each do |em| %>
<td><%= em.date %></td>
<td><%= em.count %></td>
<% end %>
</tr>
<% end %>
By the way, it's convention to use snake_case in ruby and it will make using associations easier.

One-to-one association

I have two models and I want to display them in one table.
Model 1:
class Name < ActiveRecord::Base
has_one :employer, :foreign_key => 'application_id'
end
Model 2:
class Employer < ActiveRecord::Base
belongs_to :name, :foreign_key => 'application_id'
end
Controller:
def summary
#name = Name.all
end
I have this in my view:
<% #name.each do |e| %>
<tr>
<td ><%= e.application_id %></td>
<td ><%= e.Name_of_employee%></td>
<td ><%= e.Employer_name%></td>
</tr>
<% end %>
The name only have one employer.
I am getting "undefined method `Employer' for #
"
TYIA!
as the association is defined,
has_one :employer, :foreign_key => 'application-id'
notice the case employer, so it has to be small case, and not class name
<td ><%= e.employer.name %></td> # name or some other attribute you wish to display
Also, including the association first will help eliminate n+1
#name = Name.includes(:employer)

Implement order pages with rails

I wanna implement a order page, but it's so hard...
The system is in portugues, for others reasons, sorry about this.
My view:
conta/pedidos/index.html.erb
<h3>Meus pedidos</h3>
<table>
<thead>
<th>#</th>
<th>Data do pedido</th>
</thead>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to pedido.id, pedido_path(pedido.token) %></td>
<td><%= pedido.create_at.to_s(:long) %></td>
</tr>
<% end %>
</tbody>
</table>
My controller:
conta/pedidos_controller.rb
class Conta::PedidosController < ApplicationController
before_action :authenticate_usuario!
def index
#pedidos = current_usuario.pedidos.order("id DESC")
end
end
My model:
pedido.rb
class Pedido < ActiveRecord::Base
belongs_to :pessoa
has_many :itens, class_name: "ItemPedido" , dependent: :destroy
accepts_nested_attributes_for :enderecos
before_create :gerar_token
def gerar_token
self.token = SecureRandom.uuid
end
end
And the error:
ArgumentError in Conta::PedidosController#index
No association found for name `enderecos'. Has it been defined yet?
Please, what I make?
I'm not sure why do you have accepts_nested_attributes_for :enderecos in pedido.rb. It's not mentioned anywhere in the provided code. Can you simple comment/remove it?
If it's need, then you need to set association for it: may be has_many :enderecos

Getting uncategorized objects in has_many :through

Good day all,
Pardon me for my noob-ness in rails.
So here's my question.
So I've a category model and a itinerary model defined below
class Category < ActiveRecord::Base
has_many :categorizations, :dependent => :destroy
has_many :itineraries, :through => :categorizations
end
class Itinerary < ActiveRecord::Base
has_many :categorizations
has_many :categories, :through => :categorizations
end
So in my view, I am looping through categories to display itineraries in groups.
<% #categories.each do |category| %>
<table>
<thead>
<tr>
<th colspan="4"><%= category.name %></th>
</tr>
</thead>
<tbody>
<% category.itineraries.each do |itinerary| %>
<tr>
<td><%= itinerary.name %></td>
<td><%= link_to 'Show', itinerary %></td>
<td><%= link_to 'Edit', edit_itinerary_path(itinerary) %></td>
<td><%= link_to 'Destroy', itinerary, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
So I am wondering, how do we display itineraries that are not categorised yet?
I've searched around and found out that using scopes in the model will be the way to go.
scope :without_categories, -> { includes(:categorizations).where( :categorizations => { :itinerary_id => nil } )}
I find it not very "DRY" due to the fact that I've to write another table to iterate through itinerary.without_categories again.
Is there a way where we're able to code it in such a way where categories.all shows everything with uncategorized items in it?
Thank you.
Update #1
Decided to use this in my controller, which builds a new "Uncategorized" category on index action and it'll add to the array.
def index
uncategorized = Category.new
uncategorized.name = "Uncategorized";
uncategorized.itineraries = Itinerary.without_categories
#categories = Category.all << uncategorized
end
I know that in rails, controllers should be as skinny as possible.
But I can't think of a better way.
Anyone with a better answer, please feel free to share. Thanks! :)
You just have to find the itineraries that dont have a reference inside the Categorizations table. You can do a nested query for this.
SELECT * FROM itineraries where id NOT IN ( SELECT itinerary_id FROM categorizations')
just do a method in your Itinerary model like this:
def self.uncategorized
Itinerary.find_by_sql('SELECT * FROM itineraries where id NOT IN ( SELECT itinerary_id FROM categorizations)')
end

Need data from a many:many join in a Rails view

Its maybe not the best solution in most cases, but i want a table with data form 3 tables.
class Media < ActiveRecord::Base
belongs_to :user
belongs_to :type
has_many :ratings
end
class User < ActiveRecord::Base
has_many :medias
has_many :ratings
end
class Rating < ActiveRecord::Base
belongs_to :user
belongs_to :media
end
Thats the view I want
<table>
<tr>
<th>Name</th>
<th>Comment</th>
<th>Creator</th>
<th>Type</th>
<% for user in #users %>
<th><%=h user.login %></th>
<% end %>
</tr>
<% for media in #medias %>
<tr>
<td><%=h media.name %></td>
<td><%=h media.comment %></td>
<td><%=h media.user.login %></td>
<td><%=h media.type.name %></td>
<% for user in #users %>
<td><%=h GET_RATING (media, user) %></td>
<% end %>%>
</tr>
<% end %>
</table>
Basicly i want one new row for each users ratings for each media
What I want is a Table that looks like that:
media.name media.comment ... rating(media, user).rating
I think it would be better to use a join in the Controller with the Media find methods but I dont know how exactly, enougher possible solution could be helper method that takes media and user as parameters.
What do you think is the best solution for this?
This kind of association belongs in your model, a has many through relationship is perfect for this.
class User < ActiveRecord::Base
has_many :ratings
has_many :media, :through => :ratings
end
class Media < ActiveRecord::Base
has_many :ratings
has_many :users, :through => ratings
end
class Rating < ActiveRecord::Base
belongs_to :user
belongs_to :media
end
Then you can access
media.name media.comment
Then could also access
user.ratings
or:
<% media.users.each do |user| %>
## Do stuff with user.ratings array
<% end %>
You can also:
media.ratings.each do |rating|
rating.your_attribute
rating.user.your_attribute
end

Resources