Input fields showing nil in Rails database - ruby-on-rails

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.

Related

Rails rolling back twice every time I try to post Data

I am trying to create an app that allows users to make lists of items and view only the lists they themselves have created. Every time I press submit on the form this happens
Started POST "/lists" for 127.0.0.1 at 2017-08-18 15:56:40 -0400
Processing by ListsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"VnsMdQq3mw5XabkYCZFTgvgwFc3H89paHA0VE5gunFbiMfa0xGr0p1GEZDHc3yemwBx07K1h4CXuS0l5XL1VbA==", "list"=>{"income"=>"12", "put_into_savings"=>"12", "month"=>"12", "year"=>"21"}, "commit"=>"Create List"}
(0.1ms) begin transaction
(0.1ms) rollback transaction
(0.0ms) begin transaction
(0.0ms) rollback transaction
Rendering lists/new.html.erb within layouts/application
Rendered lists/new.html.erb within layouts/application (9.3ms)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 5], ["LIMIT", 1]]
Completed 200 OK in 269ms (Views: 222.2ms | ActiveRecord: 2.7ms)
Here is all my code:
lists_controller.rb
class ListsController < ApplicationController
def show
#user = User.find(params[:id])
#lists = #user.lists
end
def new
end
def edit
end
def create
#list = List.create(list_params)
if #list.save
redirect_to home_url
else
render :new
end
end
private
def list_params
params.require(:list).permit(:income, :put_into_savings, :month, :year)
end
end
lists/new.html.erb
<%= form_for List.new do |f| %>
<div class="field">
<%= f.label :income %><br />
<%= f.text_field :income %>
</div>
<div class="field">
<%= f.label :put_into_savings %><br />
<%= f.text_area :put_into_savings %>
</div>
<div class="field">
<%= f.label :month %><br />
<%= f.number_field :month %>
</div>
<div class="field">
<%= f.label :year %><br />
<%= f.number_field :year %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
schema.rb
ActiveRecord::Schema.define(version: 20170818185700) do
create_table "items", force: :cascade do |t|
t.string "item_name"
t.integer "item_cost"
t.string "item_waste"
t.string "item_group"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "lists", force: :cascade do |t|
t.integer "income"
t.integer "put_into_savings"
t.string "month"
t.string "year"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "Item_id"
t.integer "User_id"
end
create_table "users", force: :cascade do |t|
t.string "email"
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
end
Routes.rb
Rails.application.routes.draw do
root 'home#index'
get 'home' => 'home#index'
resources :lists
resources :sessions, only: [:new, :create, :destroy]
resources :users, only: [:new, :create]
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
Here is my list model:
class List < ApplicationRecord
has_many :items
belongs_to :user
end
How can I solve this?
You are having logic problem with your model association.
Assuming that a List could have more than one Item, you shouldn't have declared your table List with the attribute item_id. (Doing that it means a List could ONLY have one item). I recommend you read ruby-on-rais-guide-for-associations.
For the problem with the user_id, you need to explicit declared the user_id in your list object (considering that you want to associate a List with a User in the moment the List is created). One way to do it could be:
def create
#list = List.new(list_params)
#list[:user_id] = current_user.id # Considering you add this method
if #list.save
redirect_to home_url
else
render :new
end
And add some validation in model:
class List < ApplicationRecord
has_many :items
belongs_to :user
validates :user_id, presence: true
end
It seems you need to read more about validation too ruby-on-rais-guide-for-validation. About your twice rollback, it is unclear the reason, but fixing you association and validations problems, I think you can fix it.
Try read more about rails, the problem you are having are really basic. Good luck!
UPDATE:
As suggested by at0misk answer, to solve the problem with twice rollback:
In List controller:
#list = List.new(list_params)
# instead of #list = List.create(list_params)
The create method create a new object and save immediately. So, rails was trying to save twice, in the method create first, then in the method save in sequence.
In your create method, you're calling create and then calling save. Create creates an object and saves it to the database, so calling save is redundent.
Have you checked to see if your record is saving? If it is then this is definitely what's wrong. I prefer to use this pattern, using new instead of create, and then attempting to save in an if block:
def create
#list = List.new(list_params)
if #list.save
redirect_to home_url
else
render :new
end
end

