nil value instead of form value - ruby-on-rails

I have a page index of Beer Receipe which also is supposed to display the ratings/comments. I've inserted a couple in rails c, and it displays fine on the Beer Receipe page. But when I try to create the rating on the form itself, both the star and comment comes up blank on the form, and when I look in the rails c, it shows nil value. Why?
Have three models: Beer_Receipe, Ingredient, & Rating
This is the schema:
create_table "beer_receipes", force: :cascade do |t|
t.string "name"
t.string "style"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "ingredients", force: :cascade do |t|
t.string "name"
t.string "category"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "ratings", force: :cascade do |t|
t.string "ratable_type"
t.integer "ratable_id"
t.integer "stars"
t.text "comments"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Their associations are:
class BeerReceipe < ActiveRecord::Base
has_many :ratings, as: :ratable, dependent: :destroy
end
class Ingredient < ActiveRecord::Base
has_many :ratings, as: :ratable, dependent: :destroy
end
class Rating < ActiveRecord::Base
belongs_to :ratable, polymorphic: true
end
This is the Beer Receipe Index
<p id="notice"><%= notice %></p>
<h2>Beer Receipe Index</h2>
<p>
<strong>Name:</strong>
<%= #beer_receipe.name %>
</p>
<p>
<strong>Style:</strong>
<%= #beer_receipe.style %>
</p>
<h2>Ratings</h2>
<%= render #beer_receipe.ratings %>
<h2>Add Ratings</h2>
<%= render 'ratings/form' %>
<%= link_to 'Edit', edit_beer_receipe_path(#beer_receipe) %> |
<%= link_to 'Back', beer_receipes_path %>
This is the _form.html.erb page
<%= form_for([#beer_receipe, #beer_receipe.ratings.build]) do |f| %>
<p>
<%= f.label :stars %><br>
<%= f.select :stars, (0..10) %>
</p>
<p>
<%= f.label :comments %><br>
<%= f.text_field :comments %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
And lastly, but not least, Ratings Controller
class RatingsController < ApplicationController
def new
end
def create
#beer_receipe = BeerReceipe.find(params[:beer_receipe_id])
#rating = #beer_receipe.ratings.create(rating_params)
#redirect_to beer_receipe_path(#beer_receipe)
end
def destroy
#beer_receipe = BeerReceipe.find(params[:beer_receipe_id])
#rating = #beer_receipe.ratings.find(params[:id])
#rating.destroy
redirect_to beer_receipe_path(#rating)
end
def edit
end
def update
end
private
def rating_params
params.require(:rating).permit(:star, :comment)
end
end
EDIT
Started POST "/beer_receipes/1/ratings" for 127.0.0.1 at 2016-04-01 15:14:43 -0700
Processing by RatingsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"3kilQgA3tZ0ZxsfuRY4LKFkNl3+oL1x9zRT2/EccDeM0b+6a1NuHgo6cHaYOqBJMd6s4dduID06i5oTvcBisTw==", "rating"=>{"stars"=>"6", "comments"=>"testing .."}, "commit"=>"Create Rating", "beer_receipe_id"=>"1"}
[1m[35mBeerReceipe Load (0.2ms)[0m SELECT "beer_receipes".* FROM "beer_receipes" WHERE "beer_receipes"."id" = ? LIMIT 1 [["id", 1]]
Unpermitted parameters: stars, comments
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
[1m[35mSQL (0.6ms)[0m INSERT INTO "ratings" ("ratable_id", "ratable_type", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["ratable_id", 1], ["ratable_type", "BeerReceipe"], ["created_at", "2016-04-01 22:14:43.982989"], ["updated_at", "2016-04-01 22:14:43.982989"]]
[1m[36m (38.6ms)[0m [1mcommit transaction[0m
Rendered ratings/create.html.erb within layouts/application (0.1ms)
Completed 200 OK in 437ms (Views: 351.6ms | ActiveRecord: 40.8ms)
Started GET "/" for 127.0.0.1 at 2016-04-01 15:16:03 -0700
Processing by BeerReceipesController#index as HTML
[1m[35mBeerReceipe Load (0.8ms)[0m SELECT "beer_receipes".* FROM "beer_receipes"
Rendered beer_receipes/index.html.erb within layouts/application (14.7ms)
Completed 200 OK in 686ms (Views: 668.5ms | ActiveRecord: 1.3ms)
Started GET "/beer_receipes/2" for 127.0.0.1 at 2016-04-01 15:16:06 -0700
Processing by BeerReceipesController#show as HTML
Parameters: {"id"=>"2"}
[1m[36mBeerReceipe Load (0.6ms)[0m [1mSELECT "beer_receipes".* FROM "beer_receipes" WHERE "beer_receipes"."id" = ? LIMIT 1[0m [["id", 2]]
[1m[35mRating Load (0.3ms)[0m SELECT "ratings".* FROM "ratings" WHERE "ratings"."ratable_id" = ? AND "ratings"."ratable_type" = ? [["ratable_id", 2], ["ratable_type", "BeerReceipe"]]
Rendered ratings/_rating.html.erb (1.3ms)
Rendered ratings/_form.html.erb (8.1ms)
Rendered beer_receipes/show.html.erb within layouts/application (90.6ms)
Completed 200 OK in 140ms (Views: 134.6ms | ActiveRecord: 1.1ms)
Started POST "/beer_receipes/2/ratings" for 127.0.0.1 at 2016-04-01 15:16:11 -0700
Processing by RatingsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"WmwvDG+a/YsgGKpOGtlxQLUCNjyc/+y3lhab5ZO9WPCwS2TUu3bPlLdCcAZR/2gkm6SZNu9Yv4T55On2pLn5XA==", "rating"=>{"stars"=>"3", "comments"=>"sdfsdf"}, "commit"=>"Create Rating", "beer_receipe_id"=>"2"}
Rendered ratings/create.html.erb within layouts/application (0.3ms)
Completed 200 OK in 104ms (Views: 101.5ms | ActiveRecord: 0.0ms)

try this in your ratings controller create action:
#rating = Rating.new(stars: params[:rating][:star], comments: params[:rating][:comments], ratable_id: params[:beer_recipe_id])
if #rating.save
puts "huzzah!"
end
Let me know if that works.

Related

Error in the association of two models. (# must exists)

I want to be able to choose an author when creating a post. I have a Post and Author model. In the author's model, I prescribed has_many :posts, and in the Post model belongs_to :author. In the form view, created a list of authors <%= form.collection_select(:author_id, Author.all, :id, :last_name, class:'form-control' ) %>. In the post controller I prescribed:
def post_params
params.require(:post).permit(:name, :title, :content, :picture, :author_id)
end
schema.rb:
create_table "posts", force: :cascade do |t|
t.string "name"
t.string "title"
t.text "content"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "author_id"
t.index ["author_id"], name: "index_posts_on_author_id"
end
But when creating a post, I get an error:
Author must exist
logs:
Started POST "/posts" for ::1 at 2019-11-18 00:51:40 +0200
Processing by PostsController#create as HTML
Parameters: {"authenticity_token"=>"68iOabMzXQPuvC83f5Oe3kQEl5rFeQLQNCuMjvtRZgfdArdvMs79gKs8MeTNzBcsN0dRjTdRVCFkIrvZqixY1g==", "post"=>{"author_id"=>"2", "name"=>"SomeName", "title"=>"SomeTitle", "content"=>"SomeContent"}, "commit"=>"Submit"}
Rendering posts/new.html.erb within layouts/application
[1m[36mAuthor Load (0.2ms)[0m [1m[34mSELECT "authors".* FROM "authors"[0m
↳ app/views/posts/_form.html.erb:16
Rendered posts/_form.html.erb (Duration: 8.2ms | Allocations: 2071)
Rendered posts/new.html.erb within layouts/application (Duration: 9.1ms | Allocations: 2157)
Completed 200 OK in 34ms (Views: 30.4ms | ActiveRecord: 0.2ms | Allocations: 13745)```
The Author must exist error indicates that your new post is failing a validation: the presence of a value for the author_id attribute which links a post to an author. This validation comes bundled by default with the belongs_to association helper method (and can be disabled as per Simon Franzen's comment above: belongs_to: model, optional: true.
Since you're permitting the author_id key in post_params, the weak link in the chain is either your post#create controller action or your _form.html.erb view. A couple of suggestions for post#create, and _form.html.erb, respectively:
def create
post = Post.create(post_params)
redirect_to post
end
<%= form_with model: #post do |form| %>
...
<%= form.label :author %>
<%= form.collection_select :author_id, Author.all, :id, :name %>
...
<%= form.submit "Create Post" %>
<% end %>
We need more of the code for your post controller actions and form view to give a more precise answer.

Unpermitted parameter in HABTM relationship

So I'm building an HABTM relationship and I always get this error back in the terminal when I submit the form:
Unpermitted parameter: :color_ids
No other errors. The app works fine, except that the associations are always an empty array.
Schema.rb:
create_table "colors", force: :cascade do |t|
t.string "color"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "colors_products", id: false, force: :cascade do |t|
t.integer "color_id", null: false
t.integer "product_id", null: false
end
create_table "products", force: :cascade do |t|
t.string "title"
t.decimal "price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
color.rb:
class Color < ApplicationRecord
has_and_belongs_to_many :products
end
product.rb:
class Product < ApplicationRecord
has_and_belongs_to_many :colors
end
_form.html.erb:
<div class="field">
<%= form.label :color %>
<%= form.collection_select :color_ids, Color.all, :id, :color, {:multiple => true}, class: "input-field-data" %>
</div>
product_controller.rb
def product_params
params.require(:product).permit(:title, :price, color_ids: [])
end
changing the param hash from color ids to color_ids:[:id, :color]
makes no difference.
This example is obviously just something I recreated to see if I did something else wrong in my original app, probably also easier to debug.
Any ideas what's wrong with that setup? I actually have another project with the exact same setup and it works? Because of that, I think that I'm missing something, but I don't actually find anything wrong with my code.
Thanks in advance for any input!
Edit:
As requested, here is the terminal log when submitting a new product with a collection_select as shown above:
Started POST "/products" for 127.0.0.1 at 2019-02-10 14:02:59 +0100
Processing by ProductsController#create as HTML
Parameters: {"authenticity_token"=>"+f+GJaN58M029eGICvMqlwtjYB4Qmv/KNBY0OnymrxyFy+zNYXKfZtCXR0NM3kLY16QIzfLb+takhNjgIQXeEw==", "product"=>{"title"=>"abc", "price"=>"9.99", "color_ids"=>"1"}, "commit"=>"Create Product"}
Unpermitted parameter: :color_ids
(0.1ms) begin transaction
↳ app/controllers/products_controller.rb:30:in `block in create'
Product Create (1.0ms) INSERT INTO "products" ("title", "price", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "abc"], ["price", 9.99], ["created_at", "2019-02-10 13:02:59.634965"], ["updated_at", "2019-02-10 13:02:59.634965"]]
↳ app/controllers/products_controller.rb:30:in `block in create'
(1.1ms) commit transaction
↳ app/controllers/products_controller.rb:30:in `block in create'
Redirected to http://localhost:3000/products/15
Completed 302 Found in 14ms (ActiveRecord: 2.3ms | Allocations: 3885)
Started GET "/products/15" for 127.0.0.1 at 2019-02-10 14:02:59 +0100
Processing by ProductsController#show as HTML
Parameters: {"id"=>"15"}
Product Load (0.4ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT ? [["id", 15], ["LIMIT", 1]]
↳ app/controllers/products_controller.rb:67:in `set_product'
Rendering products/show.html.erb within layouts/application
Rendered products/show.html.erb within layouts/application (Duration: 1.1ms | Allocations: 302)
Completed 200 OK in 23ms (Views: 16.0ms | ActiveRecord: 0.4ms | Allocations: 8945)
Also:
Submitting via rails console works fine, so this has definitely something to do with the form i guess:
irb(main):010:0> p = Product.last
=> #<Product id: 15, title: "abc", price: 0.999e1, created_at: "2019-02-10 13:02:59", updated_at: "2019-02-10 13:02:59">
irb(main):011:0> p.colors
=> #<ActiveRecord::Associations::CollectionProxy []>
irb(main):012:0> p.colors << [Color.last]
=> #<ActiveRecord::Associations::CollectionProxy [#<Color id: 2, col: "Red", created_at: "2019-02-10 09:04:42", updated_at: "2019-02-10 09:04:42">]>
irb(main):013:0> p.colors
=> #<ActiveRecord::Associations::CollectionProxy [#<Color id: 2, col: "Red", created_at: "2019-02-10 09:04:42", updated_at: "2019-02-10 09:04:42">]>
_form.html.erb (generated by scaffold and adjusted with the collection_select field)
<%= form_with(model: product, local: true) do |form| %>
<% if product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :price %>
<%= form.text_field :price %>
</div>
<div class="field">
<%= form.label :color_ids %>
<%= form.collection_select( :color_ids, Color.all, :id, :col, {multiple: true}) %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Greetings!
You are expecting an array/hash but you are receiving a single string. It looks like the helper is not creating a multiple select, do you see the multiple="true" attr on the select tag? If not, try changing the method to this:
form.collection_select( :color_ids, Color.all, :id, :col, {}, {multiple: true})
Note the extra {}. The helper expect the first hash to be the options for the helper and the second hash to be the options for the tag.

Rails: Create action not saving has_many through associations - "rollback transaction"

Be easy on me, I'm just starting to learn Rails and this is my first question on here!
The project I'm using to learn is a volleyball scoreboard, so right now I'm trying to build a form that will submit the score of a 2v2 game. I have users and games which are associated by a has_many through relationship to a join table of participants which also includes a 'result' attribute ('W' or 'L').
My problem is that when I submit it fails, and no participants are created. If I removed the associations from the form, submission will work with just game parameters.
Hopefully, I've included all the relevant information below. Also, if there is a better way to do all this, I'd love to hear it!
MODELS
class Game < ApplicationRecord
has_one :venue
has_many :participants
has_many :users, through: :participants
accepts_nested_attributes_for :participants,
reject_if: :all_blank, allow_destroy: true
end
class User < ApplicationRecord
has_many :participants
has_many :games, through: :participants
end
class Participant < ApplicationRecord
belongs_to :game
belongs_to :user
end
SCHEMA
create_table "games", force: :cascade do |t|
t.date "game_date"
t.integer "winning_score"
t.integer "losing_score"
t.text "notes"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "venue_id"
t.index ["venue_id"], name: "index_games_on_venue_id"
end
create_table "participants", force: :cascade do |t|
t.integer "user_id"
t.integer "game_id"
t.string "result"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["game_id"], name: "index_participants_on_game_id"
t.index ["user_id"], name: "index_participants_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.index ["email"], name: "index_users_on_email", unique: true
end
create_table "venues", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
CONTROLLER
class GamesController < ApplicationController
def show
#game = Game.find(params[:id])
end
def new
#users = User.all
#game = Game.new
#game.participants.build
end
def create
#game = Game.new(game_params)
if #game.save
redirect_to 'show'
else
render 'new'
end
end
private
def game_params
params.require(:game).permit(:game_date, :winning_score,
:losing_score, :notes, :venue_id,
participants_attributes: [:user_id, :result,
:_destroy])
end
end
FORM
<%= simple_form_for #game do |f| %>
<div id="winners">
<b>Winners</b>
<% for i in 0..1 %>
<%= f.simple_fields_for :participants do |p| %>
<%= p.association :user, :collection => #users, label: false %>
<%= p.input :result, :as => :hidden, :input_html => { :value => 'W' }%>
<% end %>
<% end %>
</div>
<%= f.input :winning_score, :collection => 15..30 %>
<div id="losers">
<b>Losers</b>
<% for i in 2..3 %>
<%= f.simple_fields_for :participants do |p| %>
<%= p.association :user, :collection => #users, label: false %>
<%= p.input :result, :as => :hidden, :input_html => { :value => 'L' }%>
<% end %>
<% end %>
</div>
<%= f.input :losing_score, :collection => 0..30 %>
<%= f.input :notes %>
<%= f.submit "Submit!", class: "btn btn-primary" %>
<% end %>
RESPONSE
Processing by GamesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"p8081+wU7EqYV7PIIAOGP3N+Md4CJusFpL9qTm3CeC54fP7pTPEwtfYS5v5x+ErBWxGiB0oj1pklYGXwl/cRBw==", "game"=>{"participants_attributes"=>{"0"=>{"user_id"=>"3", "result"=>"W"}, "1"=>{"user_id"=>"2", "result"=>"W"}, "2"=>{"user_id"=>"1", "result"=>"W"}, "3"=>{"user_id"=>"6", "result"=>"W"}}, "winning_score"=>"18", "losing_score"=>"4", "notes"=>"13241234"}, "commit"=>"Submit!"}
(0.1ms) begin transaction
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 6], ["LIMIT", 1]]
(0.1ms) rollback transaction
Rendering games/new.html.erb within layouts/application
Rendered games/new.html.erb within layouts/application (69.4ms)
Rendered layouts/_shim.html.erb (0.4ms)
Rendered layouts/_header.html.erb (0.7ms)
Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 199ms (Views: 144.9ms | ActiveRecord: 0.5ms)
#kkulikovskis comment worked for me. I changed:
has_many :participants
to
has_many :participants, inverse_of: :game
in the game model

How to display all comments?

Please help me to display all the comments for certain thread.
I use the following gems:
'awesome_nested_set',
'acts_as_commentable_with_threading'
For example, I create scaffold 'message'. And I try for certain message unit make comments thread.
MessagesController:
def show
# to display all comments
#all_comments = #message.comment_threads
p '-----------------'
p #all_comments
p #all_comments.count
# for form new comment
#message = Message.find(params[:id])
#user_who_commented = current_user
#comment = Comment.build_from( #message, #user_who_commented.id, "Hey guys this is my comment!" )
end
views/messages/show.html.erb:
<p>
<strong>message Title:</strong>
<%= #message.title %>
</p>
<p>
<strong>message Body:</strong>
<%= #message.body %>
</p>
<%= render 'comments/form' %>
<% #all_comments.each do |comment| %>
<div>
<%= #comment.title %>
<%= #comment.body %>
</div>
<% end %>
schema:
create_table "comments", force: :cascade do |t|
t.integer "commentable_id"
t.string "commentable_type"
t.string "title"
t.text "body"
t.string "subject"
t.integer "user_id", null: false
t.integer "parent_id"
t.integer "lft"
t.integer "rgt"
t.datetime "created_at"
t.datetime "updated_at"
end
in this table after add new comment i(and gem) filled via create-action fields:
title,
body,
user_id,
lft,
rgt
CommentsController:
def create
comment = Comment.new(comment_params)
comment.user = current_user
comment.save
if comment.update_attributes(user: current_user)
redirect_to messages_path, notice: 'Comment was successfully created.'
else
render :new
end
end
def new
#comment = Comment.new
end
The form to add a new message worked ok, but all comments for certain messages are not displayed.
ps:
log:
Started GET "/messages/1" for 127.0.0.1 at 2015-10-23 14:09:47 +0300
Processing by MessagesController#show as HTML
Parameters: {"id"=>"1"}
Message Load (0.1ms) SELECT "messages".* FROM "messages" WHERE "messages"."id" = ? LIMIT 1 [["id", 1]]
"-----------------"
Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."commentable_id" = ? AND "comments"."commentable_type" = ? [["commentable_id", 1], ["commentable_type", "Message"]]
#<ActiveRecord::Associations::CollectionProxy []>
(0.1ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."commentable_id" = ? AND "comments"."commentable_type" = ? [["commentable_id", 1], ["commentable_type", "Message"]]
0
CACHE (0.0ms) SELECT "messages".* FROM "messages" WHERE "messages"."id" = ? LIMIT 1 [["id", "1"]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 2]]
Rendered comments/_form.html.erb (1.0ms)
Rendered messages/show.html.erb within layouts/application (1.9ms)
Completed 200 OK in 40ms (Views: 34.5ms | ActiveRecord: 0.4ms)
Why are you outputting in the show action?
You should only be defining #instance_variables and passing them to the view for rendering:
#config/routes.rb
resources :users do
resources :comments, only: [:show, :create]
end
#app/controllers/messages_controller.rb
class MessagesController < ApplicationController
def show
#message = Message.find params[:id]
end
end
#app/views/messages/show.html.erb
<%= #message.title %>
<%= render #message.comments if #message.comments.any? %>
#app/views/messages/_comment.html.erb
<% comment.title %>
<% comment.body %>
This will output the top-level comments.
If you wanted nested comments, I'd highly recommend using acts_as_tree. This gives you access to "child" objects (set with a parent column in your table), which allows you to do the following:
<%= render #message.comments if #message.comments.any? %>
#app/views/messages/_comment.html.erb
<%= render comment.children if comment.children.any? %>
Notes
1. Vars
When you run a loop (<% #message.comments.each do |comment| %>), you need to use the local variable within the block:
#message.comments.each do |comment|
comment.title
comment.body
end
You're currently using #comment.title -- should be comment.title
-
2. Comment Creation
You can make comment creation through a form embedded in the messages#show view:
#app/views/messages/show.html.erb
<%= render "comments/new" %>
You'd have to make sure you set your #comment variable:
#app/controllers/messages_controller.rb
class MessagesController < ApplicationController
def show
#message = Message.find params[:id]
#comment = Comment.new
end
end
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
#comment = Comment.new comment_params
end
private
def comment_params
params.require(:comment).permit(:title, :body)
end
end
You're doing this already, of course - I think it could be cleared up a lot.
-
3. Migration
Finally, you're using a polymorphic association in your table. This should not be used in this case; you should have a standard foreign_key as follows:
create_table "comments", force: :cascade do |t|
t.integer "message_id"
t.string "title"
t.text "body"
t.string "subject"
t.integer "user_id", null: false
t.integer "parent_id"
t.datetime "created_at"
t.datetime "updated_at"
end
This would allow for the following:
#app/models/message.rb
class Message < ActiveRecord::Base
has_many :comments
end
#app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :message
belongs_to :user
acts_as_tree
end

Input fields showing nil in Rails database

I created a cookbook scaffold, allowing users to create many cookbooks. I associated the user_id to the cookbook in the controller, but the title and description is showing up nil in the rails database.
class CookBooksController < ApplicationController
before_action :set_cook_book, only: [:show, :edit, :update, :destroy]
# GET /cook_books
# GET /cook_books.json
def index
#cook_books = CookBook.all
end
# GET /cook_books/1
# GET /cook_books/1.json
def show
end
# GET /cook_books/new
def new
#cook_book = CookBook.new()
end
# GET /cook_books/1/edit
def edit
end
# POST /cook_books
# POST /cook_books.json
def create
#cook_book = CookBook.new(cook_book_params)
#cook_book.user_id = current_user.id
respond_to do |format|
if #cook_book.save
format.html { redirect_to #cook_book, notice: 'Cook book was successfully created.' }
format.json { render :show, status: :created, location: #cook_book }
else
format.html { render :new }
format.json { render json: #cook_book.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /cook_books/1
# PATCH/PUT /cook_books/1.json
def update
respond_to do |format|
if #cook_book.update(cook_book_params)
format.html { redirect_to #cook_book, notice: 'Cook book was successfully updated.' }
format.json { render :show, status: :ok, location: #cook_book }
else
format.html { render :edit }
format.json { render json: #cook_book.errors, status: :unprocessable_entity }
end
end
end
# DELETE /cook_books/1
# DELETE /cook_books/1.json
def destroy
#cook_book.destroy
respond_to do |format|
format.html { redirect_to cook_books_url, notice: 'Cook book was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cook_book
#cook_book = CookBook.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def cook_book_params
params.require(:cook_book).permit(:title, :user_id, :description)
end
end
class CookBook < ActiveRecord::Base
belongs_to :users
end
ActiveRecord::Schema.define(version: 20140811235307) do
create_table "cook_books", force: true do |t|
t.string "title"
t.integer "user_id"
t.string "description"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "pages", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.text "header"
end
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "username"
t.string "country"
t.string "address"
t.string "provider"
t.string "uid"
t.boolean "admin", default: false
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Any help appreciate it! thank you
EDIT! Form added
<%= form_for(#cook_book) do |f| %>
<% if #cook_book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#cook_book.errors.count, "error") %> prohibited this cook_book from being saved:</h2>
<ul>
<% #cook_book.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
EDIT! Server Log
Started GET "/cook_books/new" for 127.0.0.1 at 2014-08-12 02:21:05 -0400
ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by CookBooksController#new as HTML
Rendered cook_books/_form.html.erb (30.2ms)
Rendered cook_books/new.html.erb within layouts/application (36.9ms)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Rendered layouts/_header.html.erb (28.2ms)
Completed 200 OK in 335ms (Views: 306.3ms | ActiveRecord: 1.7ms)
Started POST "/cook_books" for 127.0.0.1 at 2014-08-12 02:21:15 -0400
Processing by CookBooksController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"TNDketl0ixC8Lh/aAWIGf7SWeiwHZR9ITlEEpa7/+xM=", "cook_book"=>{"title"=>"Test title", "description"=>"test description "}, "commit"=>"Create Cookbook"}
**WARNING: Can't mass-assign protected attributes for CookBook: title, description
app/controllers/cook_books_controller.rb:28:in `create'** (Just saw this)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
(0.1ms) begin transaction
SQL (0.9ms) INSERT INTO "cook_books" ("created_at", "updated_at", "user_id") VALUES (?, ?, ?) [["created_at", "2014-08-12 06:21:15.547634"], ["updated_at", "2014-08-12 06:21:15.547634"], ["user_id", 1]]
(1.4ms) commit transaction
Redirected to http://localhost:3000/cook_books/8
Completed 302 Found in 29ms (ActiveRecord: 2.9ms)
Started GET "/cook_books/8" for 127.0.0.1 at 2014-08-12 02:21:15 -0400
Processing by CookBooksController#show as HTML
Parameters: {"id"=>"8"}
CookBook Load (0.4ms) SELECT "cook_books".* FROM "cook_books" WHERE "cook_books"."id" = ? LIMIT 1 [["id", 8]]
Rendered cook_books/show.html.erb within layouts/application (1.4ms)
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Rendered layouts/_header.html.erb (2.3ms)
Completed 200 OK in 34ms (Views: 30.9ms | ActiveRecord: 0.7ms
)
EDIT! Model
class CookBook < ActiveRecord::Base
belongs_to :users
end
Your Code is fine,but when looked at the server log,you have this warning
Can't mass-assign protected attributes for CookBook: title,
description
And from the comments,it is confirmed that you have this gem protected_attributes.This adds the default attr_accessible.But when it comes with Rails4,this gem is not required.You need to remove it to get the things work.
A small note:
As #Jaugar Chang pointed,you have belongs_to :users.It should be belongs_to :user.It would lead to further problems.

Resources