Form Helper Undefined Method - ruby-on-rails

When I try to access the view, an error is returned:
undefined method 'title' for #Task id: nil, created_at: nil, updated_at: nil
tasks_controller.rb (Controller)
class TasksController < ApplicationController
def new
#task = Task.new
end
def create
#task = Task.new(params[:task])
if #task.save
redirect_to new_task_path
end
end
end
/tasks/new.html.erb (View)
<%= form_for :task, url: tasks_path do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :details %><br>
<%= f.text_area :details %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
task.rb (Model)
class Task < ActiveRecord::Base
belongs_to :user
attr_accessible :title, :details, :user_id, :volunteers
end
What should I do?

You have not defined fields in your database, see:
#Task id: nil, created_at: nil, updated_at: nil
There is no title nor details there, do this:
rails g migration add_title_and_details_to_tasks title details
Check that your migration file is correctly creating these 2 fields.
Then run rake db:migrate. Next time remember to generate your resource with these fields:
rails g scaffold Task title details
This way, when you migrate your fields will be there.

It looks like you have pending migration(s) (do you have title in your schema.rb).
other note: build your form for #task

Related

Unpermitted parameter: ROR

I am new in ror and when I submit my form:
<%= form_for :project, url: projects_path, html: {id:'form'} do |f| %>
<%= f.text_field :text, placeholder: 'Новая задача' %>
<%= link_to 'Отмена', '', id:'cancel_link' %>
<%= link_to 'Отправить', projects_path, id:'submit_link' %>
<% end %>
Have error:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OR2HWCi3zVz9gB5VAmnzbEuzIwFGE58JlLrWQdNcws6FVTzqh5Cu0zvUJTUEv2O/sCvU9HuadJYr3mfA40ehGA==", "project"=>{"text"=>"NEW ITEM"}} Unpermitted parameter: :text
Have two models:
class Project < ApplicationRecord
has_many :todos
validates :title, presence: true
accepts_nested_attributes_for :todos
end
class Todo < ApplicationRecord
belongs_to :project, required: false
end
The Todo model has a text attribute in which our todo should be located
Controller
class ProjectsController < ApplicationController
def index
#projects = Project.all
end
def create
#project = Project.new(project_params)
if #project.save
redirect_to root_path
end
end
def update
end
private
def project_params
params.require(:project).permit(:title, todos_attributes: [:id, :text])
end
end
Project db
class CreateProjects < ActiveRecord::Migration[5.2]
def change
create_table :projects do |t|
t.string :title
t.string :todos
t.timestamps
end
Todo db
class CreateTodos < ActiveRecord::Migration[5.2]
def change
create_table :todos do |t|
t.text :text
t.boolean :isCompleted
t.integer :project_id
t.timestamps
end
I'm requesting the todo attributes using accepts_nested_attributes_for: todos, the controller is also registered on the guides, in project_params I request todos_attributes. But when sending a form to the database, the value is text. He does not save in db. Can u help please
In order to save text field in Todo model, you have to create nested form. Use nested_form gem for this purpose.
A vague example to show how it works:
<%= nested_form_for :project, url: projects_path, html: { id: 'form' } do |f| %>
<%= f.text_field :title, placeholder: 'Новая задача' %>
<%= f.fields_for :todos do |todo_form| %>
<%= todo_form.text_field :text %>
<%= todo_form.link_to_remove "Remove this todo" %>
<% end %>
<p><%= f.link_to_add "Add a todo", :todos %></p>
<%= link_to 'Отмена', '', id:'cancel_link' %>
<%= link_to 'Отправить', projects_path, id:'submit_link' %>
<% end %>
In controller, to have the functionality of removing a todo in case of editing a project:
def project_params
params.require(:project).permit(:title, todos_attributes: [:id, :text, _destroy])
end
In the migration CreateProjects < ActiveRecord::Migration[5.2], I do not think that you require todos as a string.
The form which you created is wrong, you need to create a nestead_form
It is giving you and Unpermitted parameter error because the text is not a field of project model you can check this on your migration file. You need to change it to title because the title is the field of project model.
And for to create a nested form you need to do some changes in your form
<%= form_for :project, url: projects_path, html: {id:'form'} do |f| %>
<%= f.text_field :title, placeholder: 'Новая задача' %>
<%= f.fields_for :todos do |todo| %>
<%= f.text_field :text %>
<% end %>
<%= link_to 'Отмена', '', id:'cancel_link' %>
<%= link_to 'Отправить', projects_path, id:'submit_link' %>
<% end %>

Building survey from railscast in rails 5