nil value instead of form value

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.

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

Can't link user_id to new created object - rails 4

i am new to rails so any help would be much appreciated. I have the models userrs (recruiters) and adverts. Userr has_many adverts and Advert belongs to a user.
Question: when a userr creates an advert i want the created advert to
be automatically linked to the userr that created the advert. I am
unsure how to go about this in the controller
i know how to assign an advert to a user in the console. but unsure how to do this in the controller
console
advert = Advert.first
advert.userr_id = 3
advert.save
route
Rails.application.routes.draw do
resources :adverts
resources :feedbacks
devise_for :userrs
devise_for :userjs
root 'static_pages#homepg'
get 'affiliate', to: 'static_pages#affiliatepg'
get 'terms', to: 'static_pages#termpg'
get 'privacy', to: 'static_pages#privacypg'
get 'contact', to: 'static_pages#contactpg'
get 'about', to: 'static_pages#aboutpg'
get 'recruiters', to: 'static_pages#recruiterpg'
get 'jobseekers', to: 'static_pages#jobseekerpg'
get 'approach', to: 'static_pages#approachpg'
get 'sector', to: 'static_pages#sectorpg'
get 'news', to: 'static_pages#newspg'
get 'offer', to: 'static_pages#offerpg'
get 'refferal', to: 'static_pages#refferalpg'
end
i placed the below code:
in my advert controller under the create function:
def create
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.build(params[:advert])
if #advert.save
flash[:notice] = 'Successfully created advert'
redirect_to recruiters_path
else
render action: 'new'
end
end
but i got the error:
Couldn't find Userr without an ID
log - error message
Started GET "/adverts/new" for 127.0.0.1 at 2015-04-02 14:59:38 +0100
Processing by AdvertsController#new as HTML
Completed 404 Not Found in 1ms (ActiveRecord: 0.0ms)
ActiveRecord::RecordNotFound (Couldn't find Userr without an ID):
app/controllers/adverts_controller.rb:20:in `new'
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_source.erb (8.2ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_trace.html.erb (3.4ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_request_and_response.html.erb (0.8ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_web_console.html.erb (0.8ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/diagnostics.html.erb within rescues/layout (27.3ms)
Started GET "/adverts/new" for 127.0.0.1 at 2015-04-02 14:59:38 +0100
Processing by AdvertsController#new as HTML
Completed 404 Not Found in 1ms (ActiveRecord: 0.0ms)
ActiveRecord::RecordNotFound (Couldn't find Userr without an ID):
app/controllers/adverts_controller.rb:20:in `new'
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_source.erb (8.1ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_trace.html.erb (3.0ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_request_and_response.html.erb (0.9ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_web_console.html.erb (0.8ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/diagnostics.html.erb within rescues/layout (26.2ms)
Schema
ActiveRecord::Schema.define(version: 20150330233948) do
create_table "adverts", force: true do |t|
t.string "title"
t.text "content"
t.integer "category_jobtype_id"
t.integer "category_positiontype_id"
t.integer "salarystart"
t.integer "salaryend"
t.integer "category_country_id"
t.string "city"
t.string "town"
t.string "postcode"
t.integer "category_editorialapproval_id"
t.integer "category_applicationrequest_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "userr_id"
end
create_table "userrs", 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 "firstname"
t.string "lastname"
t.string "companyname"
t.integer "category_businesstype_id"
end
add_index "userrs", ["email"], name: "index_userrs_on_email", unique: true
add_index "userrs", ["reset_password_token"], name: "index_userrs_on_reset_password_token", unique: true
model
class Advert < ActiveRecord::Base
belongs_to :user
end
class Userr < ActiveRecord::Base
has_many :adverts
end
controller: Advert
class AdvertsController < ApplicationController
respond_to :html, :xml, :json
before_action :set_advert, only: [:show, :edit, :update, :destroy]
def index
#adverts = Advert.all
respond_with(#adverts)
end
def show
respond_with(#advert)
end
# def new
# #advert = Advert.new
# respond_with(#advert)
# end
def new
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.build
respond_with(#advert)
end
def edit
end
# def create
# #advert = Advert.new(advert_params)
# #advert.save
# respond_with(#advert)
# end
def create
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.build(params[:advert])
if #advert.save
flash[:notice] = 'Successfully created advert'
redirect_to recruiters_path
else
render action: 'new'
end
end
def update
#advert.update(advert_params)
respond_with(#advert)
end
def destroy
#advert.destroy
respond_with(#advert)
end
private
def set_advert
#advert = Advert.find(params[:id])
end
def advert_params
params.require(:advert).permit(:title, :content, :category_jobtype_id, :category_positiontype_id, :salarystart, :salaryend, :category_country_id, :city, :town, :postcode, :category_editorialapproval_id, :category_applicationrequest_id)
end
end
form for advert
<%= simple_form_for(#advert) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title %>
<%= f.input :content %>
<%= f.association :category_jobtype, collection: CategoryJobtype.all, prompt: "select a category" %>
<%= f.association :category_positiontype, collection: CategoryPositiontype.all, prompt: "select a category" %>
<%= f.input :salarystart %>
<%= f.input :salaryend %>
<%= f.association :category_country, collection: CategoryCountry.all, prompt: "select a category" %>
<%= f.input :city %>
<%= f.input :town %>
<%= f.input :postcode %>
<%= f.association :category_editorialapproval, as: :radio_buttons %>
<%= f.association :category_applicationrequest, as: :radio_buttons %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
any help will be appreciated
First, you need to add userr_id to params:
def advert_params
params.require(:advert).permit(:userr_id, :title, :content, :category_jobtype_id, :category_positiontype_id, :salarystart, :salaryend, :category_country_id, :city, :town, :postcode, :category_editorialapproval_id, :category_applicationrequest_id)
end
Second, add userr_id to the form:
<%= simple_form_for(#advert) do |f| %>
<%= f.hidden_field(:userr_id) %>
Third, change the param name in create:
def create
#userr = Userr.find(params[:advert][:userr_id])
You can do the same via routes, without altering the form. It's much cleaner but needs more source changes. I can't give you the full syntax here, but it will look like the following:
#routes.rb
resources :userrs do
resources :addverts
end
And the advert's form will become /userrs/[user-id]/adverts, so you'll be able to get the user id from the url instead of the form field. But you'll need to change all the path shortcuts.

Instance of Rails model only creatable through console

I've been following the tutorial on creating a Rails blog (http://www.roberthuberdeau.com/articles/4-How-to-create-a-blog-in-Ruby-on-Rails-3) and have basically got all the way to the end.
However, after all the migrations I'm now struggling. Whenever I complete the form I previously used to create articles, I can't see them on the index page. I've dug around and believe the root of the error is that I'm not saving any articles when I press 'create article'.
To test this, I created an article using the console and this is appearing as it should so I think the problem lies somewhere between the form that creates articles and the controller (though am happy to be corrected on this).
Whenever I try the following appears in the logs:
Started POST "/articles" for 127.0.0.1 at 2013-04-01 21:12:58 +0100
Processing by ArticlesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"XLeHm+4Tgd6n9vt4RxAQ5YVTbWTi+UnqkmBso9Iuo+4=", "article"=>{"title"=>"I rule", "body"=>"Change teams.", "tag_names"=>"kill", "published"=>"1"}, "commit"=>"Create Article"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Role Load (0.1ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles_users"."user_id" = 1 AND "roles"."name" = 'Admin' LIMIT 1
Role Load (0.1ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles_users"."user_id" = 1 AND "roles"."name" = 'Moderator' LIMIT 1
Role Load (0.1ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles_users"."user_id" = 1 AND "roles"."name" = 'Member' LIMIT 1
Redirected to http://localhost:3000/
Completed 302 Found in 5ms (ActiveRecord: 0.5ms)
With the database schema:
ActiveRecord::Schema.define(:version => 20130401171646) do
create_table "articles", :force => true do |t|
t.string "title"
t.text "body"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id", :null => false
t.boolean "published", :default => false
end
create_table "comments", :force => true do |t|
t.integer "article_id"
t.string "name"
t.string "email"
t.text "body"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "roles", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "roles_users", :id => false, :force => true do |t|
t.integer "role_id"
t.integer "user_id"
end
create_table "taggings", :force => true do |t|
t.integer "article_id"
t.integer "tag_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "tags", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
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
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", :null => false
t.datetime "updated_at", :null => 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
Articles controller:
class ArticlesController < ApplicationController
before_filter :authenticate_user!, :except => [:index, :show]
# GET /articles
# GET /articles.xml
def index
#articles = Article.published.page(params[:page]).per(5).ordered
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #articles }
end
end
# GET /articles/1
# GET /articles/1.xml
def show
#article = Article.find(params[:id])
#comment = Comment.new(:article=>#article)
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #article }
end
end
# GET /articles/new
# GET /articles/new.xml
def new
#article = Article.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #article }
end
end
# GET /articles/1/edit
def edit
#article = Article.find(params[:id])
authorize! :edit, #article
end
# POST /articles
# POST /articles.xml
def create
authorize! :create, #article
#article = Article.new(params[:article])
#article.user_id = current_user.id
respond_to do |format|
if #article.save
format.html { redirect_to(#article, :notice => 'Article was successfully created.') }
format.xml { render :xml => #article, :status => :created, :location => #article }
else
format.html { render :action => "new" }
format.xml { render :xml => #article.errors, :status => :unprocessable_entity }
end
end
end
# PUT /articles/1
# PUT /articles/1.xml
def update
#article = Article.find(params[:id])
authorize! :update, #article
respond_to do |format|
if #article.update_attributes(params[:article])
format.html { redirect_to(#article, :notice => 'Article was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #article.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.xml
def destroy
#article = Article.find(params[:id])
authorize! :destroy, #article
#article.destroy
respond_to do |format|
format.html { redirect_to(articles_url) }
format.xml { head :ok }
end
end
end
Articles model:
class Article < ActiveRecord::Base
attr_accessible :body, :title, :tag_names
has_many :comments, :dependent => :destroy
has_many :taggings, :dependent => :destroy
has_many :tags, :through => :taggings
validates_presence_of :title, :body
validates_uniqueness_of :title
attr_writer :tag_names
after_save :assign_tags
validates_numericality_of :user_id
belongs_to :user
scope :published, lambda {{:conditions => ['published = ?', true]}}
scope :ordered, lambda {{:order => "Created_at DESC" }}
def tag_names
#tag_names || tags.map(&:name).join(' ')
end
private
def assign_tags
if #tag_names
self.tags = #tag_names.split(/\,/).map do |name|
Tag.find_or_create_by_name(name)
end
end
end
end
And the form partial used to create the article:
<%= form_for(#article) do |f| %>
<% if #article.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#article.errors.count, "error") %> prohibited this article from being saved:</h2>
<ul>
<% #article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="field">
<%= f.label :tag_names, "Tags" %>
<%= f.text_field :tag_names %>
</div>
<div class="field">
<%= check_box("article", "published" ) %>
<%= "Publish article" %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Any help you can give me on this would be greatly appreciated.
By request:
Ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.role? :Admin
can :manage, :all
can :publish, Article
elsif user.role? :Moderator
can :read, [Article, Comment]
can [:edit, :update], Comment
elsif user.role? :Member
can :read, :all
can :create, [Article, Comment]
can [:edit, :update], Comment
end
end
end
p.s. the only other error I can see (and I don't know if it's relevant or a different issue entirely) is that when trying to view an article (show.html.erb) I receive the following error:
Processing by ArticlesController#show as HTML
Parameters: {"id"=>"1"}
Article Load (0.2ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT 1 [["id", "1"]]
Completed 500 Internal Server Error in 44ms
ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: article):
app/controllers/articles_controller.rb:18:in `new'
app/controllers/articles_controller.rb:18:in `show'
I'm guessing there's a problem with the authorize! :create, #article line in the ArticleController.create. At the point that that executes, #article isn't created yet.
Judging by the CanCan source, I think the following might do what you want:
def create
authorize! :create, Article
#article = Article.new(params[:article])
#article.user_id = current_user.id
...
The article is not being created because of this.
authorize! :create, #article
You will have to show us your ability model, ability.rb.
You might also want to try the obvious. bundle install and restart the server.

Resources