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 %>
Related
I have a little bit of a newbie question.
I have a basic form with a dropdown list that looks like the following :
## apply.html.erb
<%= form_for #category do |f| %>
<%= f.label 'parent' , 'Category' %>
<%= f.select :category, [["foo", 0 ], ["bar", 1 ]] %>
<% end %>
The dropdown list values are "foo" and "bar".
I am trying to pull values directly from a database. The problem is that I have no idea how to organize the controller and the model.
Here is the controller :
## Welcome_controller.rb
class WelcomeController < ApplicationController
def index
end
def apply
#category = 'foobar'
end
end
I have not generated the controller yet. I can not find any convincing answers to my question or tutorial on the internet.
Any idea how I can make it happen?
** EDIT **
So I have been doing some edits.Here is what I have:
The view
## apply.html.erb
<%= form_for #category, as: :category do |f| %>
<%= f.label 'Categories' %>
<%= f.select :category, #category %>
<% end %>
The controller :
## welcome_controller.rb
def apply
#category = Category.new
#categories = Category.pluck(:id, :name)
end
The model :
## Category.rb
class Category < ApplicationRecord
end
I get the following in the terminal :
ActionView::Template::Error (undefined method `categories_path' for #<#<Class:0x007ffb7c5a2808>:0x007ffb7c2814f8>):
3: <div id="category_block">
4: <span>What would you like to get financed ?</span>
5:
6: <%= form_for #category, as: :category do |f| %>
7: <%= f.label 'Categories' %>
8: <%= f.select :category, #category %>
9: <% end %>
app/views/welcome/apply.html.erb:6:in `_app_views_welcome_apply_html_erb___747255529581383389_70359048261520'
It looks like the problem comes from #category = Category.new because when I replace Category.new with a string like ' foobar', the error disappears.
Any idea how to fix this problem?
You should read more about the documentation. This is a pretty basic question, and you'll probably have the answer if you actually take the time to read and learn.
That said, the info you provided is lacking so I'll just assume.
First, I assume you have a Category model. It should be placed in app/models/category.rb:
def Category
...
end
Next, you're not actually querying anything from the database. You can do it this way:
## app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
def index
end
def apply
#category = Category.new
#categories = Category.pluck(:name, :id)
end
end
Category.new generates a new instance of the Category (category.rb) object.
Category.pluck(:name, :id) generates this array: [['foo', 1], ['bar', 2]], where name and id are attributes of the Category model (just change it to your liking).
Once you have your array stored in #categories, you can use it in your form like this:
## app/views/welcome/apply.html.erb
<%= form_for #category do |f| %>
<%= f.label 'parent' %>
<%= f.select :category, #categories %>
<% end %>
You're probably not planning to actually create a form for a Category considering that you have a dropdown for categories so you should just change it to something else. Also, take note of the file names. They're all lowercase and separated by underscores. (Welcome_controller.rb should be welcome_controller.rb)
** EDIT **
Now that you've added an object to the form_for, rails will automatically assign a path for your form unless you change it. For this case, the path is categories_path. Read more here.
What you need to do is modify your routes.rb and add the following line:
resources :categories
That line will automatically generate routes that provide a mapping between HTTP verbs and URLs to controller actions.
Next you need to create a CategoriesController:
## app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def create
#category = Category.new(category_params)
if #account_user.save
redirect_to apply_path
else
render :new
end
end
private
def category_params
params.require(:category).permit! # MODIFY THIS
end
end
Anyway, this is basically a walkthrough and you should be figuring this out yourself. There are a lot of resources out there -- it's not hard to find one. You can also check this out: video.
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
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
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])
I am just trying to print the parameters that have been entered into my form.
Basically I create a new bet then I display the parameters:
MIGRATION
class CreateBets < ActiveRecord::Migration
def self.up
create_table :bets do |t|
t.integer :accepted ,:default => 0
t.integer :user_1_id #proposer
t.integer :user_2_id #receiver
t.integer :team_1_id #proposer's team
t.integer :team_2_id #receiver's team
t.integer :game_id
t.integer :winner
t.integer :amount
t.timestamps
end
end
def self.down
drop_table :bets
end
end
CONTROLLER
bets_controller.erb
class BetsController < ApplicationController
def index
redirect_to new_bet_path
end
def new
#b=Bet.new
end
def create
#points=params[:points]
#winner=params[:winner]
end
end
VIEWS
New.erb
<% facebook_form_for Bet.new do |f| %>
<%= f.text_field :amount, :label=>"points" %>
<%= f.text_field :winner, :label=>"WinningTeam" %>
<%= f.buttons "Bet" %>
<% end %>
create.erb
points:<%= #points %>
<br>
winner:<%= #winner %>
I tried to make this code work with instance variables but it didn't work either. Where is the problem?
Thank you.
I think that params[:winner] and params[:point] is empty hash. Try adding this to your create.erb:
params: <%= params.inspect %>
It will display your params hash, so you will see how to get to it.
Another hint, why you are creating new object in new action and then in form you are doing it again? So:
<% facebook_form_for #b do |f| %>
And another thing, it is really good to keep naming conventions, so don't create #b object, but #bet.
In create action you should have line like this:
#bet = Bet.new(params[:bet])
And in view:
<p>
points:<%= #bet.points %>
</p>
<p>
winner:<%= #bet.winner %>
</p>
If you use <br> it's better to use <br/>.
Your index action is totaly useless. It would be better if you would move all behaviour from new action to index and remove new action completly.
As klew pointed, for me it seems that you're getting empty params[:winner]and params[:point]. You can make sure that of what you're getting by taking a look at your servers log.
You will see a line like
Processing BetsController#create (for 127.0.0.1 at 2010-04-11 20:56:51) [POST]
Parameters: {"your"=>"parameters", "should"=>"apper in this hash"}