Implement order pages with rails - ruby-on-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

Related

Ruby on rails NoMethodError active record

I have these models
class Auto < ApplicationRecord
belongs_to :marca
belongs_to :modelo
belongs_to :cliente
end
class Cliente < ApplicationRecord
has_many :autos
end
class Marca < ApplicationRecord
has_many :modelos
has_many :autos
end
class Modelo < ApplicationRecord
belongs_to :marca
has_many :autos
end
and this index view
<table class="table table-striped" id="autos">
<tr>
<th>Id</th>
<th>Cliente</th>
<th>Marca</th>
<th>Modelo</th>
<th>Placas</th>
</tr>
<% #auto.each do |auto| %>
<tr>
<td><%= auto.id %></td>
<td><%= auto.cliente.nombre %></td>
<td><%= auto.marca.nombre%></td>
<td><%= auto.modelo.nombre %></td>
<td><%= auto.placas %></td>
</tr>
<% end %>
</table>
and this in my autos controller
def show
#auto = Auto.find(params[:id])
end
def index
#auto = Auto.all
end
the problem is that show me this error:
undefined method `nombre' for nil:NilClass in this line:
<td><%= auto.cliente.nombre %></td>
rarely at show view where I call
#auto.cliente.nombre
works fine, can you help me? thanks
It seems like <td><%= auto.cliente.nombre %></td> doesn't work because auto.cliente is nil, and you cannot call that method nombre on nil. Perhaps one of your auto objects doesn't have an associated client?
To see how this happens, try running nil.hello in Ruby and you should see a NoMethodError with the error message undefined method 'hello' for nil:NilClass.
auto.cliente.try(:nombre) will save you from error if you by chance allow auto without cliente.

undefined method operators on legal Postgresql database

I'm beginner, so sorry if i ask for something trivial.
Two tables imed_patient and imed_operator are legal Postgresql tables with relation between them (many patients to one operator by r_opr_code field in imed_patient), described by definitions:
class ImedOperator < ActiveRecord::Base
self.table_name = "imed_operator"
self.primary_key = "code"
belongs_to :ImedPatient
end
class ImedPatient < ActiveRecord::Base
self.table_name = "imed_patient"
self.primary_key = "code"
has_one :ImedOperator, :foreign_key => "r_opr_code"
end
I want to view all patients with data (ex. name, surname) from imed_operator (details of patients), so I produced pacjenci_controller.rb
class PacjenciController < ApplicationController
def index
#patients = ImedPatient.all
#operator = #patients.operators
end
def show
#patient = ImedPatient.find(params[:id])
end
end
In web broweser I receive error :
NoMethodError in PacjenciController#index
undefined method `operators' for #<ImedPatient::ActiveRecord_Relation:0x007fbb269ffe00>
Extracted source (around line #5): #operator = #patient.operators
UPDATE:
my index.html.erb
<h1>Pacjenci w Optimed</h1>
<table>
<tr>
<th>Nazwisko</th>
<th>ImiÄ™</th>
<th>Pesel</th>
<th>Code_operator</th>
<th>Wizyty</th>
<th></th>
<th></th>
</tr>
<% #patients.each do |patient| %>
<tr>
<td><%= link_to #operator.surname, controller: "pacjenci", action: "show", id: patient.r_opr_code %></td>
<td><%= #operator.first_name %></td>
<td><%= #operator.pesel %></td>
<td><%= patient.r_opr_code %></td>
<td><%= link_to 'Wizyty', url_for(action: 'wizytypacjenta', controller: 'wizyty', id: patient.code) %></td>
</tr>
<% end %>
</table>
<br>
<p><%= link_to 'Start', url_for(action: 'index', controller: 'pacjenci') %></p>
<p><%= link_to 'Wstecz', url_for(:back) %></p>
And I stucked :(
ImedPatient has_one ImedOperator, so you need to change
#operator = #patient.operators
to
#operator = #patient.imed_operator
However, I'm not sure you are doing what you want to do. In the index action you are calling ImedPatient.all, so you will get all the records. That's why the variable should be called #patients, not #patient. Then, if you want to get all operators for all the patients, you should use
#operator = #patients.map(&:imed_operator)
If you made a mistake and you actually wanted the #operator in show action it should be:
#operator = #patient.imed_operator
Update: another problem is the has_one declaration. I think it should be:
has_one :imed_operator, :foreign_key => "r_opr_code"
Update 2:
After what you have written in comments it seems that you have confused the association and it should be the other way:
class ImedOperator < ActiveRecord::Base
has_one :imed_patient, foreign_key: 'r_opr_code'
end
class ImedPatient < ActiveRecord::Base
belongs_to :imed_operator , foreign_key: 'r_opr_code'
end
Have a look at: http://guides.rubyonrails.org/association_basics.html#choosing-between-belongs-to-and-has-one

Can't link to correct route using link_to

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.

Calling a single method from a Rails controller

I am creating a trivia game where there are multiple categories (like sports, history, art, etc.). At the end of each category's game, I want to show a scoreboard of results only for that single category.
By specifying the category in the method, I am now successfully filtering only for history scores, as seen here:
class ScoreboardController < ApplicationController
def index
#participations = Participation.where(finished: true, category: "history").order(score: :desc)
end
end
While that is good, I now need to make it so that the scoreboard controller can produce a filtered set of scores for history, sports, and any other number of category iterations, whereas it only covers the history category at current.
To make this happen, I tried creating a second method within the controller for:
#participations = Participation.where(finished: true, category: "sports").order(score: :desk)
Unfortunately, that still only returned scores from the first method for history with no sports scores.
I think I am doing one of two things wrong:
1) Am I writing the methods incorrectly by adding additional iterations into the same controller?
2) In the scoreboard view (as opposed to the scoreboard controller), I am not calling the controller correctly.
Any ideas where I am going wrong?
Additional Info: Scoreboard View
<thead>
<tr>
<th>#</th>
<th>User</th>
<th>Category</th>
<th>Score</th>
</tr>
</thead>
<tbody>
<% #participations.each_with_index do |participation, index| %>
<tr>
<td>#<%= index + 1 %></td>
<td><%= participation.user.username %></td>
<td><%= participation.category %></td>
<td><%= participation.score %></td>
</tr>
<% end %>
</tbody>
You should change your ScoreboardController index to contain different instance variables for different categories. ie:
ScoreboardController.rb
def index
#participations_score = Participation.where(finished: true, category: "history").order(score: :desc)
#participations_history = Participation.where(finished: true, category: "sports").order(score: :desc)
# other particpation categories
end
index.html.erb
<h1>History Scoreboard</h1>
<thead>
<tr>
<th>#</th>
<th>User</th>
<th>Category</th>
<th>Score</th>
</tr>
</thead>
<tbody>
<% #participations_history.each do |participation_history| %>
<tr>
<td>#<%= participation_history.id %></td>
<td><%= participation_history.username %></td>
<td><%= participation_history.category %></td>
<td><%= participation_history.score %></td>
</tr>
<% end %>
</tbody>
<!--- Add more code for the rest of the categories --->
I strongly suggest that you brush up on your knowledge of the Ruby programming language as well as the Ruby on Rails framework. You can do so by going to Code academy.
Sounds like a job for nested resources, with a singular resource for:
#config/routes.rb
resources :categories do
resource :scoreboard, module: :categories #-> url.com/categories/:category_id/scoreboard
end
#app/controllers/categories/scoreboards_controller.rb
class Categories::ScoreboardsController < ApplicationController
def show
#results = Participation.where(finished: true, category: params[;category_id]).order(score: :desc)
end
end
This will allow you to invoke the scoreboards#show action, populating with the appropriate category from the routes....
#app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def create
#category = ...
redirect_to [#category, :scoreboard]
end
end
Associations
Now, there's a better way.
Instead of calling Participation naked, you'll be best using the categories and scoreboards association you should have set up in the backend:
#app/models/category.rb
class Category < ActiveRecord::Base
has_many :participations
has_many :scoreboards, through: :participations
end
#app/models/participation.rb
class Participation < ActiveRecord::Base
belongs_to :category
belongs_to :scoreboard
end
#app/models/scoreboard.rb
class Category < ActiveRecord::Base
has_many :participations
has_many :categories, through: :participations
end
This will allow you to use the same routes as above, but this time populating the response through the associations:
#app/controllers/categories/scoreboards_controller.rb
class Categories::ScoreboardsController < ApplicationController
def show
#category = Category.find params[:id]
#results = #category.participations.where(participation: {attribute: true})
end
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