I have problem to link to show file
http://localhost:3000/sigs/3
I got this error
ActiveRecord::RecordNotFound in SigsController#show
Couldn't find Ofertum with 'id'=3
Please help me. Here is my codes
I have two models: One for offers and one for signs
Each offer have signs and each sign have one offer
In sig model
belongs_to :ofertum
in ofertum model
has_many :sigs
in routes
resources :oferta
resources :sigs
in sigs controller
class SigsController < ApplicationController
def new
#ofertum = Ofertum.find(params[:id])
#sig = #ofertum.sigs.build
end
def create
#ofertum = Ofertum.find(params[:id])
#sig = #ofertum.sigs.build(sig_params)
if #sig.save
redirect_to sigs_path(:id => #ofertum.id)
end
end
def destroy
#ofertum = Ofertum.find(params[:id])
#sigs=#ofertum.sigs
if #sigs.destroy
redirect_to root_path
end
end
def show
#ofertum = Ofertum.find(params[:id])
#sigs=#ofertum.sigs
end
def edit
end
def update
end
def index
end
def destroy
end
private
def sig_params
sig_params = params.require(:sig).permit([:name,:comment,:description,:price,:image])
end
end
In oferta index.html.erb
<% #oferta.each do |o| %>
<ul class="cat">
<li class="pull-left"><h2><%= link_to o.offer,o %></h2><br><h4><%= o.description %></h4>
<div class="main">
<% if o.sigs.exists? %>
<div id="myBtnContainer">
<% for item in o.sigs %>
<button class="btn active" onclick="filterSelection('<%= item.name %>')"><%= item.name%><%= link_to item.description,item %><br></button>
<% end %>
</div>
<div class="row">
<% for item in o.sigs %>
<div class="column <%= item.name %>">
<div class="content">
<%= image_tag item.image.url(), style: "width:100%"%>
<h4><br><%= item.name %></h4>
<p><%= item.comment %></p>
</div>
</div>
<% end %><br><br>
</div>
<% end %>
</div>
<% end %>
In the database
class AddNameToSig < ActiveRecord::Migration[5.2]
def change
add_column :sigs, :name, :string
add_column :sigs, :comment, :string
add_column :sigs, :description, :text
add_column :sigs, :price, :string
end
end
in sigs show.html.erb
<%= #sig.name %>
<div class="container">
<%= link_to #sig, class: "btn tf-btn btn-default", method: :delete, data: { confirm: "Are you sure you want to delete this sign?" } do %>Delete <% end %>
</div>
The param in the path /sigs/3 is about a sig, not an ofertum. So you might do this way
def show
sig = Sig.find(params[:id])
#sigs = sig.ofertum.sigs
end
or
def show
ofertum = Sig.find(params[:id]).ofertum
#sigs = ofertum.sigs
end
and yes, if you need even the ofertum in the view
def show
#ofertum = Sig.find(params[:id]).ofertum
#sigs = #ofertum.sigs
end
Related
I am having trouble debugging this error. NoMethodError in Products#Index undefined method 'id' for #ActiveRecord::Relation
Here is my products controller:
class ProductsController < ApplicationController
def index
if params[:query].present?
#products = Product.search_by_name_and_category(params[:query])
else
#products = Product.all
end
end
def new
#product = Product.new
#product.user = current_user
end
def show
#product = Product.find(params[:id])
end
end
Here is my product model:
class Product < ApplicationRecord
belongs_to :user
has_many :bookings
validates :name, presence: true
validates :category, presence: true
has_one_attached :photo
include PgSearch::Model
pg_search_scope :search_by_name_and_category,
against: [ :name, :category ],
using: {
tsearch: { prefix: true } # <-- now `superman batm` will return something!
}
end
This is my product-card partial.
<div class="card-product-container">
<div class="cards">
<div class="card-product">
<%= link_to product_path(#products.id) do %>
<img src="https://source.unsplash.com/random/?<%= product.name %>" />
<div class="card-product-footer">
<div>
<h2><%= product.name %></h2>
<p><%= product.category %></p>
</div>
<h2><%= product.price %></h2>
</div>
<% end %>
</div>
</div>
#products is a list of many Products. The list doesn't have an ID. Each Product in the list does.
You instead want the ID of a each individual Product in #products.
Iterate through #products and work with a single Product.
<% #products.each do |product| %>
<div class="card-product">
<%= link_to product_path(product.id) do %>
<img src="https://source.unsplash.com/random/?<%= product.name %>" />
<% end %>
<div class="card-product-footer">
<div>
<h2><%= product.name %></h2>
<p><%= product.category %></p>
</div>
<h2><%= product.price %></h2>
</div>
</div>
<% end %>
I have a list of users that post reviews. I'm trying to make the list sortable in different ways. I'm stuck on sorting the list by each user's most recent review.
My current approach is to make a model scope. I'm just not getting it.
This is the model:
class User < ApplicationRecord
attr_accessor :password
validates_confirmation_of :password
validates :email, :presence => true, :uniqueness => true
validates :user_name, :presence => true, :uniqueness => true
before_save :encrypt_password
has_many :reviews
has_one_attached :avatar_pic
scope :users_most_recent, -> {(
select('users.id, users.user_name')
.joins(:reviews).where('reviews.updated_at')
.group('users.id')
.order('updated_at DESC')
)}
def self.user_reviews(user_id)
#user_reviews = Review.where(user_id: user_id).count
end
def self.user_ave_rating(user_id)
_average_reviews = []
_rev_count = 0
_new_average = 0.0
_average_reviews = Review.where(user_id: user_id)
_average_reviews.each do |average_review|
_rev_count += average_review.rating
end
_new_average = (_rev_count / _average_reviews.length.to_f).round(1)
end
def self.user_latest_review(user_id)
#latest_review = Review.where(user_id: user_id).where('created_at < ? ', Time.now).order('created_at DESC').first
if #latest_review.nil?
last_review = {}
else
last_review = #latest_review.created_at.strftime('%m-%d-%Y')
end
end
def encrypt_password
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password,password_salt)
end
def self.authenticate(email, password)
user = User.find_by "email = ?", email
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
end
This is the controller, the index is where I'm trying to implement this:
class UsersController < ApplicationController
before_action :current_user, only: [:show, :edit, :update, :destroy]
def new
#user = User.new
end
def create
#user = User.new(user_params)
#user.avatar_pic.attach(params[:user][:avatar_pic])
if #user.save
flash[:notice] = "You've successfully signed up!"
session[:user_id] = #user.id
redirect_to "/"
else
flash[:alert] = "There was a problem signing up."
redirect_to '/signup'
end
end
def show
#user = current_user
render :show
end
def edit
#user = current_user
render :edit
end
def update
#user = current_user
if #user.update(user_params)
flash[:notice] = "Profile successfully updated!"
redirect_to user_path(#user)
else
render :edit
flash[:notice] = "Something went wrong. Please contact Mario's technical assistance staff."
end
end
def index
case
when params[:az]
#users = User.order('user_name').paginate(page: params[:page], per_page: 20)
when params[:za]
#users = User.order('user_name DESC').paginate(page: params[:page], per_page: 20)
when params[:high_rating]
"High Rating"
when params[:low_rating]
"Low Rating"
when params[:most_reviews]
"Most Reviews"
when params[:least_reviews]
"Least Reviews"
when params[:most_recent]
#users = User.users_most_recent.paginate(page: params[:page], per_page: 20)
when params[:least_recent]
"Least Recent"
else
#users = User.all.paginate(page: params[:page], per_page: 20)
end
render :index
end
private
def user_params
params.require(:user).permit(:email, :user_name, :password, :password_confirmation, :admin, :avatar_pic)
end
end
This is my view:
<p id="notice"><%= notice %></p>
<div class="sort-flex-wrapper">
<h1 class="center">Our Community</h1>
<div class="btn-group sort-button">
<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Sort By
</button>
<div class="dropdown-menu">
<%= link_to "User Name A-Z", users_path(:az => 'az'), class: "dropdown-item" %>
<%= link_to "User Name Z-A", users_path(:za => 'za'), class: "dropdown-item" %>
<%= link_to "Highest Average Rating", users_path(:high_rating => 'high_rating'), class: "dropdown-item" %>
<%= link_to "Lowest Average Rating", users_path(:low_rating => 'low_rating'), class: "dropdown-item" %>
<%= link_to "Most Reviews", users_path(:most_reviews => 'most_reviews'), class: "dropdown-item" %>
<%= link_to "Least Reviews", users_path(:least_reviews => 'least_reviews'), class: "dropdown-item" %>
<%= link_to "Most Recent Review", users_path(:most_recent => 'most_recent'), class: "dropdown-item" %>
<%= link_to "Least Recent Review", users_path(:least_recent => 'least_recent'), class: "dropdown-item" %>
</div>
</div>
</div>
<div class="community-flex-container">
<% if #users.any? %>
<% #users.each do |user| %>
<div class="community-profile-card">
<div class="community-profile-flex">
<div class="community-profile-box1">
<% if user.avatar_pic.attached? %>
<%= image_tag user.avatar_pic, class:"avatar" %><br>
<% else %>
<%= image_tag 'generc_profile_pic.webp', class:"avatar", alt: 'Avatar Not Found ' %><br>
<% end %>
</div>
<div class="community-profile-box2">
<div class="community-column-box1">
<% if user.user_name? %>
<h3><%= user.user_name %></h3>
<% else %>
<h3>Guest User</h3>
<% end %>
</div>
<div class="community-column-box2">
<div class="community-align-stars">
<p>Average Rating: </p>
</div>
<div class="community-align-stars">
<div class="star-align">
<%= render partial: "shared/review_stars", locals: { review: User.user_ave_rating(user.id) } %>
</div>
</div>
</div>
<div class="community-column-box3">
<p>Number of Reviews: <%= User.user_reviews(user.id) %></p>
</div>
<div class="community-column-box4">
<% if User.user_latest_review(user.id) == {} %>
<p>Most Recent Review: None</p>
<% else %>
<p>Most Recent Review: <%= User.user_latest_review(user.id) %></p>
<% end %>
</div>
</div>
</div>
</div>
<% end %>
<% else %>
<p>There are no users (yet).</p>
<% end %>
</div>
<div class="pagination">
<%= will_paginate #reviews%>
</div>
scope :users_most_recent, -> {(
select('users.id, users.user_name, max(reviews.updated_at) as reviews_updated_at')
.joins(:reviews)
.group('users.id')
.order('reviews_updated_at')
)}
Well, while we're at it we might as well fix the whole index method. You're doing to much in the controller, split it out to something like this:
class UserList
def self.order_users_by(order_value)
case order_value
when :az
User.order('user_name ASC')
when :za
User.order('user_name DESC')
when :high_rating
User.all.sort_by(&:average_rating).reverse
when :low_rating
User.all.sort_by(&:average_rating)
when :most_reviews
User.all.sort_by(&:review_count).reverse
when :least_reviews
User.all.sort_by(&:review_count)
else
User.all.sort_by(&:last_updated_review)
end
end
end
class User
def average_rating
(BigDecimal(reviews.sum(:rating).to_s) / BigDecimal(reviews.count.to_s)).round(1)
end
def review_count
reviews.count
end
def last_updated_review
reviews.order("updated_at")
end
end
class UsersController < ApplicationController
def index
UserList.order_users_by(params).paginate(page: params[:page], per_page: 20)
end
end
I am modifying the blog of the guide that I have just finished.
What I want now is to show if there were errors in validating comments in the same way that I show them when validating articles.
I already established the corresponding restrictions in the model, and in fact works, because when you want to comment with values that violate the restriction, the system does not save the comment, but the user does not know why that happens.
Articulo means an article
Comentar means to comment
Comentario means a comment
Comentarios means comments
Annex some files:
/app/controllers/articulos_controller.rb
class ArticulosController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secreto", except: [:index, :show]
def index
#articulos = Articulo.all
end
def show
#articulo = Articulo.find(params[:id])
end
def new
#articulo = Articulo.new
end
def edit
#articulo = Articulo.find(params[:id])
end
def create
#articulo = Articulo.new(articulo_params)
if #articulo.save
redirect_to #articulo
else
render 'new'
end
end
def update
#articulo = Articulo.find(params[:id])
if #articulo.update(articulo_params)
redirect_to #articulo
else
render 'edit'
end
end
def destroy
#articulo = Articulo.find(params[:id])
#articulo.destroy
redirect_to articulos_path
end
private
def articulo_params
params.require(:articulo).permit(:titular, :contenido)
end
end
/app/controllers/comentarios_controller.rb
class ComentariosController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secreto", only: :destroy
def new
articulo = Articulo.find(params[:id])
#comentario = articulo.comentarios.build
end
def create
#articulo = Articulo.find(params[:articulo_id])
#comentario = #articulo.comentarios.create(comentario_params)
redirect_to articulo_path(#articulo)
end
def destroy
#articulo = Articulo.find(params[:articulo_id])
#comentario = #articulo.comentarios.find(params[:id])
#comentario.destroy
redirect_to articulo_path(#articulo)
end
private
def comentario_params
params.require(:comentario).permit(:comentarista, :contenido)
end
end
/app/models/articulo.rb
class Articulo < ApplicationRecord
has_many :comentarios
validates :titular, presence: true, length: { minimum: 5 }
validates :contenido, presence: true, length: { minimum: 10 }
end
/app/models/comentario.rb
class Comentario < ApplicationRecord
belongs_to :articulo
validates :comentarista, presence: true, length: { minimum: 4 }
validates :contenido, presence: true, length: { minimum: 2 }
end
/app/views/articulos/_form.html.erb
<%= form_for #articulo do |f| %>
<% if #articulo.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#articulo.errors.count, "error") %> han impedido que el artículo sea grabado:
</h2>
<ul>
<% #articulo.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :titular %><br>
<%= f.text_field :titular %>
</p>
<p>
<%= f.label :contenido %><br>
<%= f.text_area :contenido %>
</p>
<p>
<%= f.submit 'Guardar' %>
</p>
<% end %>
/app/views/comentarios/_form.html.erb
<%= form_for([#articulo, #articulo.comentarios.build]) do |f| %>
<p>
Nombre<br>
<%= f.text_field :comentarista %>
</p>
<p>
Comentario<br>
<%= f.text_area :contenido %>
</p>
<p>
<%= f.submit 'Comentar' %>
</p>
<% end %>
How can I be able to show such errors when validating?
From already thank you very much.
You should create an error messages partial app/views/shared/_error_messages.html.erb like so:
<% if object.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(object.errors.count, "error") %> han impedido que el
artículo sea grabado: # change artículo to the appropriate word
</h2>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
And render the error messages partial inside your articles and comments forms:
/views/comentarios/_form.html.erb and
/views/articulos/_form.html.erb
<%= render 'shared/error_messages', object: f.object %>
This is the DRY way and it'll work with both articles and comments or any object.
Also, change your comments controller's create action to this as it redirects to the article show page instead of showing the errors:
def create
#articulo = Articulo.find(params[:articulo_id])
#comentario = #articulo.comentarios.create(comentario_params)
if #comentario.save
redirect_to articulo_path(#articulo)
end
end
How can we DESC order results according to its :date_value in the quantifieds index?
Results being the nested attribute to quantifieds.
Right now the order is according to where the User added the result in the form, regardless of :date_value.
This has proven more difficult than I would have guessed.
class QuantifiedsController < ApplicationController
before_action :set_quantified, only: [:show, :edit, :update, :destroy]
before_action :logged_in_user, only: [:create, :destroy]
def index
if params[:tag]
#quantifieds = Quantified.tagged_with(params[:tag])
else
#quantifieds = Quantified.joins(:results).all
#averaged_quantifieds = current_user.quantifieds.averaged
#instance_quantifieds = current_user.quantifieds.instance
end
end
def show
end
def new
#quantified = current_user.quantifieds.build
end
def edit
end
def create
#quantified = current_user.quantifieds.build(quantified_params)
if #quantified.save
redirect_to quantifieds_url, notice: 'Quantified was successfully created'
else
#feed_items = []
render 'pages/home'
end
end
def update
if #quantified.update(quantified_params)
redirect_to quantifieds_url, notice: 'Goal was successfully updated'
else
render action: 'edit'
end
end
def destroy
#quantified.destroy
redirect_to quantifieds_url
end
private
def set_quantified
#quantified = Quantified.find(params[:id])
end
def correct_user
#quantified = current_user.quantifieds.find_by(id: params[:id])
redirect_to quantifieds_path, notice: "Not authorized to edit this goal" if #quantified.nil?
end
def quantified_params
params.require(:quantified).permit(:categories, :metric, :result, :date, :tag_list, results_attributes: [:id, :result_value, :date_value, :_destroy])
end
end
class Quantified < ActiveRecord::Base
belongs_to :user
has_many :results #correct
accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true #correct
scope :averaged, -> { where(categories: 'Averaged') }
scope :instance, -> { where(categories: 'Instance') }
validates :categories, :metric, presence: true
acts_as_taggable
CATEGORIES = ['Averaged', 'Instance']
end
class Result < ActiveRecord::Base
belongs_to :user
belongs_to :quantified
end
class CreateQuantifieds < ActiveRecord::Migration
def change
create_table :quantifieds do |t|
t.string :categories
t.string :metric
t.references :user, index: true
t.timestamps null: false
end
add_foreign_key :quantifieds, :users
add_index :quantifieds, [:user_id, :created_at]
end
end
class CreateResults < ActiveRecord::Migration
def change
create_table :results do |t|
t.string :result_value
t.date :date_value
t.integer :quantified_id
t.timestamps null: false
end
end
end
form
<%= javascript_include_tag "quantified.js" %>
<%= simple_form_for(#quantified) do |f| %>
<%= f.error_notification %>
<div class="america">
<form>
<% Quantified::CATEGORIES.each do |c| %>
<%= f.radio_button(:categories, c, :class => "date-format-switcher") %>
<%= label(c, c) %>
<% end %>
<br/>
<br/>
<div class="form-group">
<%= f.text_field :tag_list, quantified: #quantified.tag_list.to_s.titleize, class: 'form-control', placeholder: 'Enter Action' %>
</div>
<div class="form-group">
<%= f.text_field :metric, class: 'form-control', placeholder: 'Enter Metric' %>
</div>
<div id="results">
<%= f.fields_for :results do |result| %>
<%= render 'result_fields', :f => result %>
<% end %>
</div>
<div class="links">
<b><%= link_to_add_association 'Add Result', f, :results %></b>
</div>
<div class="america2">
<%= button_tag(type: 'submit', class: "btn") do %>
<span class="glyphicon glyphicon-plus"></span>
<% end %>
<%= link_to quantifieds_path, class: 'btn' do %>
<span class="glyphicon glyphicon-chevron-left"></span>
<% end %>
<%= link_to #quantified, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn' do %>
<span class="glyphicon glyphicon-trash"></span>
<% end %>
</div>
</form>
</div>
<% end %>
index
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>AVERAGE</b></h4></div>
<% #averaged_quantifieds.each do |averaged| %>
<div class="attempt">
<b><%= raw averaged.tag_list.map { |t| link_to t.titleize, tagquantifieds_path(t) }.join(', ') %>
<%= link_to edit_quantified_path(averaged) do %>
(<%= averaged.metric %>)</b>
<% end %>
<ul>
<% averaged.results.each do |result| %>
<li>
<b><%= result.result_value %></b>
<%= result.date_value.strftime("%b %Y") %>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
<div class="valuations-button">
<%= link_to new_quantified_path, class: 'btn' do %>
<b><span class="glyphicon glyphicon-plus"</span></b>
<% end %>
</div>
<br>
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>INSTANCE</b></h4></div>
<% #instance_quantifieds.each do |instance| %>
<div class="attempt">
<b><%= raw instance.tag_list.map { |t| link_to t.titleize, tagquantifieds_path(t) }.join(', ') %>
<%= link_to edit_quantified_path(instance) do %>
(<%= instance.metric %>)</b>
<% end %>
<ul>
<% instance.results.each do |result| %>
<li>
<%= result.date_value.strftime("%b.%d.%y") %>
<%= result.result_value %>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
<div class="valuations-button">
<%= link_to new_quantified_path, class: 'btn' do %>
<b><span class="glyphicon glyphicon-plus"</span></b>
<% end %>
</div>
Thanks so much for your time!
Got it! Add default_scope { order('date_value DESC') } in result.rb
im having some trouble with my Ruby on Rails app. I'm new at this so i imagine the problem isn't too complicated
Basically I am trying to create a discussion board. the page /discussions has many discussions created by users who can make microposts to comment on them. When I click the post button for the micropost form however, i get an error that reads
NoMethodError in Microposts#create
Showing /home/nick/Documents/RailsProjects/buon/app/views/shared/_discussion_form.html.erb where line #1 raised:
undefined method `model_name' for NilClass:Class
any ideas? heres some of the code
micropost.rb
class Micropost < ActiveRecord::Base
attr_accessible :break_votes, :content, :not_votes
belongs_to :user
belongs_to :discussion
validates :content, presence: true, length: { maximum: 200 }
validates :user_id, presence: true
validates :discussion_id, presence: true
default_scope order: 'microposts.created_at DESC'
end
_discussions.html.erb
<% content_for :script do %>
<%= javascript_include_tag 'hover_content' %>
<% end %>
<li>
<div class = "intro-bar"><span class = "intro"><%=discussion.intro %></span></div>
<div class = "content-bar">
<span class = "content"><%= discussion.content %>
<div class = "vote-plus"><%= link_to "Stay Together", signup_path,class: "btn btn-large btn-primary" %></div>
<div class = "vote-neg"><%= link_to "Break Up", signup_path,class: "btn btn-large btn-primary" %></div>
</span>
</div>
<span class = "timestamp">
Posted <%= time_ago_in_words(discussion.created_at) %> ago.
</span>
</li>
<div class = "comments">
<% discussion.microposts.each do |micropost| %>
<li>
<div class = "post-comment"><%= micropost.content%></div>
</li>
<% end %>
</div>
<% if signed_in? %>
<div class = "row">
<aside class = "span4">
<section>
<%= render 'shared/micropost_form', :locals => {:discussion => discussion }%>
</section>
</aside>
</div>
<% end %>
micropost controller
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
def index
end
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Posted!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def destroy
end
end
discussions_controller
class DiscussionsController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update]
def show
#user = User.find(params[:id])
#discussions = #user.discussion.paginate(page: params[:page])
#microposts = #user.micropost.paginate(page: params[:page])
end
def index
#discussions = Discussion.all
end
def create
#discussion = current_user.discussions.build(params[:discussion])
if #discussion.save
flash[:success] = "Discussion Started!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def destroy
end
def edit
end
def update
end
def new
end
end
update: micropost_form
<% #micropost = Micropost.new %>
<% #micropost.discussion = nil %>
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>