Ruby on Rails nil value - ruby-on-rails

I somehow broke my application and can't seem to find my mistake and would appreciate some help a lot.
<%= debug #relquotes %>
<%= debug #book%>
<h4 class="text-center">Related Quotes</h4>
<% #relquotes.each do |quote| %>
<article class="blog-1 blog-archive py-5">
<div class="col-12 col-md-8 mr-md-auto ml-md-auto">
<ol class="list-unstyled">
<li>
<h2 class="leading-normal mb-3"><%= quote.title %></h2>
<div class="article-meta color-grey-50">
<div class="media-body d-flex align-items-center">
<p class="m-0 media-heading"><a>by </a><%= link_to quote.user.username, user_path(quote.user) %> •
created <%= time_ago_in_words(quote.created_at) %> ago</p>
</div>
</div>
<p class="quotebody"><%= sanitize quote.body.first(240) %> (...)</p>
<a> <%= link_to quote do %> Read more →</a>
<% end %>
</ol>
</div>
</article>
<% end %>
Got this on my Book view and I have related quotes from books that I want to display with this
class Quote < ApplicationRecord
belongs_to :user
belongs_to :category
belongs_to :book
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :body, presence: true, length: {minimum: 240}
end
class Book < ApplicationRecord
belongs_to :user, optional: true
belongs_to :category, optional: true
has_many :quotes
has_many :reviews, dependent: :destroy
has_attached_file :book_cover, styles: {book_index: '250x350>', book_show: '325x475>'}
validates_attachment_content_type :book_cover, content_type: /\Aimage\/.*\z/
end
My books controller
class BooksController < ApplicationController
layout "_app_nav"
before_action :set_book, only: [:show, :edit, :update, :destroy]
# GET /books/1
def show
#average_review = if #book.reviews.blank?
0
else
#book.reviews.average(:rating).round(2)
end
#relquotes = #book.quotes
end
private
# Use callbacks to share common setup or constraints between actions.
def set_book
#book = Book.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def book_params
params.require(:book).permit(:title, :author, :description, :user_id, :book_cover, :category_id)
end
end
The debug #book works fine and my book gets displayed. I confirmed via rails console that the quote is associated with the book.
The debug #relquotes resolves in plain '--- []'.
It was working before and I cant seem to find where I messed it up.
My #relquotes should display all the quotes that are associated with a book. I can confirm that quotes are associated with a book.
eg. quote has book_id = 1 - therefore the book with the book_id 1 should display this quote as a 'related quote'.
Any help would be appreciated.
Thanks in advance!

Related

Not able to display random images below product image in Ruby on rails app?

