uninitialized constant User::Post (NameError) - ruby-on-rails

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

Related

Ruby on Rails nil value

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!

Check box that creates nested objects in rails

I'm building an app that creates exams. For the part where a user selects the answers on the exam, I want to use a checkbox (or a radio button) to allow them to pick the answer.
I want all the user-selected answers to be a table in itself called "responses". I can't figure out how to use a radio button to create records.
All the response record needs to do is take the ID's of the Exam, User, and Score. Score is a table that tracks the user's scores and the number of correct answers.
Here's my examination model (rails wouldn't let me use the word "exam"). I have it set for nested attributes.
class Examination < ApplicationRecord
belongs_to :user
has_many :questions, dependent: :destroy
has_many :scores
has_many :responses
has_secure_password
accepts_nested_attributes_for :responses, allow_destroy: true
end
The response model is pretty basic:
class Response < ApplicationRecord
belongs_to :user
belongs_to :score
belongs_to :examination
end
Here's the "take an exam" page:
<%= link_to "Back to all exams", examinations_path %>
<h2><%= #exam.name %></h2>
<h3><%= #exam.intro %></h3>
<%= form_for #exam do |f| %>
<%= f.hidden_field :name, value: #exam.name %>
<%= fields_for :responses do |res_f| %>
<% #exam.questions.each_with_index do |question, i| %>
<% index = i + 1 %>
<h2>Question #<%=index%></h2><span style="font-size: 24px; font-weight: normal">(<%= question.points %> Points)</span>
<hr>
<h3><%= question.body %></h3>
<% question.answers.each do |ans| %>
<table>
<tr>
<td><%= res_f.check_box :answer_id , ans.id, :examination_id , #exam.id, :user_id %></td>
<td><%= ans.body %></td>
</tr>
</table>
<% end %>
<% end %>
<% end %>
<%= f.submit 'Submit' %>
<% end %>
This code doesn't run because Rails expects the responses records to exist in order to use the form. It throws this error:
undefined method `merge' for 484:Integer
If I tweak that checkbox code to this:
<%= res_f.check_box :answer_id %>
The code will run and it will give me the following params on submit:
Started PATCH "/examinations/34" for 127.0.0.1 at 2018-02-24 16:22:41 -0800
Processing by ExaminationsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"y4vcPByUKnDdM6NsWDhwxh8MxJLZU4TQo+/fUrmKYEfb3qLn5FVieJAYirNRaSl0w5hJax20w5Ycs/wz1bMEKw==", "examination"=>{"name"=>"Samuel Smith’s Oatmeal Stout"}, "responses"=>{"answer_id"=>"1"}, "commit"=>"Submit", "id"=>"34"}
I know it's not right but I was hoping it would create a record at least. All the checkbox has to do it create a response record. It should be able to grab the answer_id, exam_id and user_id. That's it.
Does anyone know how to do this?
Edit in response to Pablo 7:
Here are the other models (they're pretty basic right now)
class Score < ApplicationRecord
belongs_to :user
belongs_to :examination
has_many :responses, dependent: :destroy
end
class User < ApplicationRecord
has_many :examinations, dependent: :destroy
has_many :scores, dependent: :destroy
has_many :responses, dependent: :destroy
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
class Question < ApplicationRecord
belongs_to :examination
has_many :answers, dependent: :destroy
accepts_nested_attributes_for :answers, allow_destroy: true
validates_presence_of :body
validates_presence_of :question_type
end
#exam and Examination are the same. There is a "take" action in the Examination controller that allows a user to take an exam:
def take
#exam = Examination.find(params[:id])
#score = #exam.scores.build
#score.user_id = current_user.id
#score.save
end
So an exam belongs to the user that created it. The same user or a different one can take an exam using the take action. They would then have a score that belongs to them.
I think you must do some changes to your models:
A Response should belong to a Question (it's the question the user is responding).
A Response should belong to an Answer (it's the correct Answer for the question; the one that the user checks). If you want to allow multiple correct answers, this should be changed.
A Response should not belong to an Examination and should not belong to a User. In fact, a Response belongs to a Score and that's enough because the Score already belongs to an Examination and to a User.
An Examination should not have many responses. In fact, an Examination has many scores and scores have many responses. If you want, you can use has_many :responses, through: :scores
A User should not have many Responses. They have many Scores and Scores have many Responses. If you want, you can use has_many :responses, through: :scores
When you create a new score (in take), you should create empty responses for each question in the examination:
def take
#exam = Examination.find(params[:id])
#score = #exam.scores.build(user_id: current_user.id)
#exam.questions.each { |question| #score.responses.build(question_id: question.id) }
#I don't think you should save here.
#This method is like the new method
#You should save when the score is submitted
##score.save
end
In your form:
I would change the form to the score model (not examination). If you are using nested routes it could be [#exam, #score]
This may have many errors, as I cannot test it right now. I hope the idea is clear:
<%= form_for #score do |f| %>
<%= f.hidden_field :name, value: #score.examination.name %>
<% #score.responses.each_with_index do |response, i| %>
<%= f.fields_for response do |res_f| %>
<% index = i + 1 %>
<h2>Question #<%= index %></h2>
<span style="font-size: 24px; font-weight: normal">
(<%= response.question.points %> Points)
</span>
<hr>
<h3><%= response.question.body %></h3>
<%= res_f.collection_radio_buttons :answer_id, response.question.answers, :id, :body %>
<% end %>
<% end %>
<%= f.submit 'Submit' %>
<% end %>
The submit should call a method in Score model to create a Score (ScoresController.create)
Thanks Pablo, I finally got it working. Your code didn't quite work but it put me on the right path. I changed the model associations around as you suggested. That does make more sense.
Here are my models:
class Answer < ApplicationRecord
belongs_to :question
has_many :responses, dependent: :destroy
end
class Examination < ApplicationRecord
belongs_to :user
has_many :questions, dependent: :destroy
has_many :answers, :through => :questions
has_many :scores
has_secure_password
end
class Question < ApplicationRecord
belongs_to :examination
has_many :answers, dependent: :destroy
has_many :responses
accepts_nested_attributes_for :answers, allow_destroy: true, :reject_if => :all_blank
validates_presence_of :body
validates_presence_of :question_type
end
class Response < ApplicationRecord
belongs_to :score
belongs_to :answer
belongs_to :question
end
class Score < ApplicationRecord
belongs_to :user
belongs_to :examination
has_many :responses, dependent: :destroy
accepts_nested_attributes_for :responses, allow_destroy: true, reject_if: :no_answer_id?
private
def no_answer_id?(att)
att['answer_id'].blank?
end
end
I had to add that special method to the Score model to account for unchecked responses. Otherwise, it would throw an error.
I moved the "take a test" logic and view to the Score controller. With your code, I was getting a double loop (questions listed multiple times). I learned that you can actually access the responses through the "form_for" form loop using "res_f.object". That's pretty cool.
I also had to add a hidden field on the radio button collection form to get the question id.
Here it is:
<%= link_to "Back to all exams", examinations_path %><br/>
<h2><%= #exam.name %></h2>
<h3><%= #exam.intro %></h3>
<%= form_for [#exam, #score] do |f| %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.fields_for :responses do |res_f| %>
<h2>Question # <%= res_f.object.question.position %></h2>
<span style="font-size: 24px; font-weight: normal">
(<%= res_f.object.question.points %> Points)
</span>
<hr>
<h3><%= res_f.object.question.body %></h3>
<p><%= res_f.collection_radio_buttons :answer_id, res_f.object.question.answers, :id, :body do |b| %></p>
<div>
<%= b.radio_button %>
<%= b.label %>
<%= res_f.hidden_field :question_id, value: res_f.object.question.id %>
</div>
<% end %>
<% end %>
<%= f.submit 'Submit' %>
<% end %>
And the Scores controller:
class ScoresController < ApplicationController
def new
#exam = Examination.find(params[:examination_id])
#score = #exam.scores.build(user_id: current_user.id)
#exam.questions.each do |question|
res = #score.responses.build(question_id: question.id)
logger.info question.id
logger.info res
end
end
def create
#exam = Examination.find(params[:examination_id])
#score = #exam.scores.build(score_params)
if #score.save
redirect_to examination_path(#exam)
else
logger.info #score.errors.full_messages
redirect_to root_path
end
end
protected
def score_params
params.require(:score).permit(:examination_id, :user_id,
responses_attributes: [:id, :answer_id, :question_id, :selected])
end
end
This all works fine if there is only one correct answer. I'll have to modify it later to account for multiple answers. At least it works! I'll give you the credit Pablo.
Cheers

Undefined method, wrong association or call?

I'm trying to make cumulative show.html for each user, that displays some data from 4 different models. Those tables:
Problem is that I dont know how to call data from Websites table for each Button. With displaying Buttons' data there is no problem.
That part of html should looks something like this:
<% if #profile.buttons.any? %>
<ul>
<% #buttons.each do |button| %>
<li>
<%= button.website.name %>
<%= link_to button.user_website_url, button.user_website_url %>
</li>
<% end %>
</ul>
<% else %>
<p>None websites added. Please finish your profile creation.</p>
<% end %>
Models:
class Website < ActiveRecord::Base
has_many :buttons
mount_uploader :logo, LogoUploader
validates :name, presence: true, length: { maximum: 50 }
validates :logo, presence: true
end
class Button < ActiveRecord::Base
belongs_to :profile
belongs_to :website
accepts_nested_attributes_for :website
validates :description, length: { maximum: 140 }
validates :user_website_url, presence: true, length: { maximum: 200 }
end
class Profile < ActiveRecord::Base
belongs_to :user
has_many :buttons, :dependent => :destroy
#...
end
User Controller:
def show
#user = User.find(params[:id])
#profile = #user.profile
#buttons = #profile.buttons
end
At this state of everything I'm getting an error:
undefined method `name' for nil:NilClass
So, what is wrong with this? I've tried many variations of associations and I'm getting either the error I put above or that no Id is passing (wrong query) for each website (that I also didn't know how to deal with).
This is probably due to a button that has no associated website. See the line:
<%= button.website.name %>
If one of the buttons has a website_id of nil, calling the method name on the nil value would produce the error you see.
Something is wrong with the following code, button.website returns nil,and nil dosen't have a method name:
<%= button.website.name %>
to fix it ,just use try:
<%= button.try(:website).try(:name) %>
This line raising the error <%= button.website.name %>
.name is not getting any value because button has no any associated website and that's why it returns nil:NilClass as an error.

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.

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 %>

Resources