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.
Related
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.
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
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.
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.
Currently I have an edit form as follows:
<li>
<%= form_for #ingredient do |f| %>
<span class="span2"><%= f.text_field :name, placeholder: "#{#ingredient.name}" %></span>
<span class="span1"><%= f.text_field :quantity, placeholder: "#{#ingredient.quantity}" %></span>
<span class="span1"><%= f.text_field :unit, placeholder: "#{#ingredient.unit}" %></span>
<span class="span3">Added: <%= #ingredient.updated_at.strftime("%d %b. at %H:%M") %></span>
<span class="span2"><%= f.text_field :expiration, placeholder: "#{#ingredient.expiration}" %></span>
<span class="span2"><%= f.submit "Submit", class: "btn btn-small" %></span>
<% end %>
</li>
When I click submit my log file shows the follow:
Started PATCH "/pantries/112" for 127.0.0.1 at 2014-04-29 18:03:35 -0400
Processing by PantriesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"NUSmadjWCVVLHOZmncKD5D48L+7ZMa3DEbZ9Y+Y+Pnc=", "pantry"=>{"name"=>"test1", "quantity"=>"1", "unit"=>"cup", "expiration"=>"2015-05-05"}, "commit"=>"Submit", "id"=>"112"}
[1m[35mUser Load (0.5ms)[0m SELECT "users".* FROM "users" WHERE "users"."remember_token" = '27ecdc04fc67375fd3567c89fbe831e4d4919d09' LIMIT 1
[1m[36mPantry Load (0.3ms)[0m [1mSELECT "pantries".* FROM "pantries" WHERE "pantries"."id" = $1 LIMIT 1[0m [["id", "112"]]
[1m[35m (0.2ms)[0m BEGIN
[1m[36m (0.1ms)[0m [1mCOMMIT[0m
Redirected to http://localhost:3000/users/1/pantry
Completed 302 Found in 6ms (ActiveRecord: 1.1ms)
It doesn't raise an error it just does not update at all, but says that the update completed successfully.
pantry.rb
class Pantry < ActiveRecord::Base
before_save { self.name = name.downcase }
belongs_to :user
validates :name, presence: true
validates :user_id, presence: true
end
pantries_controller
def update
#ingredient = Pantry.find(params[:id])
if #ingredient.update_attributes(params[ingredient_params])
redirect_to pantry_user_path(current_user), :flash => {info: "Ingredient Updated"}
else
redirect_to pantry_user_path(current_user), :flash => {info: "Failed"}
end
end
private
def ingredient_params
params.require(:pantry).permit(:name, :quantity, :unit, :expiration, :created_at, :updated_at)
end
schema:
create_table "pantries", force: true do |t|
t.string "name"
t.string "quantity"
t.string "unit"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.date "expiration"
end
add_index "pantries", ["expiration"], name: "index_pantries_on_expiration", using: :btree
add_index "pantries", ["quantity"], name: "index_pantries_on_quantity", using: :btree
add_index "pantries", ["unit"], name: "index_pantries_on_unit", using: :btree
If I replace #ingredients.update_attributes with #ingredient.update_column(:expiration, params[:pantry][:expiration]) the update takes place on that column. Falling back to update_column is not ideal. I understand update_attributes and update_attributes! call callbacks while update_column does not. I don't see any issue with the callbacks and no error messages are given. Anyone have an idea on what the issue might be?
Change your update action as below:
def update
#ingredient = Pantry.find(params[:id])
if #ingredient.update_attributes(ingredient_params) ## Call ingredient_params
redirect_to pantry_user_path(current_user), :flash => {info: "Ingredient Updated"}
else
redirect_to pantry_user_path(current_user), :flash => {info: "Failed"}
end
end
With Rails 4 strong parameters concept, you need to whitelist the attributes that you would like to be saved in database.
Currently, you are using params[ingredient_params] instead of calling ingredient_params which is causing this issue