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
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.
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.
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
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
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.