Error: ActiveRecord::RecordNotFound Couldn't find Option with 'id'=
This is happening when I add a link to the options show.html.erb to get all the registrations for that option. In order to get the event id and the option id, I'm adding the following to the show method in the OptionsController:
#event = Event.find(params[:event_id])
#option = Option.find(params[:option_id])
This is the link I'm adding to the show.html.erb file:
link_to "Registrations", event_option_registrations_path(#option)
This is how my 3 models look: Event, option and registrations
event.rb:
class Event < ActiveRecord::Base
has_many :options, dependent: :destroy
end
option.rb:
class Option < ActiveRecord::Base
belongs_to :event
has_many :registrations
end
routes.rb:
resources :events do
resources :options do
resources :registrations
end
Route for Registrations:
event_option_registrations_path /events/:event_id/options/:option_id/registrations(.:format)
registrations#index
Error: ActiveRecord::RecordNotFound Couldn't find Option with 'id'=
This error message is saying that, it can't find the option with id = nil when you do this:
#option = Option.find(params[:option_id])
which means, your params[:option_id] is nil in this case.
You should put a print statement in your controller like this:
def your_action
# these are for debugging
puts params.inspect
puts params[:option_id]
#event = Event.find(params[:event_id])
#option = Option.find(params[:option_id])
end
Then you will be able to see what you are getting inside your params hash. Then, you can grab the correct attribute and then do the rest of the work. Hope this helps you debug the issue and solve your problem.
Update
change this:
#option = Option.find(params[:option_id])
To:
#option = Option.find(params[:id])
Because, in your params hash, you don't have a option_id key, but you have a id key which refers to the id of the option.
Related
I'm following the Rails tutorial and making changes where appropriate, with the intention that my tutorial project will become a full-fledged production app after the completion of the tutorial.
I've run into a snag with the second model portion of the tutorial. Here is how I've written my second model.
In my policy.rb:
class Policy < ApplicationRecord
has_one :insured
end
In my insured.rb:
class Insured < ApplicationRecord
belongs_to :policy
end
In my routes.rb:
resources :policies do
resource :insured
end
In my insureds_controller.rb:
def create
#policy = Policy.find(params[:policy_id])
# next line is raising the error
#insured = #policy.insured.create(insured_params)
redirect_to #insured
end
private
def insured_params
params.permit(:name, :address, :phone, :email)
end
I've inspected the #policy object with render plain: #policy.inspect and can confirm that ActiveRecord is retrieving the policy correctly. When I inspect the attributes of #policy, using render plain: #policy.attribute_names.inspect, I don't see an insured attribute, which I thought Rails was supposed to automatically manage for me. In the tutorial, an article has_many :comments, and a comment is supposedly easily created and associated with the parent article with this call: #article.comments.create(comment_params). I also noticed that the tutorial uses params.require(:comment).permit(...) while I have to use params.permit(...), after inspecting the params hash I saw that the :insured attributes existed in the top-level of the hash, instead of being tied to an :insured key within the hash.
I tried manually saving and assigning the #insured object like so:
def create
#policy = Policy.find(params[:policy_id])
#insured = Insured.new(insured_params)
if #insured.save
#policy.insured = #insured
redirect_to #insured
end
end
Only to run into the following error in my .../insureds/new.html.erb:
<h1>New Insured</h1>
<h1><%= #policy.policy_number %></h2>
<%= render 'form' %>
<%= link_to 'Cancel', policy_path(#policy) %>
Which derives from my partial form .../insureds/_form.html.erb:
# the following line raises the error
<%= form_with model: #insured, local: true do |form| %>
# html omitted for brevity
<% end %>
Error: 'undefined method insureds_path'. This is weird because when I inspect the HTML I can see the form action for this view is /policies/[:id]/insured.
Sorry for the massive wall of text, I wanted to show you guys that I did try to figure out what is going wrong.
There is an error in your config/routes.rb file:
resources :policies do
# change it for:
collection do
get 'insured', to: 'policies#show_insured', as: 'show_policy_insured'
# maybe unnecessary to be here
# get 'insured/new', to: 'insureds#new', as: 'new_policy_insured'
# post 'insured/create', to: 'insureds#create', as: 'create_policy_insured'
# delete 'insured/delete', to: 'insureds#delete', as: 'delete_policy_insured'
end
end
# add resources here
resources :insureds
In policy_controller.rb:
def show_insured # 'policy/:id/insureds/
end
In insureds_controller.rb:
def show # '/insureds/:id'
end
def create
...
redirect_to show_policy_insured && return if #insured_policy
end
# before_filter or before_action
#policy = Policy.find(params[:id])
#insured_policy = #policy.insured
Check it and run this to see your routes:
$ bundle exec rake routes
get /policies/:id/insured => 'policies_controller#show_insured'
get /insureds/:id => 'insureds_controller#show'
get /insured/new => 'insureds_controller#new'
post /insureds/create => 'insureds_controller#create'
delete /insureds/:id/delete => 'insureds_controller#delete'
#maguri, that's not all necessary. The stumbling block I was running into was that Rails couldn't automatically determine the correct routes. When I provided my own urls in the form_with declarations, everything went smoothly.
Observe the following change in my _form.html.erb for the Insured model, which belongs_to Policy, which has_one Insured.
<%= form_with model: #insured, url: policy_insured_path(#policy) local: true do |form| %>
In my updated insureds_controller.rb file, using #Phlip's suggestion:
def create
#policy = Policy.find(params[:policy_id])
#insured = #policy.create_insured(insured_params)
if #policy.insured.save
redirect_to policy_insured_path(params[:policy_id])
else
render 'new'
end
end
This allows me to keep routes.rb clean and simple:
resources :policies do
resource: insured
end
Thank you for your answer, it helped me discover the problem was with my routes.
I am building a question and answer website where the user inputs a question, I take the users input and compare it against the database, If the answer is correct, I take the value of the question and add it to the scoreboard, However I am having an issue where the users input is not being passed through the models, and when I set the #user_input = params[:content], It is always returning null, I believe this is because I am using namespace/nested models.
The plan of actions:
Get the current answer from the database for the current_question_id, and set as a varaiable
Check Users input against the answer in the database
if question_id & user_submitted_answer exists in database
create record in submission's table with status == correct
else
create record in submissions table with status == Incorrect
Models:
members/question
class Members::Question < ActiveRecord::Base
belongs_to :category
belongs_to :point
belongs_to :event
has_many :submissions
has_one :answer
end
Submissions
class Submission < ActiveRecord::Base
belongs_to :question
belongs_to :member
end
Routes:
Rails.application.routes.draw do
#Root Routes
root 'home#index'
get 'home/index'
get 'home/about'
mount RailsAdmin::Engine => '/eriadmin', as: 'rails_admin'
#Devise Controller
devise_for :members
#Members namepsace
get '/members/', to: 'members/dashboard#index', as: 'members_dashboard', only: [:show]
resources :answers
namespace :members do
resources :questions, only: [:index,:show] do
resources :submissions
end
end
end
Submissions Controller
Create Method
#answer_check = Answer.where("question_id = ? AND content = ?",set_members_question, set_user_submission)
if #answer_check.present?
flash.alert = 'Answer There'
#submission = #members_question.submissions.create(params[:submission].permit(:question_id))
#submission.member_id = current_member.id
#submission.content = Submission.find_by(params[:content])
else
flash.alert = 'NOPE NOT There'
#submission = #members_question.submissions.create(params[:submission].permit(:question_id))
#submission.content = "Incorrect"
#submission.member_id = current_member.id
end
def set_user_submission
#members_question = Submission.find(params[:content])
end
The user_submitted_answer :content is not being passed from the form in the "Questions/Show" into the submissions controller?
Am I doing this wrong, approaching it wrong or is there a rails method that I can use that is more efficient and works to achieve what I need?
My current code, Always returns false and the users_input is not being inserted into the database.
From what I see, you are creating the submission in either of the cases, then assigning the content and member id and not saving it.
Keep in mind that create method initializes the object and also saves it after which any values you assign needs to be saved again. So I have tweaked your code as follows where the submission object is initialized then you add the content and member_id and atlast you save it.
if #answer_check.present?
flash.alert = 'Answer There'
#submission = #members_question.submissions.new(params[:submission].permit(:question_id))
#submission.member_id = current_member.id
#submission.content = Submission.find_by(params[:content])
#submission.save
else
flash.alert = 'NOPE NOT There'
#submission = #members_question.submissions.new(params[:submission].permit(:question_id))
#submission.content = "Incorrect"
#submission.member_id = current_member.id
#submission.save
end
Hope this works and please upvote if deemed correct!
Cheers!
I have
class Clot < ActiveRecord::Base
has_many :memberships
has_many :users, through: :memberships
end
and same for users
I have follow button with action
def follow
#clot = Clot.find(params[:id])
#clot.users << current_user
redirect_to #clot
end
Its working fine but i want to create unfollow button
i wrote
= button_to 'unollow', unfollow_clot_path(#clot), :method => :delete
with
def unfollow
#clot.users.destroy
end
My routes looks like
resources :clots do
member do
post :follow
delete :unfollow
end
end
but i am getting error. please tell me answer and also tell me right way if i am doing it wrong.
Thanks in advance
When you say this, it will call controller method unfollow, and in params will pass clot id. So you have to find that clot object with that id
= button_to 'unollow', unfollow_clot_path(#clot), :method => :delete
def method_name
#clot = Clot.find(params[:id])
end
But When you will do
#clot.users
It will return array of user for that clot instance. And you can't call destroy method on array object. So first will return you the first found object,So you can write like
#clot.users.first.destory!
Or you can also use destory_all method. To destroy all objects
I am attempting to locate a parent object in a nested controller, so that I can associate the descendant resource with the parent like so:
# teams_controller.rb <snippet only>
def index
#university = Univeresity.find(params[:university_id])
#teams = #university.teams
end
When I call find(params[:university_id]) per the snippet above & in line 6 of teams_controller.rb, I receive ActiveRecord::RecordNotFound - Couldn't find University without an ID.
I'm not only interested in fixing this issue, but would also enjoy a better understanding of finding objects without having to enter a University.find(1) value, since I grant Admin the privilege of adding universities.
The Rails Guides say the following about the two kinds of parameters in a website:
3 Parameters
You will probably want to access data sent in by the user or other
parameters in your controller actions. There are two kinds of
parameters possible in a web application. The first are parameters
that are sent as part of the URL, called query string parameters. The
query string is everything after “?” in the URL. The second type of
parameter is usually referred to as POST data. This information
usually comes from an HTML form which has been filled in by the user.
It’s called POST data because it can only be sent as part of an HTTP
POST request. Rails does not make any distinction between query string
parameters and POST parameters, and both are available in the params
hash in your controller:
It continues a little further down, explaining that the params hash is an instance of HashWithIndifferentAccess, which allows usage of both symbols and strings interchangeably for the keys.
From what I read above, my understanding is that Rails recognizes both parameters (URL & POST) and stores them in the same hash (params).
Can I pass the params hash into a find method in any controller action, or just the create/update actions? I'd also be interested in finding a readable/viewable resource to understand the update_attributes method thats called in a controller's 'update' action.
Please overlook the commented out code, as I am actively searching for answers as well.
Thanks in advance.
Here are the associated files and server log.
Webrick
teams_controller.rb
class TeamsController < ApplicationController
# before_filter :get_university
# before_filter :get_team
def index
#university = University.find(params[:univeristy_id])
#teams = #university.teams
end
def new
#university = University.find(params[:university_id])
#team = #university.teams.build
end
def create
#university = University.find(params[:university_id])
#team = #university.teams.build(params[:team])
if #team.save
redirect_to [#university, #team], success: 'Team created!'
else
render :new, error: 'There was an error processing your team'
end
end
def show
#university = University.find(params[:university_id])
#team = #university.teams.find(params[:id])
end
def edit
#university = University.find(params[:university_id])
#team = #university.teams.find(params[:id])
end
def update
#university = University.find(params[:university_id])
#team = #university.teams.find(params[:id])
if #team.update_attributes(params[:team])
redirect_to([#university, #team], success: 'Team successfully updated')
else
render(:edit, error: 'There was an error updating your team')
end
end
def destroy
#university = University.find(params[:university_id])
#team = #university.teams.find(params[:id])
#team.destroy
redirect_to university_teams_path(#university)
end
private
def get_university
#university = University.find(params[:university_id]) # can't find object without id
end
def get_team
#team = #university.teams.find(params[:id])
end
end
team.rb
class Team < ActiveRecord::Base
attr_accessible :name, :sport_type, :university_id
has_many :home_events, foreign_key: :home_team_id, class_name: 'Event'
has_many :away_events, foreign_key: :away_team_id, class_name: 'Event'
has_many :medias, as: :mediable
belongs_to :university
validates_presence_of :name, :sport_type
# scope :by_university, ->(university_id) { where(team_id: team_id).order(name: name) }
# scope :find_team, -> { Team.find_by id: id }
# scope :by_sport_type, ->(sport_type) { Team.where(sport_type: sport_type) }
# scope :with_university, joins: :teams
# def self.by_university(university_id)
# University.where(id: 1)
# University.joins(:teams).where(teams: { name: name })
# end
def self.by_university
University.where(university_id: university_id).first
end
def self.university_join
University.joins(:teams)
end
def self.by_sport_type(sport_type)
where(sport_type: sport_type)
end
def self.baseball
by_sport_type('Baseball/Softball')
end
end
university.rb
class University < ActiveRecord::Base
attr_accessible :address, :city, :name, :state, :url, :zip
has_many :teams, dependent: :destroy
validates :zip, presence: true, format: { with: /\A\d{5}(-\d+)?\z/ },
length: { minimum: 5 }
validates_presence_of :name, :address, :city, :state, :url
scope :universities, -> { University.order(name: 'ASC') }
# scope :by_teams, ->(university_id) { Team.find_by_university_id(university_id) }
# scope :team_by_university, ->(team_id) { where(team_id: team_id).order(name: name)}
def sport_type
team.sport_type
end
end
views/teams/index.html.erb
Placed in gists for formatting reasons
rake routes output: (in a public gist)
enter link description here
rails console
You're not going to want to have both:
resources :universities #lose this one
resources :universities do
resources :teams
end
As for params... you have to give a param. So, when you go to http://localhost:3000/teams there are no params, by default. If you go to http://localhost:3000/teams/3 then params[:id] = 3 and this will pull up your third team.
Keep in mind the nomenclature of an index. The index action of Teams, is going to list all of the teams. All of them. There is no one University there, so what are you actually trying to find? If anything, you'd have, for your University controller:
def show
#university = University.find(params[:id])
#teams = #university.teams
end
so, the address bar will be showing http://localhost:3000/universities/23, right? params[:id] = 23, then you can find the teams associated with that university.
I've been building messaging in a rails app for users to be able to send each other messages. I've looked at a few gems such as mailboxer but ultimately decided to build my own.
I'm hoping someone can help me put these pieces together. I've been following a similar question's answer here.
I'm testing in the rails console and I keep getting the following error:
undefined method `send_message' for #
How can I fix this?
Controller
class MessagesController < ApplicationController
# create a comment and bind it to an article and a user
def create
#user = User.find(params[:id])
#sender = current_user
#message = Message.send_message(#sender, #user)
flash[:success] = "Message Sent."
flash[:failure] = "There was an error saving your comment (empty comment or comment way to long)"
end
end
Routes
resources :users, :except => [ :create, :new ] do
resources :store
resources :messages, :only => [:create, :destroy]
end
Messages Model
class Message < ActiveRecord::Base
belongs_to :user
scope :sent, where(:sent => true)
scope :received, where(:sent => false)
def send_message(from, recipients)
recipients.each do |recipient|
msg = self.clone
msg.sent = false
msg.user_id = recipient
msg.save
end
self.update_attributes :user_id => from.id, :sent => true
end
end
You are invoking the method on a class level: Message.send_message. For this to work, it would expect a declaration like this:
def self.send_message(from, recipients)
# ...
end
But, you got this instead:
def send_message(from, recipients)
# ...
end
So, either invoke the method on the instance you need it for, or refactor to make it work on a class level.