undefined method `model_name_question' for #..Rails 4 - ruby-on-rails

I am getting this error after submitting the form:(in the index page)
<%= simple_form_for(#quiz, html: {class: 'form-vertical' }) do |f| %>
<%= render 'shared/error_messages_question' %>
<%= f.input_field :content, :rows => 3, :style => "width:80%", :placeholder => "enter your question." %>
<%= f.button :submit %>
<% end %>
I have question model:
class Question < ActiveRecord::Base
validates :question, presence: true
belongs_to :category
belongs_to :questioner
end
and questions controller:
class QuestionsController < ApplicationController
def index
#quiz = Question.new
#questioner = Questioner.new
end
def new
#quiz = Question.new(quiz_params)
end
def show
#quiz = Question.find(params[:id])
end
def edit
#quiz = find(params[:id])
raise "Question Not edited!" unless #quiz
end
def create
#quiz = Question.new(quiz_params)
if #quiz.save
flash[:success] = 'You have successfully posted the questions!'
redirect_to questions_path
else
flash[:error] = "Please review the problems below."
# render 'new'
redirect_to questions_path
end
end
private
def quiz_params
params.require(:question).permit(:content, :answered, :questioner_id, :category_id)
end
end
what could b the problem?
in the rails server I have this:
Completed 500 Internal Server Error in 5ms
NoMethodError - undefined method `question' for #<Question:0x0000000433dfc0>:
activemodel (4.0.2) lib/active_model/attribute_methods.rb:439:in `method_missing'

The issue may potentially be related to this validation line
validates :question, presence: true
It assumes your Question model has a :question attribute. In other words, makes sure there is a proper question database column in the questions database table.
If this is not the case, fix the either the table or the validation accordingly.

Related

Trying to save to Parent and child tables in Rails, but get argument error on nested Attributes

Hi I am trying to save to two tables at the same time from one form.
I have created Contact with a has_many relationship to Order which belongs_to Contact.
models/contact.rb
class Contact < ActiveRecord::Base
has_many :orders
accepts_nested_attributes_for :orders, reject_if: :all_blank
end
models/order.rb
class Order < ActiveRecord::Base
belongs_to :contact
end
I have also created the OrdersController which looks as follows
controllers/OrdersController.rb
class OrdersController < ApplicationController
def new
#contact = Contact.new
#contact.orders.build
end
def create
#contact = Contact.new(order_params)
if #contact.save
#order = #contact.orders.build(order_params)
#order.save
flash[:success] = "Your has been sent we'll get back to you shortly"
redirect_to new_order_path
else
flash[:danger] = "We were unable to process your request please try again or email admin#careerfalir.co.za"
redirect_to new_order_path
end
end
. . .
private
def order_params
params.require(:contact).permit(:id,:name,:surname, :email, :comments, :dob, :phone_number, :contact_method, orders_attributes: [:email, :contact_id,:package,:jobs_strategy,:fast_turn_around,:order_comments, :contact_email])
end
end
When I try and create and an order I get an error unknown attribute: name
#contact = Contact.new(order_params)
if #contact.save
*** #order = #contact.orders.build(order_params) *** This is the line with the error
#ordar.save
flash[:success] = "Your has been sent we'll get back to you shortly"
redirect_to new_order_path
Name does not exist in the Orders table which why I assume it is complaining, but it does exist in the Contacts table. Should I be creating this differently?
I have also tried #order = #contact.orders.create(order_params) with the same error.
Here is an sample of the view
<%= form_for #contact, url: orders_path do |f| %>
<div>
<%= f.label :name %>
<%= f.text_field :name, class:"form-control" %>
</div>
<div>
.....
<%= f.fields_for :order do |order| %>
<div>
<%= order.label :package %>
<%= order.text_field :package, class: "form-control" %>
</div>
1) First point is the create method has #ordar.save instead of #order.save which I am assuming as Typo
2) The second point is #order = #contact.orders.build(order_params) this line does not require order_params and should be simply #order = #contact.orders.build
So with those changes your create action should be,
def create
#contact = Contact.new(order_params)
if #contact.save
flash[:success] = "Your has been sent we'll get back to you shortly"
redirect_to new_order_path
else
flash[:danger] = "We were unable to process your request please try again or email admin#careerfalir.co.za"
redirect_to new_order_path
end
end

ActiveRecord::RecordNotFound: Couldn't find Answer with ID=5 for Application with ID=

I have a nested form, and am having trouble getting the create and update function to work.
I think what's happening is that the nested object is being created first, and is causing an error.
I get this error when trying to run the create action:
ActiveRecord::RecordNotFound in ApplicationsController#create
Couldn't find Answer with ID=5 for Application with ID=
Rails.root: /Users/stepan/Desktop/Sites/atlas
Application Trace | Framework Trace | Full Trace
app/controllers/applications_controller.rb:22:in `create'
This only happened after I allowed the :id parameter for the answers model. The reason I did that was to make it possible for the update action to work.
This is what my Controller Looks like ->
class ApplicationsController < ApplicationController
def new
#job = Job.find(params[:job_id])
#user = current_user
#application = Application.new()
#job.questions.count.times do
#application.answers.build
end
end
def create
#user = current_user
#job = Job.find(params[:job_id])
#application = Application.new(application_params)
#application.job_id = #job.id
if #application.save
redirect_to root_url, :notice => "You have now applied!"
else
render :action => 'new'
end
end
def edit
#job = Job.find(params[:job_id])
#user = current_user
#application = Application.find(params[:id])
#answers = []
#job.questions.each do |question|
#application.answers.each do |answer|
#answers << answer if answer.question_id == question.id
end
end
end
def update
#job = Job.find(params[:job_id])
#user = current_user
#application = Application.find(params[:id])
if #application.update_attributes(application_params)
redirect_to root_url, :notice => "You have updated your application!"
else
render :action => 'new'
end
end
def destroy
Application.find(params[:id]).destroy
flash[:success] = "Application Deleted."
redirect_to root_url
end
def show
#job = Job.find(params[:job_id])
#user = current_user
#application = Application.find(params[:id])
#answers = []
#job.questions.each do |question|
#application.answers.each do |answer|
#answers << answer if answer.question_id == question.id
end
end
end
private
def application_params
params.require(:application).permit(:id, :job_id, :user_id, answers_attributes:[:content, :question_id, :id]).merge(user_id: current_user.id)
end
end
This is the form:
<% provide(:title, " Apply to this job") %>
<div class="row">
<div class="span6">
<h2> Job: <%= #job.job_title %></h2>
<p> <%= #job.job_summary %> </p>
</div>
<div class="span6">
<h2> Applicant: <%= #user.name %></h2>
</div>
<div class="span12">
<h3>You're almost done! Answer the questions below and you'll be applied to the job.</h3>
</div>
</div>
<%= form_for [#job, #application] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<% #job.questions.each_with_index do |question| %>
<%= f.fields_for :answers, question do |question_field| %>
<%= question_field.label :content, question.content %>
<%= question_field.text_area :content, :value => "" %>
<%= question_field.hidden_field :question_id, :value => question.id %>
<% end %>
<% end %>
<%= f.submit "Submit the application", class: "button" %>
<% end %>
This is my Application Model:
# == Schema Information
#
# Table name: applications
#
# id :integer not null, primary key
# user_id :integer
# job_id :integer
# created_at :datetime
# updated_at :datetime
#
class Application < ActiveRecord::Base
belongs_to :job
belongs_to :user
validates :job_id, presence: true
validates :user_id, presence: true
has_many :answers
accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
This is my answer model:
# == Schema Information
#
# Table name: answers
#
# id :integer not null, primary key
# application_id :integer
# question_id :integer
# created_at :datetime
# updated_at :datetime
# content :string(255)
#
class Answer < ActiveRecord::Base
belongs_to :question
belongs_to :application
validates :content, presence: true
end
There was a similar problem here --> Rails 4 Nested Attributes Unpermitted Parameters, But I don't quite understand what the answer is doing.
Help much appreciated!
Some issues you may benefit from looking into:
Application Create
Bluntly, I think you're trying to do too much with the application create function
There's a principle in Rails (and all MVC) called fat model skinny controller, meaning you should put as many actions into the model as possible. The controller really just needs to guide logic (call respective methods depending on model responses). Here's what I'd do:
#app/controllers/applications_controller.rb
before_filter :set_user
def new
job_id = params[:job_id]
#application = Application.build(job_id)
end
def create
#application = Application.new(application_params)
#application.save
redirect_to root_url, :notice => "You have now applied!"
end
private
def set_user
#user = current_user
end
def application_params
params.require(:application).permit(:job_id, :user_id, answers_attributes:[:question_id, :content]).merge(user_id: current_user.id, job_id: params[:job_id])
end
#app/models/application.rb
Class Application < ActiveRecord::Base
#Associations here
accepts_nested_attributes_for :answers
validates :title, :other_application_vars,
presence: true #-> shows errors if validation fails (no need for "if #application.save" logic.... needs testing)
def self.build(job_id) #-> class method -- not sure about passing arguments
application = self.new
job = Job.find(job.id)
job.questions.count.times do
application.answers.build
end
application
end
end
#app/models/answer.rb
Class Answer < ActiveRecord::Base
validates :question_id, :content,
presence: true
end
Strong Params
You mentioned it will only allow you to do this if you send the id param through. I don't have a super amount of experience here, but I've found you don't need to send the :id param through strong params. This is probably what's causing the issue - you're not setting the id param, and consequently it's getting confused
If you adopt a conventional way of doing this, you shouldn't have this error

Absolutely stuck trying to create nested association in rails form with has_many through

I posted an earlier question about this and was advised to read lots of relevant info. I have read it and tried implementing about 30 different solutions. None of which have worked for me.
Here's what I've got.
I have a Miniatures model.
I have a Manufacturers model.
Miniatures have many manufacturers THROUGH a Productions model.
The associations seem to be set up correctly as I can show them in my views and create them via the console. Where I have a problem is in letting the Miniatures NEW and EDIT views create and update to the Productions table.
In the console the command #miniature.productions.create(manufacturer_id: 1) works, which leads me to believe I should be able to do the same in a form.
I THINK my problem is always in the Miniatures Controller and specifically the CREATE function. I have tried out a ton of other peoples solutions there and none have done the trick. It is also possible that my field_for stuff in my form is wrong but that seems less fiddly.
I've been stuck on this for days and while there are other things I could work on, if this association isn't possible then I'd need to rethink my entire application.
The form now creates a line in the Productions table but doesn't include the all important manufacturer_id.
Any help VERY much appreciated.
My New Miniature form
<% provide(:title, 'Add miniature') %>
<h1>Add a miniature</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#miniature) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.fields_for :production do |production_fields| %>
<%= production_fields.label :manufacturer_id, "Manufacturer" %>
<%= production_fields.select :manufacturer_id, options_from_collection_for_select(Manufacturer.all, :id, :name) %>
<% end %>
<%= f.label :release_date %>
<%= f.date_select :release_date, :start_year => Date.current.year, :end_year => 1970, :include_blank => true %>
<%= f.submit "Add miniature", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
Miniatures controller
class MiniaturesController < ApplicationController
before_action :signed_in_user, only: [:new, :create, :edit, :update]
before_action :admin_user, only: :destroy
def productions
#production = #miniature.productions
end
def show
#miniature = Miniature.find(params[:id])
end
def new
#miniature = Miniature.new
end
def edit
#miniature = Miniature.find(params[:id])
end
def update
#miniature = Miniature.find(params[:id])
if #miniature.update_attributes(miniature_params)
flash[:success] = "Miniature updated"
redirect_to #miniature
else
render 'edit'
end
end
def index
#miniatures = Miniature.paginate(page: params[:page])
end
def create
#miniature = Miniature.new(miniature_params)
if #miniature.save
#production = #miniature.productions.create
redirect_to #miniature
else
render 'new'
end
end
def destroy
Miniature.find(params[:id]).destroy
flash[:success] = "Miniature destroyed."
redirect_to miniatures_url
end
private
def miniature_params
params.require(:miniature).permit(:name, :release_date, :material, :scale, :production, :production_attributes)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
end
Miniature model
class Miniature < ActiveRecord::Base
has_many :productions, dependent: :destroy
has_many :manufacturers, :through => :productions
accepts_nested_attributes_for :productions
validates :name, presence: true, length: { maximum: 50 }
validates :material, presence: true
validates :scale, presence: true
validates_date :release_date, :allow_blank => true
def name=(s)
super s.titleize
end
end
Production model
class Production < ActiveRecord::Base
belongs_to :miniature
belongs_to :manufacturer
end
Manufacturer model
class Manufacturer < ActiveRecord::Base
has_many :productions
has_many :miniatures, :through => :productions
validates :name, presence: true, length: { maximum: 50 }
accepts_nested_attributes_for :productions
end
Instead of calling:
#production = #miniature.productions.create
Try Rails' "build" method:
def new
#miniature = Miniature.new(miniature_params)
#miniature.productions.build
end
def create
#miniature = Miniature.new(miniature_params)
if #miniature.save
redirect_to #miniature
else
render 'new'
end
end
Using the build method uses ActiveRecord's Autosave Association functionality.
See http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
You also need to update your params method, e.g.
def miniature_params
params.require(:miniature).permit(:name, :release_date, :material, :scale, productions_attributes: [:manufacturer_id])
end
Also your fields_for should be plural (I think)...
<%= f.fields_for :productions do |production_fields| %>

Rails: Form inputs not saving after submit

why wont anything entered into this form save?
new.html.erb
<%= form_for [#requestable, #request] do |f| %>
<%= f.label :status %>
<%= f.text_field :status, rows: 8 %>
<%= f.submit "Request", :class => 'btn'%>
<% end %>
requests_controller.rb
class RequestsController < ApplicationController
before_filter :load_requestable
def index
#requests = #requestable.requests
end
def new
#request = #requestable.requests.new
end
def create
#request = #requestable.requests.new(params[:status])
if #request.save
redirect_to [#requestable, :requests], notice: "Request sent."
else
render :new
end
end
private
def load_requestable
klass = [Company, Profile].detect { |c| params["#{c.name.underscore}_id"]}
#requestable = klass.find(params["#{klass.name.underscore}_id"])
end
end
my controller is based on this
https://github.com/railscasts/154-polymorphic-association-revised/blob/master/blog-after/app/controllers/comments_controller.rb
request.rb
class Request < ActiveRecord::Base
attr_accessible :status
belongs_to :requestable , polymorphic: true
belongs_to :profile
validates :status, presence: true
end
This is being produced by my debuger
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
utf8: ✓
authenticity_token: /0H2k89HN4JVXBPsoFWen5rUfx2xr4p5hr1uDSQVlcA=
request: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
status: pending
commit: Request
action: create
controller: requests
company_id: '1'
Take a look at what's in your params hash. The status field is probably in something like params[:request][:status]. Assuming standard activerecord-y stuff, you want to pass the hash for the whole request object to .new.

Rails validations not working with habtm

for now i've got followings:
model => User (name, email)
has_and_belongs_to_many :trips
model => Trip (dest1, dest2)
has_and_belongs_to_many :users
validates :dest1, :dest2, :presence => true
model => TripsUsers (user_id, trip_id) (id => false)
belongs_to :user
belongs_to :trip
As you see from the code, trip model has validation on dest1, and dest2, but it's not showing up an errors. Controller and view defined as follow:
trips_controller.rb
def new
#user = User.find(params[:user_id])
#trip = #user.trips.build
end
def create
#user = User.find(params[:user_id])
#trip = Trip.new(params[:trip])
if #trip.save
#trip.users << #user
redirect_to user_trips_path, notice: "Success"
else
render :new
end
end
_form.html.erb
<%= simple_form_for [#user, #trip] do |f| %>
<%= f.error_notification %>
<%= f.input :dest1 %>
<%= f.input :dest2 %>
<%= f.submit "Submit" %>
<% end %>
According to the rails guide on presence validation, it can't be used with associated objects. Try to use a custom validation:
validate :destinations_presence
def destinations_presence
if dest1.nil?
errors.add(:dest1, "missing dest1")
elsif dest2.nil?
errors.add(:dest1, "missing dest2")
end
end

Resources