I want to be able to show 3 random product images below a product image, so far I've inserted this code below the product image as seen in the views/products/show.html.erb
views/products/show.html.erb
<div class="col-xs-12 col-sm-6 center-block" >
<%= image_tag #product.image.url(:medium), class: "img-responsive" %>
#This is the Product image#
##EDITED ##
#Below is the codesnippet for three products to appear##
<% #products.each do |product| %>
<div class="col-sm-2 center-block " >
<%= link_to product_path (product) do %>
<%= image_tag product.image.url(:thumb), class: "img-responsive" %>
<% end %>
<div class="product_description">
<h5><%= link_to product.title, product %></h5>
</div>
</div>
<% end %>
And in my products_controller.rb I've the code, I believe the problem is to be found in the #products, but I'm not sure what it is. Please can someone advice me.
products_controller.rb
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
def show
#meta_title = "Concept Store #{#product.title}"
#meta_description = #product.description
#products = Product.all ###EDITED###
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :description, :price_usd, :price_isl, :image, :category_id, :stock_quantity, :label_id, :query, :slug)
end
end
My models Products and Categorieshave relations
product.rb
class Product < ActiveRecord::Base
belongs_to :category
belongs_to :label
has_many :product_items, :dependent => :destroy
extend FriendlyId
friendly_id :title, use: [:slugged, :finders]
validates :title, :description, presence: true
validates :price_usd, :price_isl, numericality: {greater_than_or_equal_to: 0.01}
validates :title, uniqueness: true
has_attached_file :image, styles: { medium: "500x500#", thumb: "100x100#" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
end
category.rb
class Category < ActiveRecord::Base
has_many :products, :dependent => :nullify
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
end
Let's break this down:
#products = Category.joins(:products).where(:products => {:id => #product.image})
#products okay, presumably a collection of Product instances
Category.joins(:products) uhhh, this returns instances of Category
where(products: { id: #product.image }) wait, filter by products with an ID matching #product.image, which is ostensibly a string url or file path
All together: #products = an array of categories with associated products where the numeric ID matches a particular string on a particular product.
My recommendation for you would be to review the Rails Guides with particular attention to the ActiveRecord Basics.

Rails - Returning list of incorrect ids

I have an app including Dog, Events and Booking models. Each event has many bookings, each dog has many bookings but each booking belong to an event and has one dog.
On the view for Events it should list all bookings with that id and the details of the linked dog.
I was having a lot of trouble with "Rails Error: undefined method ` ' for nil:NilClass" but then realised the problem was that it is retrieving a list of dogs based on the booking id and not the dog_id field.
In the console I can see that this is the SQL query being generated and what I think is the source of the error but I can't figure out why:
SELECT "dogs".* FROM "dogs" INNER JOIN "bookings" ON "dogs"."id" = "bookings"."id" WHERE "bookings"."event_id" = ? [["event_id", 1]]
I've spent days combing Stack Overflow and Google to figure out where I've gone wrong but am a bit lost. Here are the models:
class Event < ActiveRecord::Base
has_many :bookings
has_many :dogs, :through => :bookings, :foreign_key => "dog_id"
end
class Dog < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 255 }
validates :breed, presence: true, length: { maximum: 255 }
belongs_to :owner
validates :owner_id, presence: true
has_many :bookings
has_many :events, through: :bookings, :foreign_key => "event_id"
end
class Booking < ActiveRecord::Base
belongs_to :event
has_one :dog, :foreign_key => "id"
validates :event_id, presence: true
validates :dog_id, presence: true
end
The controllers
class EventsController < ApplicationController
before_action :logged_in_user
def index
#events = Event.paginate(page: params[:page])
end
def show
#event = Event.find(params[:id])
#bookings = #event.bookings.paginate(page: params[:page])
...
class DogsController < ApplicationController
def show
#dog = Dog.find(params[:id])
end
def new
#dog = Dog.new
end
...
class BookingsController < ApplicationController
end
And finally the show view for Events and the _booking partial it renders:
<% provide(:title, #event.name) %>
<div class="row">
<aside class="col-md-4">
<section class="event_info">
<h1><%= #event.name %></h1> - <%= #event.category %>
<span><b><%= #event.date %></b> <%= #event.start %> - <%= #event.finish %> </span>
<span><b>Location:</b> <%= #event.location %></span>
<%-# Calculated occupany figure goes in line below. -%>
<span><b>Capacity: </b>X / <%=#event.capacity %></span>
</section>
</aside>
<div class="col-md-8">
<section class="event_notes_header">
Description
</section>
<section class="event_notes_body">
<%= #event.description %>
</section>
<section class="event_notes_header">
Notes
</section>
<section class="event_notes_body">
Event notes will be displayed here...
</section>
</div>
<div class="col-md-8">
<% if #event.bookings.any? %>
<h3>Bookings (<%= #event.bookings.count %>)</h3>
<ol class="bookings">
<%= render #bookings %>
</ol>
<%= will_paginate #bookings %>
<% end %>
</div>
</div>
_booking.html.erb
<li id="booking<%= booking.id %>">
<span class="event"><%= link_to booking.event.name, booking.event %></span>
<span class="dog"><%= link_to booking.dog.name, booking.dog %></span>
</li>
Apologies if I've missed anything or if the code has gotten a little convoluted - this is where I am after several days of plugging stuff in and out to try and fix this error.
The first problem I see here is in your associations (and I believe it's the main reason this crap is happening). Your Booking model is a typical joining model for a has_many :through association. But the inner associations are not set properly. If you look at the association between Dog and Booking, you'll notice that there are two has_* paths and no belongs_to path (wich needs to be on the model, that has the dog_id in it, in this case the Booking model).
So your first step is to set the associations properly. You should change
has_one :dog, :foreign_key => "id"
to
belongs_to :dog
Second thing I recommend you do with those associations is getting rid of those foreign_key calls, that might just confuse you and are not needed as long as you're folowing conventions.

uninitialized constant User::Post (NameError)

I have the following problem, In UserController#show there has to be a list of posts, but it throws an error as shown in the screen shot:
The part of the code which is responsible to show user posts (show.html.erb)
<div class="span8">
<% if #user.posts.any? %>
<h3>Работы (<%= #user.posts.count %>)</h3>
<ol class="posts">
<%= render #posts %>
</ol>
<%= will_paginate #posts %>
<% end %>
</div>
posts.rb:
class Posts < ActiveRecord::Base
belongs_to :user
default_scope -> { order('created_at DESC') }
validates :description, presence: true, lenght: { minimum: 6 }
validates :user_id, presence: true
end
part of a code in user.rb
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
Your help, thanks in advance is very important.
Excuse for possible mistakes in the text
You should name your model in singular form:
class Post < ActiveRecord::Base

Rails ActiveRecord_Relation

I am currently developing a somewhat 'big' project. In this project I have many models, views, and controllers from which I have to mention the following:
Group.rb:
class Group < ActiveRecord::Base
has_many :users, through: :grouprel
has_many :grouprel, dependent: :destroy
validates :name, presence: true, length: {maximum: 25},
uniqueness: { case_sensitive: false }
validates :description, presence: true , length: {maximum: 140}
end
Grouprel.rb
class Grouprel < ActiveRecord::Base
belongs_to :user
belongs_to :group
validates :user_id, presence: true
validates :group_id, presence: true
end
User.rb
class User < ActiveRecord::Base
.....
has_many :groups, through: :grouprel, dependent: :destroy
has_many :grouprel, dependent: :destroy
.....
StaticPageController:
class StaticPagesController < ApplicationController
def home
if logged_in?
#tweet = current_user.tweets.build
#feed_items = current_user.feed.paginate(page: params[:page])
#groupi = Grouprel.where(user_id: current_user.id).pluck(:group_id)
#groupies = Group.where(id: #groupi).paginate(page: params[:page])
end
end
.....
end
Home.html.erb:
<% if logged_in? %>
.......
<section class="user_info">
<%= render 'shared/group_participation' %>
</section>
</aside>
.............
_group_participation.html.erb
<h5> Your groups: </h5>
<% if #groupies %>
<ol class="tweets">
<%= content_tag_for(:li, #groupies) do %>
<%= link_to #groupies.name, group_path(#groupies) %>
<% end %>
</ol>
<%= will_paginate #groupies %>
<% end %>
here I want to display every single group that a user is part of. The error I get when trying to get the #groupies in the StaticPagesController is %23<Group::ActiveRecord_Relation:0x007f86b00f6ed0> . I checked in my rails console , and it should return something.
What my limited knowledge about rails and ruby can tell is that this is a problem because the StaticPageController can't see the Grouprel.rb table. I tried to include controllers in herlpers. I even tried to define a method that returns 'groupies' in the application controller and then use that in the StaticPagesController. Could I get a hint of why I get that error returned ?
If my post has to contain any more specifications please do tell I will post them the second I see the request
You're not iterating over the groupies collection and are calling the name method on the collection itself. content_tag_for can iterate over the collection for you but you need to use the value it yields to the block:
<%= content_tag_for(:li, #groupies) do |group| %>
<%= link_to group.name, group_path(group) %>
<% end %>

Rails has_many through form with checkboxes and extra field in the join model

I'm trying to solve a pretty common (as I thought) task.
There're three models:
class Product < ActiveRecord::Base
validates :name, presence: true
has_many :categorizations
has_many :categories, :through => :categorizations
accepts_nested_attributes_for :categorizations
end
class Categorization < ActiveRecord::Base
belongs_to :product
belongs_to :category
validates :description, presence: true # note the additional field here
end
class Category < ActiveRecord::Base
validates :name, presence: true
end
My problems begin when it comes to Product new/edit form.
When creating a product I need to check categories (via checkboxes) which it belongs to. I know it can be done by creating checkboxes with name like 'product[category_ids][]'. But I also need to enter a description for each of checked relations which will be stored in the join model (Categorization).
I saw those beautiful Railscasts on complex forms, habtm checkboxes, etc. I've been searching StackOverflow hardly. But I haven't succeeded.
I found one post which describes almost exactly the same problem as mine. And the last answer makes some sense to me (looks like it is the right way to go). But it's not actually working well (i.e. if validation fails). I want categories to be displayed always in the same order (in new/edit forms; before/after validation) and checkboxes to stay where they were if validation fails, etc.
Any thougts appreciated.
I'm new to Rails (switching from CakePHP) so please be patient and write as detailed as possible. Please point me in the right way!
Thank you. : )
Looks like I figured it out! Here's what I got:
My models:
class Product < ActiveRecord::Base
has_many :categorizations, dependent: :destroy
has_many :categories, through: :categorizations
accepts_nested_attributes_for :categorizations, allow_destroy: true
validates :name, presence: true
def initialized_categorizations # this is the key method
[].tap do |o|
Category.all.each do |category|
if c = categorizations.find { |c| c.category_id == category.id }
o << c.tap { |c| c.enable ||= true }
else
o << Categorization.new(category: category)
end
end
end
end
end
class Category < ActiveRecord::Base
has_many :categorizations, dependent: :destroy
has_many :products, through: :categorizations
validates :name, presence: true
end
class Categorization < ActiveRecord::Base
belongs_to :product
belongs_to :category
validates :description, presence: true
attr_accessor :enable # nice little thingy here
end
The form:
<%= form_for(#product) do |f| %>
...
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<%= f.fields_for :categorizations, #product.initialized_categorizations do |builder| %>
<% category = builder.object.category %>
<%= builder.hidden_field :category_id %>
<div class="field">
<%= builder.label :enable, category.name %>
<%= builder.check_box :enable %>
</div>
<div class="field">
<%= builder.label :description %><br />
<%= builder.text_field :description %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And the controller:
class ProductsController < ApplicationController
# use `before_action` instead of `before_filter` if you are using rails 5+ and above, because `before_filter` has been deprecated/removed in those versions of rails.
before_filter :process_categorizations_attrs, only: [:create, :update]
def process_categorizations_attrs
params[:product][:categorizations_attributes].values.each do |cat_attr|
cat_attr[:_destroy] = true if cat_attr[:enable] != '1'
end
end
...
# all the rest is a standard scaffolded code
end
From the first glance it works just fine. I hope it won't break somehow.. :)
Thanks all. Special thanks to Sandip Ransing for participating in the discussion. I hope it will be useful for somebody like me.
use accepts_nested_attributes_for to insert into intermediate table i.e. categorizations
view form will look like -
# make sure to build product categorizations at controller level if not already
class ProductsController < ApplicationController
before_filter :build_product, :only => [:new]
before_filter :load_product, :only => [:edit]
before_filter :build_or_load_categorization, :only => [:new, :edit]
def create
#product.attributes = params[:product]
if #product.save
flash[:success] = I18n.t('product.create.success')
redirect_to :action => :index
else
render_with_categorization(:new)
end
end
def update
#product.attributes = params[:product]
if #product.save
flash[:success] = I18n.t('product.update.success')
redirect_to :action => :index
else
render_with_categorization(:edit)
end
end
private
def build_product
#product = Product.new
end
def load_product
#product = Product.find_by_id(params[:id])
#product || invalid_url
end
def build_or_load_categorization
Category.where('id not in (?)', #product.categories).each do |c|
#product.categorizations.new(:category => c)
end
end
def render_with_categorization(template)
build_or_load_categorization
render :action => template
end
end
Inside view
= form_for #product do |f|
= f.fields_for :categorizations do |c|
%label= c.object.category.name
= c.check_box :category_id, {}, c.object.category_id, nil
%label Description
= c.text_field :description
I just did the following. It worked for me..
<%= f.label :category, "Category" %>
<%= f.select :category_ids, Category.order('name ASC').all.collect {|c| [c.name, c.id]}, {} %>

Resources