I'm rails noob. I have a problem with contact form.
I have an error: undefined method 'name' for nil:NilClass
<p>
<strong>Name:</strong>
<%= #contact_forms.name %>
</p>
My manager.html.erb is:
<div>
<p>
<strong>Name:</strong>
<%= #contact_forms.name %>
</p>
<p>
<strong>Text:</strong>
<%= #contact_forms.text %>
</p>
</div>
My contact_form_controller.rb is:
class ContactFormController < ApplicationController
def new
end
def create
#contact_forms = Contact_form.new(params[:contact_form])
#contact_forms.save
redirect_to root_path
end
def show
#contact_forms = Contact_form.all
end
end
My file with migrates:
class CreateContactForms < ActiveRecord::Migration
def change
create_table :contact_forms do |t|
t.string :name
t.string :phone
t.string :email
t.text :text
t.timestamps null: false
end
end
end
my static_pages_controller.rb is
class StaticPagesController < ApplicationController
def home
end
def manager
end
end
Thanks
undefined method `name' for nil:NilClass
You didn't defined #contact_forms in the manager method of static_pages controller, so is the error. Defining it like below should solve your problem.
class StaticPagesController < ApplicationController
def home
end
def manager
#contact_forms = ContactForm.all
end
end
Update:
You should also iterate over #contact_forms like below in the manager.html.erb
<div>
<% #contact_forms.each do |contact_form| %>
<p>
<strong>Name:</strong>
<%= contact_form.name %>
</p>
<p>
<strong>Text:</strong>
<%= contact_form.text %>
</p>
<% end %>
</div>
I'm rails noob
Welcome to the family! You're a newb, not noob :)
Pavan's answer is right; since you're new I wanted to give you some context:
undefined method 'name' for nil:NilClass
This error means you're trying to call a method on a variable which has not been defined / populated.
In your case, #contact_forms is not defined.
The confusing part for many new Ruby developers is that instead of halting the entire program, Ruby populates the NilClass & claims there to be an error with it
So whilst you'd expect it to say the variable was undeclared, it gives you a message about how a method doesn't work.
--
To resolve your issue, you need to use the following:
#config/routes.rb
resources :contact_forms
resources :static_pages
#app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
def manager
#contact_forms = ContactForm.all
end
end
To steal from Pavan, this has to be backed up by looping through the #contact_forms variable (unless you've populated it with a single instance of the ContactForm model):
#app/views/static_pages/manager.html.erb
<% #contact_forms.each do |form| %>
<%= form.name %>
<% end %>
As an aside, I would never recommend calling a controller StaticPages.
When you get more into Ruby, you'll find out about the object orientated nature of the language:
I explain this a lot; basically, it means you have to keep your program centered around objects, in the case of Rails, are populated by the Models.
As such, you need to think about what data object you're trying to manipulate when showing this view. At present, it seems you want to show a contact form -- I'd put it in its own method in the ApplicationController:
#config/routes.rb
match "contact", to: "application#contact_form", via: [:get, :post]
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def contact_form
if request.post?
#post contact form
else
#load contact form
end
end
end
Related
I'm getting this error while trying to pass "Innovation Cloud" lesson on Codecademy. I couldn't find any solution on Stack Overlow or GitHub.
NoMethodError in Signups#new
Showing /home/ccuser/workspace/learn-rails_innovation-cloud/innovation-cloud/app/views/signups/new.html.erb where line #40 raised:
undefined method `email' for #<Signup id: nil, created_at: nil, updated_at: nil>
Important fragments of code:
routes.rb:
Rails.application.routes.draw do
get "/thanks" => "pages#thanks"
resources :signups
root "signups#new"
end
new.html.erb
<%= form_for(#signup) do |f| %>
<div class="field">
<%= f.label :signup %><br>
<%= f.text_area :email %>
</div>
<div class="actions">
<%= f.submit "Create" %>
</div>
<% end %>
db/migration
class CreateSignups < ActiveRecord::Migration
def change
create_table :signups do |t|
t.string :email
t.timestamps
end
end
end
signups_controller.rb
class SignupsController < ApplicationController
def new
#signup = Signup.new
end
private
def signup_params
params.require(:signup).permit(:email)
end
def create
#signup = Signup.new(signup_params)
if #signup.save
redirect_to '/thanks'
else
render 'new'
end
end
end
As the error implies, some code tried to call a method email on an instance of Signup. Its not clear what line of code corresponds to the line number 40, but my guess is its the following:
<%= f.text_area :email %>
Anytime you build a form with an ActiveRecord instance (as you do with form_for(#signup)), any input generated will expect an attribute on your model with the same name. In this case, its looking for an attribute named email on #signup. It does this so that the field can be populated with the current value of that attribute on the model. While this might seem unnecessary for a #new action, it makes perfect sense for an #edit action, and allows you to reuse the same form code for both.
Since I'm guessing you'd like to store the email along with the signup, you need to add the attributes to the Signup model with a migration like so:
rails generate migration AddEmailToSignup email:string
rake db:migrate
I migrated a new database table here it looks like this:
create_table "books", :force => true do |t|
t.string "books_title"
t.integer "books_count"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
and my models/books.rb looks like this:
class Books < ActiveRecord::Base
attr_accessible :books_count, :books_title
end
and i'm trying to create new record using this code:
<%= form_for(#Books) do |f| %>
<%= f.label :books_title, 'Book Title' %>
<%= f.text_field :books_title %>
<% end %>
then i'm getting error: undefined method books_title for NilClass:Class
also my controllers/books_controller.rb looks like this:
class BooksController < ApplicationController
end
Please help me.I'm very new to ruby, what shoud I do what command i need to run? Thanks!
Its actually "#books" not "#Books"
and I dont see this line in your controller, "#books = Books.all"
(actually, it should be book, model names are singular and table names are plural)..
Welcome to rails...
I would do this, goto your app path and type,
rails g scaffold book title:string count:integer user_id:integer
The above command will generate everything for you from routes, model, migration, controller, view to test cases.
Need not worry about anything. Just
run rake db:migrate (it would probably throw an error since you already have "books" table, drop it)
Now visit, http://localhost:3000/books, you will see the books list(index view). Now, goto your books controller and start your learning method by method.
You must create #book instance for form_for method like this.
class StocksController < ApplicationController
def new
#book = Book.new
end
end
And view.
<%= form_for(#book) do |f| %>
<%= f.label :books_title, 'Book Title' %>
<%= f.text_field :books_title %>
<% end %>
And you must have create method in your books controller.
class StocksController < ApplicationController
# ...
def create
#book = Book.create(book_params)
end
private
def book_params
params.require(:book).permit(:books_title)
end
end
I recommend you to use :title instead of :books_title. Because it's a little redundant.
also my controllers/books_controller.rb looks like this:
class StocksController < ApplicationController
end
Rails has a naming convention, of using the same name for the file as for the controller, so you should either rename StocksController to BooksController or books_controller.rb to stocks_controller.
In any case, you are going to need an action in it, that initializes the book object for the form. And a create action, to save it. Another thing, it's standard to name your variable as a lowercase variable, and in singular, so it would be #book.
class BooksController < ApplicationController
def new
#book = Book.new
end
def create
#book = Book.create(params)
end
end
And update your form to be
<%= form_for(#book) do |f| %>
<%= f.label :books_title, 'Book Title' %>
<%= f.text_field :books_title %>
<% end %>
As a first-time Rails user, I have to say I'm loving the Rails way of doing things. However, I'm running into an issue trying to create a simple form. I get the following error:
undefined method `categories_path' for #<#<Class:0x007f0440365880>:0x007f0430256cd8>
I tried creating a categories_path method in the controller (though I'm not sure what it would be for), but that didn't fix the error. Any rails experts out there know what's going on?
Here's the relevant code:
views/category/new.html.erb
<%= form_for #category do |f| %>
<%= f.label :category %>
<%= f.text_field :name %><br />
<%= f.submit %>
<% end %>
routes.rb
Jackeyes::Application.routes.draw do
scope "/admin" do
resources :product, :category
end
end
category_controller.rb
class CategoryController < ApplicationController
def index
#category = Category.all
end
def new
#category = Category.new
end
def create
#category = Category.new(params[:category])
#category.save
end
end
Make your resources plural:
resources :products, :categories
And try again.
Pretty basic Rails question I assume but I can't figure out the simplicity of Rails.
My simple goal is to have a user submit a form indicating the amount of a donation, and have that donation linked to the user. I'm having trouble with the create action in the donations_controller.rb
I have a User.rb model and a Donation.rb model. The User.rb has_one :donation and Donation.rb belongs_to :user. I am also using Devise so I have the current_user method.
My donation table looks like this
class CreateDonations < ActiveRecord::Migration
def change
create_table :donations do |t|
t.integer :amount
t.integer :user_id
t.timestamps
end
add_index :donations, [:user_id, :created_at]
end
end
The _form.html.erb for the donations_controller.rb looks like this
<%= form_for #donation do |f| %>
<div class="field">
<%= f.number_field :amount %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
The create action in donations_controller.rb looks like this
def create
#donation = current_user.donation.build(params[:donation])
if #donation.save
flash[:success] = "Donation"
redirect_to root_path
else
render 'home/index'
end
end
I'm getting this error message when I submit the form.
NoMethodError in DonationsController#create
undefined method `build' for nil:NilClass
The method for building the has_one association is current_user.build_donation(params[:donation])
Hi I'm a super beginner and working on my first app, I have a table of venues and users can add reviews to the venues. I would like to be able to hide the review form to users once they have submitted a review, to stop them from submitting more.
This is what I have now:
add review form on venue show page
<% if reviewed? %>
<%= form_for [#venue, #review], :class => 'rating_ballot' do |f| %>
<%= f.label("value_1", content_tag(:span, '1'), {:class=>"rating", :id=>"1"}) %>
<%= radio_button_tag("review[rating]", 1, :class => 'rating_button') %>
<%= f.label("value_2", content_tag(:span, '2'), {:class=>"rating", :id=>"2"}) %>
<%= radio_button_tag("review[rating]", 2, :class => 'rating_button') %>
<%= f.label("value_3", content_tag(:span, '3'), {:class=>"rating", :id=>"3"}) %>
<%= radio_button_tag("review[rating]", 3, :class => 'rating_button') %>
<%= f.label("value_4", content_tag(:span, '4'), {:class=>"rating", :id=>"4"}) %>
<%= radio_button_tag("review[rating]", 4, :class => 'rating_button') %>
<%= f.label("value_5", content_tag(:span, '5'), {:class=>"rating", :id=>"5"}) %>
<%= radio_button_tag("review[rating]", 5, :class => 'rating_button') %> <br>
<p>title: <br>
<%= f.text_field :title %></p><br>
<%= submit_tag %>
<% end %>
<% end %>
application controller
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
helper_method :reviewed?
protected
def reviewed?
true
end
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
I cant figure out what the reviewed? helper should be to allow me to do this, any help is greatly appreciated!
edit
I've added the has_reviewed helper to the application controller, it now shows this error:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Extracted source (around line #79):
76: <%= render :partial => 'reviews/review', :collection => #venue.reviews %>
77: </div>
78:
79: <% if reviewed? %>
application controller
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
helper_method :current_user
helper_method :has_reviewed
helper_method :reviewed?
protected
def reviewed?
Review.has_reviewed(#current_user.id, venue.id)
end
def has_reviewed
!Review.where(:user_id=>user,:venue_id=>venue).blank?
end
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
another edit
I've changed the reviewed? helper method to:
def reviewed?
if current_user
Review.has_reviewed(#current_user.id, #venue.id)
else
nil
end
end
but it gives undefined method `has_reviewed' for # error
schema
A venue has many reviews
A user has many reviews
A review belongs to a user and a venue
the routes looks like this:
App::Application.routes.draw do
resources :sessions
resources :users
resources :venues do
resources :reviews
end
end
Presuming you make the change as suggested by Wes, the reviewed? method would look in the database to see if this user has made a review.
The reviews table will need to have a column for the user that made the review and the venue it reviewed.
So the code would look something like this...
EDITED to reflect schema recently added
In the controller
def reviewed?
if current_user
#current_user.has_reviewed(#venue.id)
else
nil
end
end
In the User model...
class User < ...
has_many :reviews
def has_reviewed(venueid)
reviews.exists?(:venue_id => venueid)
end
...
end
Basically I think the has_reviewed is better off in the User model as the user has_many reviews, and then it can check if the user has reviewed the given venue.
I am presuming that the Model Review has a foreign key to venue called venue_id, as a Review belongs_to a Venue and that would be the standard thing.
<% unless reviewed? %>
[...]
<% end %>