I have been following both the old and revised railscasts & this for something that i have to make along the same lines
I followed it upto some point but neither are the questions being displayed on the form nor are the answers getting added . Following is my model code
answers.rb
class Answer < ActiveRecord::Base
attr_accessor :content, :question_id
belongs_to :question
end
surveys.rb
class Survey < ApplicationRecord
attr_accessor :name, :questions_attributes
has_many :questions
accepts_nested_attributes_for :questions, allow_destroy: true
end
questions.rb
class Question < ApplicationRecord
attr_accessor :content, :survey_id, :answers_attributes
belongs_to :survey
has_many :answers
accepts_nested_attributes_for :answers, allow_destroy: true
end
Surveys Controller
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :edit, :update, :destroy]
# GET /surveys
# GET /surveys.json
def index
#surveys = Survey.all
end
# GET /surveys/1
# GET /surveys/1.json
def show
end
# GET /surveys/new
def new
#survey = Survey.new
3.times do
question = #survey.questions.build
4.times { question.answers.build }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_survey
#survey = Survey.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def survey_params
params.require(:survey).permit(:name, :question_id)
end
end
Views
_form.html.erb
<%= f.fields_for :questions do |builder| %>
<%= render 'question_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Add Question", f, :questions %>
_question_fields.html.erb
<fieldset>
<%= f.label :content, "Question" %><br />
<%= f.text_area :content %><br />
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Question" %>
<%= f.fields_for :answers do |builder| %>
<%= render 'answer_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Add Answer", f, :answers %>
</fieldset>
_answers_fields.html.erb
<p>
<%= f.label :content, "Answer" %>
<%= f.text_field :content %>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove" %>
</p>
show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #survey.name %>
</p>
<ol>
<% for question in #survey.questions %>
<li><%= h question.content %></li>
<% end %>
</ol>
<p>
<%= link_to "Edit", edit_survey_path(#survey) %> |
<%= link_to "Destroy", #survey, :confirm => 'Are you sure?', :method => :delete %> |
<%= link_to "View All", surveys_path %>
</p>
Migrations
class CreateSurveys < ActiveRecord::Migration[5.0]
def change
create_table :surveys do |t|
t.string :name
t.timestamps
end
end
end
class CreateQuestions < ActiveRecord::Migration[5.0]
def change
create_table :questions do |t|
t.string :survey_id
t.string :integer
t.text :content
t.timestamps
end
end
end
Is there anything else i am missing out that needs to be done in rails 5 , i have been hours at this and it still confuses me why does it show me this error - Table 'app.answers' doesn't exist when i am calling answers from nested form . Any help in this regard would be very much appreciated .
The main issue here is it looks like you forgot an 'answer' migration to create the tables, create that and run it and should fix things up.
Additionally, those attr_accessor calls are going to be messing things up. They were required in older versions of Rails, but aren't anymore and now just serve throw things off. Example
With attr_accessor code
post = Post.new(title: "Something")
#=> #<Post id: nil, title: nil, created_at: nil, updated_at: nil>
post.title = "Something"
#=> "Something"
puts post
#=> #<Post id: nil, title: nil, created_at: nil, updated_at: nil>
Without
post = Post.new(title: "Something")
#=> #<Post id: nil, title: "Something", created_at: nil, updated_at: nil>
post.title = "Something Else"
#=> "Something Else"
puts post
#=> #<Post id: nil, title: "Something Else", created_at: nil, updated_at: nil>
As you can see, the first block, where my Post model had the attr_accessor for the title attribute, nothing was working as expected; I couldn't update the title. Once I removed it, things started to work as they should.
Based on the chat discussion, your _form.html.erb is missing form_for tag, and should looks something like
<%= form_for #survey do |f| %>
<%= f.label :name %><br />
<%= f.text_field :name %>
<!-- your current code here -->
<% end %>
you've got _answers_field.html.erb and in _question_fields.html.erb are calling
<%= render 'answer_fields', f: builder %>
Notice, the plural/singular mismatch.
and lastly, in your controller, you aren't permitting the nested attribute params which should end up looking like (unless I'm mistaken)
def survey_params
params.require(:survey).permit(:name, :question_attributes: [:id, :content, :_destroy, answer_attributes: [:id, :content, :_destroy])
end
Last couple of issues from chat were that the associations needed inverse_of because belongs_to is required by default in rails 5. And the last minor thing is that Answer is currently inheriting ActiveRecord::Base and the other models ApplicationRecord

ActionController::ParameterMissing

I have made an application that has a personsController class, with an action show and new. I also created the Person model this way:
rails generate model Person name:string surname:string partner:references
The partner field should reference another person. In the new action I created a form to insert a new person into the database:
<%= form_for :person , url: persons_path do |f| %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :surname %>
<%= f.text_field :surname %>
</p>
<p>
<%= f.label :partner %>
<%= f.number_field :partner , value: 0 %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
This is the personsController method create:
def create
#person= Person.new(post_params)
#Person.save
redirect_to #person
private
def post_params
params.require(:post).permit(:partner,:name,:surname);
end
The problem is that I get an error when I submit the form:
Update
I changed the instruction to:
params.require(:person).permit(:partner,:name,:surname);
But I still get an error:
NameError in PersonsController#create
uninitialized constant Person::Partner
Person model:
class Person < ActiveRecord::Base
belongs_to :partner
end
This is the problem here:
From your model post is not a defined attribute
so changed this:
def post_params
params.require(:post).permit(:partner,:name,:surname);
end
to
def post_params
params.require(:person).permit(:partner_id,:name,:surname)
end
EDIT
use partner_id instead of partner for your foreign key
<p>
<%= f.label :partner %>
<%= f.number_field :partner_id, value: 0 %>
</p>
Require person:
params.require(:person).permit(:partner, :name, :surname)

Working in install acts_as_commentable, On create, error: "unknown attribute: book_id"

I'm working to install the acts_as_commentable plugin on my
Rails 3 app.
After adding "acts_as_commentable" to my book model, I then added a
comment form on my book show view:
<% form_for(#comment) do|f| %>
<%= f.hidden_field :book_id %>
<%= f.label :comment %><br />
<%= f.text_area :comment %>
<%= f.submit "Post Comment" %>
<% end %>
Then in the controller (comments_controller.rb),
def create
#comment = Comment.new(params[:comment])
Book.comments.create(:title => "First comment.", :comment => "This
is the first comment.")
end
Then when submitting a comment, it returns the error: "unknown
attribute: book_id"
From the log:
Processing by CommentsController#create as HTML
Parameters: {"comment"=>{"comment"=>"WOOOW", "book_id"=>"32"},
"commit"=>"Post Comment",
"authenticity_token"=>"5YbtEMpoQL1e9coAIJBOm0WD55vB2XRZMJa4MMAR1YI=",
"utf8"=>"✓"}
Completed in 11ms
ActiveRecord::UnknownAttributeError (unknown attribute: book_id):
app/controllers/comments_controller.rb:3:in `new'
app/controllers/comments_controller.rb:3:in `create'
Suggestions?
<%= f.hidden_field :book_id %>
It means your Comment model has no book_id field.
Also, it's not a very good idea to call a field as the model name (comment). Use body (or message) instead of comment for the field which should contains the message body.
I think you have to options:
Option 1)
The view:
<% form_for(#comment) do|f| %>
<%= f.hidden_field :commentable_id, :value => #book.id %>
<%= f.hidden_field :commentable_type, :value => 'Book' %>
<%= f.label :comment %><br />
<%= f.text_area :comment %>
<%= f.submit "Post Comment" %>
<% end %>
The controller:
def create
#comment = Comment.create(params[:comment])
end
Option 2)
In the controller:
def create
#book = Book.find(params[:comment][:book_id])
#comment = #book.comments.create(params[:comment].except([:comment][:book_id]))
end
I haven't tested the code, but the idea should be correct
Update, given you want to comment on various models (i'm writting my code without testing it...). So let's say you have Book and Magazine, and you want to comment on them. I guess I would define nested routes for them.
map.resources :books, :has_many => :comments
map.resources :magazines, :has_many => :comments
And then in your controller you could do:
before_filter :find_commentable
def find_commentable
#commentable = Book.find(params[:book_id]) if params[:book_id]
#commentable = Magazine.find(params[:magazine_id]) if params[:magazine_id]
end
And in the new view:
<% form_for :comment, [#commentable, #comment] do |f| %>
<%= f.label :comment %>
<%= f.text_area :comment %>
<%= f.submit %>
<% end %>
So the create action could look something like:
def create
#user.comments.create(params[:comment].merge(:commentable_id => #commentable.id, :commentable_type => #commentable.class.name))
redirect_to #commentable
end
Maybe there are even better ways to do it...

NoMethodError in basic scaffolded View?

I created a basic scaffold for a Foo model with a single property - bar:String
foos/new.html.erb:
<h1>New foo</h1>
<% form_for(#foo) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :bar %><br />
<%= f.text_field :bar %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', foos_path %>
But I get a NoMethodError for my 'bar' property:
NoMethodError in Foos#new
Showing app/views/foos/new.html.erb where line #8 raised:
undefined method `bar' for #<Foo id: nil, created_at: nil, updated_at: nil>
Extracted source (around line #8):
5:
6: <p>
7: <%= f.label :bar %><br />
8: <%= f.text_field :bar %>
9: </p>
10: <p>
11: <%= f.submit 'Create' %>
As you can see, bar the only property in my Foo model:
class CreateFoos < ActiveRecord::Migration
def self.up
create_table :foos do |t|
t.String :bar
t.timestamps
end
end
def self.down
drop_table :foos
end
end
And the new method in the foos_controller is from the default scaffold:
def new
#foo = Foo.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #foo }
end
end
Any ideas would be appreciated
It would seem you capitalized the word String in your db migration. Try it with a lower case s and force the migration to run again (rake db:migrate:redo, assuming that this was your latest migration, otherwise use
rake db:migrate:down VERSION=29843923 && rake db:migrate:up VERSION=29843923
where 29843923 is your migration timestamp.).
Did you executed your migration?

Resources