Rails update ActiveRecord from a form - ruby-on-rails

Im working on a simple app here that needs a settings page since I am new to rails I am a little lost here. I would like to get it setup in a database with one column as a key and one column as the value. I already have a few things setup here but I am having trouble getting my forms to update the settings working.
All I want to do is have a single settings page with multiple settings that can be changed in it. for now all settings are going to be text fields. With my current code im getting the error "undefined method `to_key' for #". so here is some code:
model: setting.rb
class Setting < ActiveRecord::Base
def self.method_missing(method_name, *args, &block)
if method_name[-1] == '='
handle_set_setting method_name.to_s.delete("="), args.first
else
handle_get_setting method_name
end
end
private
def self.handle_get_setting(name)
if setting = Setting.find_by(key: name.to_s)
setting.value unless setting.value.empty?
else
nil
end
end
def self.handle_set_setting(name, value)
if setting = Setting.find_or_create_by(key: name.to_s)
setting if setting.update(value: value.to_s)
end
end
end
Here is my settings_controller.rb (Im 100% sure I dont have much correct in here.)
class SettingsController < ApplicationController
before_action :set_settings, only: [:edit, :update, :show]
def index
#settings = Setting.all
end
def new
#settings = Setting.new
end
def update
#settings.update(params)
end
private
def params
params.require(:key).permit(:value, :etc)
end
def set_settings
#settings = Setting.find params[:key]
end
end
and here is my index.html.erb (pretty sure this is all wrong)
<h2> Settings </h2>
<h3> Movie Settings </h3>
<%= form_for(#settings) do |f| %>
<%= f.hidden :key => "cp_api" %>
<%= f.label :value %><br>
<%= f.text_field :value %>
<%= f.submit %>
<% end %>
Here is the error log:
Started GET "/settings" for ::1 at 2015-09-18 00:57:24 -0400
Processing by SettingsController#index as HTML
Setting Load (0.1ms) SELECT "settings".* FROM "settings"
Rendered settings/index.html.erb within layouts/application (3.6ms)
Completed 500 Internal Server Error in 7ms (ActiveRecord: 0.1ms)
ActionView::Template::Error (undefined method `to_key' for # <Setting::ActiveRecord_Relation:0x007fa186b88128>):
1: <h2> Settings </h2>
2:
3: <h3> Settings </h3>
4: <%= form_for(#settings) do |f| %>
5: <%= f.hidden :key => "cp_api" %>
6: <%= f.label :value %><br>
7: <%= f.text_field :value %>
app/views/settings/index.html.erb:4:in `_app_views_settings_index_html_erb__4580226212883122031_70165864193720'
Im sure its something really easy to figure out, but I'm just really lost here, Ive been bashing my head for 2 days on this problem and I just cant seem to figure it out.
Thanks!

You need to add #setting = Setting.New to your index method like below
def index
#settings = Setting.all
#setting = Setting.new
end
and change <%= form_for(#settings) do |f| %> to <%= form_for(#setting) do |f| %>
Also you need to change your params method to below
def params
params.require(:setting).permit(:value, :key)
end
And change <%= f.hidden :key => "cp_api" %> to <%= f.hidden_field :key => "cp_api" %> to avoid further issues

Related

Wrong number of arguments error (0 for 1) in Ruby on Rails 4 when creating a form for user submission

at the moment I am attempting to create a form for my website that will allow for users to input information and then the information with be POST'ed to my database for storage. I am a new ruby on rails developer so keep that in mind.
I was able to get to the point where the user could see the form and type in information but once they hit the submit button I recieve an error, and that error is
ArgumentError in StudentsController#create
wrong number of arguments (0 for 1) in app/controllers/students_controller.rb:13:in `create'
The parameters that were sent were the following
{"utf8"=>"✓",
"authenticity_token"=>"bLalQ9Ek5ziaGiGHj03AGPCTIABAgcT+o4eTgN44qv44dxNDlrGA0h2u5BSTQVTMh+YgA/mLPQee05lT7mxCsw==",
"student"=>{"first_name"=>"Andrew",
"last_name"=>"Terra"},
"commit"=>"Submit"}
Below is my students_controller.rb file.
class StudentsController < ApplicationController
def index
#students = Student.all
end
def new
#student = Student.new
end
def create
#student = Student.new(params.require[:student])
if #student.save
redirect_to students_path
end
end
def destroy
#student = Student.find_by_id(params[:id])
if #student.destroy
redirect_to students_path
end
end
end
Below is my views/students/_form.html.erb file
<%= form_for #student do |f| %>
<p>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
</p>
<p>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
</p>
<%= f.submit "Submit" %>
<% end %>
Below is my /views/students/index.html.erb file
<%= link_to "Create new information", new_student_path %> <br /> <hr>
<% #students.each do |fo| %>
Firstname: <%= fo.first_name %> <br />
Lastname: <%= fo.last_name %> <br />
<%= link_to "Delete info?", student_path(student), :data=>{:confirm=>"Are you sure ?"}, :method=> :delete %>
<br />
<hr>
<% end %>
Finally, here is my /views/students/new.html.erb file
Enter new info
<hr>
<%= render :partial => "form" %>
And I did remember to put resources :students in my routes file. I searched around and found other people who had previously had this problem but none of the solutions worked on the code that I have written. So I was wondering if anyone could point me in the direction of where the bug is and how exactly I can fix it. Thank you.
You need to add a new private method:
private
def student_params
params.require(:student).permit(:first_name, :last_name)
end
And then as said before change your create method to:
def create
#student = Student.new(student_params)
if #student.save
redirect_to students_path
end
end
I recommend reading the documentation on Strong Parameters - to better understand how they work. https://github.com/rails/strong_parameters
You have to change
params.require[:students] to params.require(:students)
But this is still not good way to handle your params for create action, you should add private method student_params to your controller where you would whitelist your params. Like this:
def student_params
params.require(:student).permit(:first_name, :last_name)
end
Here you can find more about it,
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html

Error: param is missing or the value is empty: thing

I'm using rails 4.0.8. I added a comment section to a model called 'Things', but I keep getting the same error "param is missing or the value is empty: thing" when I press the submit comment button. It says the error is in the Things#Controller. What am I doing wrong?
UPDATE: I removed the url path from the form, but a new error returns "Couldn't find Thing without an ID". The error is in Comments#Controller.
VIEW FOR THING/SHOW
<div id= "thing">
<h1>
<%= #thing.name %>
</h1>
<br>
<div id= "commentsection">
Comments
<div id= "comments">
<br>
<% #thing.comments.each do |c| %>
<%= c.username %>
<br>
<%= c.text %>
<% end %>
<%= form_for #comment, :url => thing_path do |f| %>
<%= f.label :username %>
<%= f.text_field :username %>
<%= f.label :comment %>
<%= f.text_field :text %>
<%= f.submit "Enter", class: "btn btn-small btn-primary" %>
<% end %>
</div>
</div>
</div>
THINGS CONTROLLER
class ThingsController < ApplicationController
def show
#thing = Thing.find(params[:id])
#thing.comments.build
#comment = Comment.new
end
def index
end
def new
#thing = Thing.new
#things = Thing.all
end
def create
#thing = Thing.new(thing_params)
if #thing.save
redirect_to #thing
else
render 'new'
end
end
private
def thing_params
params.require(:thing).permit(:name, :avatar)
end
end
COMMENTS CONTROLLER (I put asterisks around the line where the error is)
class CommentsController < ApplicationController
def show
#comment = Comment.find(params[:id])
end
def new
#comment = Comment.new
#comments = Comment.all
end
def create
****#thing = Thing.find(params[:thing_id])****
#comment = #thing.comments.create(comment_params)
redirect_to thing_path(#thing)
end
end
private
def comment_params
params.require(:comment).permit(:user, :text, :upvotes, :downvotes, :thing_id)
end
end
ROUTES
Website::Application.routes.draw do
get "comments/new"
get "comments/show"
get "things/new"
root 'home_page#home'
get "all/things/new" => 'things#new'
get "all/allthings"
resources :things
resources :good_comments
get "things/show"
get "things/results"
end
You are posting the #comment form to post '/things' path.
<%= form_for #comment, :url => thing_path do |f| %>
It should just be <%= form_for #comment do %> (Rails is smart enough to plug in the comments_path) or if you feel like being more explicit (even though it's not necessary)
<%= form_for #comment, url: :comments_path do %>
Another note though, if you want that Comment to be tied to that specific Thing then in your models it should be
Class Thing
has_many :comments
end
Class Comment
belongs_to :thing
end
Then make sure in your database comment has a thing_id foreign_key field and then your form for comment should actually look like
<%= form_for #thing, #comment do %>
<% end %>

Rails4 Nested Form not saving

I have a triple nested form where a Form has many questions and questions have many answers. I have each form rendering on the show page with the form title and the form questions and input fields to create new answers associated with the asked question. The association is linking up nicely, however I cant seem to get the answers to insert into the db. I feel like it is something real easy but I cant seem to figure it out.
-Form-
<%= simple_form_for #form do |f| %>
<%= f.error_notification %>
<h1><%= #form.name %></h1>
<div class="fields">
<%= f.simple_fields_for :form_questions do |q| %>
<%= label_tag q.index+1 %>
<%= q.simple_fields_for :form_answers, q.object.form_answers.build do |a| %>
<%= a.input :answer, label: false %>
<% end %>
<% end %>
</div>
<div class="fields">
<%= f.button :submit, :class => "button", value: 'Submit' %>
</div>
<% end %>
-Form Controller-
class FormsController < ApplicationController
def new
#form = Form.new
#form.form_questions.form_answers.build
end
def create
#form = Form.new(form_params)
end
def index
#forms = Form.includes(:form_questions).all
end
def show
#form = Form.find(params[:id])
end
def edit
#form = Form.find(params[:id])
end
def form_params
params.require(:form).permit(:id, :name, form_questions_attributes: [:title, form_answers_attributes: [:answer]])
end
end
-Form Answer Controller (although if the associations are correct I feel like I should be able to handle everything in the forms controller)
class FormAnswersController < ApplicationController
def new
#form_answer = FormAnswer.new
end
def create
#form_answer = FormAnswer.new(form_answer_params)
if #form_answer.save
RequestMailer.request_submit(#form).deliver
else
format.html {render action: 'new'}
end
end
def form_answers_params
params.require(:form_answer).permit(:form_id, :form_question_id, :id, :answer)
end
end
-Server Logs-
Started PATCH "/forms/12" for 127.0.0.1 at 2014-08-05 13:31:44 -0400
Processing by FormsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"CcaCGjdoYPH2Boi1prIFhG+h5YuPHQvAxMp1dcKvWr8=", "form"=>{"form_questions_attributes"=>{"0"=>{"form_answers_attributes"=>{"0"=>{"answer"=>"hey"}}, "id"=>"50"}, "1"=>{"form_answers_attributes"=>{"0"=>{"answer"=>"ya"}}, "id"=>"51"}, "2"=>{"form_answers_attributes"=>{"0"=>{"answer"=>"go"}}, "id"=>"52"}}}, "commit"=>"Submit", "id"=>"12"}
Rendered forms/update.html.erb within layouts/application (0.1ms)
Completed 200 OK in 12ms (Views: 11.4ms | ActiveRecord: 0.0ms)

undefined method `home_home_path'

I am new to rails development and still trying to understand the building blocks of it. While running this simple code, I am getting following error
undefined method `home_home_path'
it is coming from this line <%= form_for(#homes) do |f| %> in .html.erb file. Here is my complete code, what I am doing wrong ?
I have Homes Controller file
def index
#homes = Home.all
end
def show
#home = Home.find(params[:id])
end
def new
#home = Home.new
end
def create
#home = Home.new(params[:home])
#home.save
end
Homes.rb model file
class Home < ActiveRecord::Base
attr_accessible :email, :message, :name
end
views/homes/index.html.erb
# this will show all the data
<% #homes.each do |home| %>
<%= home.name %><br />
<%= home.email %> <br />
<%= home.message %><br />
<% end %>
<br />
# this is a form where you will new records
<%= form_for(#homes) do |f| %>
<%= f.text_field :name %>
<%= f.text_field :email %>
<%= f.text_area :message %>
<%= f.submit %>
<% end %>
You should use :
<%= form_for(#home) do |f| %>
(singular)
And if you want to add a form in your index.html , remember to instantiate a new home object in your controller index method :
def index
#homes = Home.all #For displaying all the homes
#home = Home.new #For your form
end
#homes is an array object. I'm not really sure how Rails infers the url from this but running
url_for Home.limit(2).all
will also give you the same error.
The solution is to change #homes to Home.new or declare #home = Home.new in your controller and use #home in the form.
form_for Home.new
or
# controller
def index
#homes = Home.all
#home = Home.new
end
# view
form_for #home

Rails Linked Models undefined method for nil:NilClass

I've been following this, making modifications where necessary.
I have equivalents of #post and #comment. My comments are 'questions'. I've tried following this procedure again but to the comments (rather than posts). Comments on comments if you like, these are answers/responses to the questions.
I've not been successful in getting this to work.
undefined method 'answers' for nil:NilClass`
is the error in answers/_form.html.erb which is rendered as part of a comment, which is in turn rendered as part of my post equivalent.
<%= form_for([#question, #question.answers.build]) do |f| %> is the line that raises the exception. I'm thinking the problem is that #question isn't being given a value for some reason?
Either that or my routes file isn't right (would be my guess at least).
resources :posts-equivalent do
...
resources :questions
end
resources :questions do
resources :answers
end
This has had me stumped all day - any ideas would be appreciated. If you'd like to see any more code drop a comment and I'll update it here.
Additional Code:
Error Message:
Showing .../app/views/answers/_form.html.erb where line #1 raised:
undefined method `answers' for nil:NilClass
Extracted source (around line #1):
1: <%= form_for([#question, #question.answers.build]) do |f| %>
Answers Controller:
class AnswersController < ApplicationController
def create
#question = Question.find(params[:question_id])
#answer = #question.answers.create(params[:answer])
redirect_to concept_path(#question.concept)
end
end
It looks like your AnswersController is not assigning a value to the #question instance variable. It's not clear what action you are running, but I'm assuming it's either new or edit based on the fact that you have a form. You should have something like this in those actions:
class AnswersController < ApplicationController
def new
#question = Question.find(params[:question_id])
#answer = #question.answers.new
end
def edit
#question = Question.find(params[:question_id])
#answer = #question.answers.find(params[:id])
end
end
Then you can have a single form shared between new and edit:
<%= form_for([#question, #answer]) %>
In the end I sorted this in a different manner. Each question was only ever going to have one answer and so I just gave question an answer attribute and assigned that.
On the post page:
...
<%= render #questions %>
<%= render "questions/form" %>
...
In _form.html.erb
<%= form_for([#concept, #concept.question.build]) do |f| %>
<%= f.hidden_field :contributor_id, :value => session[:contributor_id] %>
<div class="field">
<%= f.text_field :question, :placeholder => "Follow-up Question" %>
</div>
<% end %>
In the _question.html.erb
<%= form_for(question) do |f| %>
<div id="question">
"<%= question.question %>" asked by <%= question.contributor.email %> | <%= question.created_at %>.
<div id="answer">
- Answer: <%= question.answer %>
<%= f.text_field :answer, :placeholder => "Respond..." %>
</div>
</div>
<% end %>
Add this to the questions controller:
def update
#question = Question.find(params[:id])
#question.update_attributes(params[:question])
#concept = Concept.find(#question.concept.id)
redirect_to concept_path(#concept)
end
And that worked for me, I know it's not what I originally asked but that fixed my problem. Thanks to those who did try to help.

Resources