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
Related
Ive installed geocoder gem but when i type the address in the form it doesnt save any params in the table, its just an empty object. is there something im missing?
The location model:
class Location < ApplicationRecord
attr_accessor :postcode, :longitude, :latitude
geocoded_by :postcode
after_validation :geocode, :if => :postcode_changed?
end
The location controller:
def create
#location = Location.new(location_params)
if #location.save
redirect_to message_path(current_user.id)
flash[:success] = "Success"
else
redirect_to root_path
flash[:danger] = "failed"
end
end
private
def location_params
params.require(:location).permit(:postcode, :user_id)
end
Here is the form:
<%= form_for #location, :url => locations_path do |f| %>
<p>
<%= f.label "postcode" %><br />
<%= f.text_field :postcode %>
<%= f.hidden_field :user_id, :value => current_user.id %>
</p>
<p><%= f.submit %></p>
<% end %>
And here is my schema:
create_table "locations", force: :cascade do |t|
t.string "postcode"
t.float "longitude"
t.float "latitude"
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_locations_on_user_id"
end
So the idea is that a user would enter his postcode in the form on his profile page his location would show for all the other users to see.
I may not have grasped the concept of it so any help or guidance would be much appreciated. Thanks
Oh and here is the table entry after save:
irb(main):011:0> Location.last
Location Load (0.4ms) SELECT "locations".* FROM "locations" ORDER BY "locations"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> #<Location id: 10, postcode: nil, longitude: nil, latitude: nil,
user_id: 9, created_at: "2017-10-17 09:40:43", updated_at: "2017-10-17 09:40:43">
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
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'm getting a rollback when trying to add a user to my DB and I'm not sure why.
I have three models:
company.rb
class Company < ActiveRecord::Base
acts_as_paranoid
has_many :locations, dependent: :destroy
has_many :users, dependent: :destroy
has_many :tests, through: :locations
has_many :reports, dependent: :destroy
accepts_nested_attributes_for :locations, :users
validates_presence_of :name
end
** user.rb **
class User < ActiveRecord::Base
acts_as_paranoid
devise :database_authenticatable,
:recoverable,
:rememberable,
:trackable,
:validatable,
:registerable
belongs_to :company
has_and_belongs_to_many :roles
end
** location.rb **
class Location < ActiveRecord::Base
acts_as_paranoid
belongs_to :company
has_many :network_hosts, dependent: :destroy
has_many :tests, dependent: :destroy
has_many :commands, dependent: :destroy
validates_presence_of :company, :identifier, :name
validates_uniqueness_of :identifier
delegate :security_percentage, to: :last_test, allow_nil: true
after_initialize :generate_identifier, if: -> { self.identifier.blank? }
def generate_identifier
self.identifier = SecureRandom.uuid.delete("-")
end
So, when a user wants to signup they need to enter company, location, and user information, which is controlled by my company_controller.rb
** company_controller.rb **
class CompanyController < ApplicationController
def new
#company = Company.new
1.times { #company.locations.build }
1.times { #company.users.build }
end
def create
#company = Company.new(company_params)
if #company.save
redirect_to root_url
else
render :new
end
end
private
def company_params
params.require(:company).permit(:name, locations_attributes: [:name], users_attributes: [:first_name, :last_name, :full_name, :email, :password, :password_confirmation])
end
end
The form is using the standard form_for with nested attributes so that I can hopefully make everything in one shot when the user clicks the submit button
** company/new.html.erb **
<%= form_for #company, :url => url_for( :controller => 'company', :action => 'new' ) do |f| %>
<div class="form-group">
<%= f.label "Company Name" %>
<%= f.text_field :name, class: "form-control", placeholder: "ACME Inc." %>
<%= f.fields_for :locations do | location_builder | %>
<%= location_builder.label "Location Name" %>
<%= location_builder.text_field :name, class: "form-control", placeholder: "Main Building" %>
<% end %>
</div>
<div class="form-group">
<%= f.fields_for :users do | user_builder | %>
<%= user_builder.label "First Name" %>
<%= user_builder.text_field :first_name, class: "form-control", placeholder: "John" %>
<%= user_builder.label "Last Name" %>
<%= user_builder.text_field :last_name, class: "form-control", placeholder: "Smith" %>
<%= user_builder.label "Full Name" %>
<%= user_builder.text_field :full_name, class: "form-control", placeholder: "John Smith" %>
<%= user_builder.label "Email" %>
<%= user_builder.email_field :email, class: "form-control", placeholder: "john#acme.com" %>
<%= user_builder.label "Password" %>
<%= user_builder.password_field :password, class: "form-control" %>
<%= user_builder.label "Confirm Password" %>
<%= user_builder.password_field :password_confirmation, class: "form-control" %>
<% end %>
</div>
<%= f.submit "Submit", class: "btn btn-large btn-success" %>
<% end %>
However, I'm getting a rollback in the logs that this isn't happening and can't figure out why.
Started POST "/signup" for 127.0.0.1 at 2015-08-07 13:49:22 -0400
Processing by CompanyController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"2OHwJ9UfEbfkZHjLdm9BfOd7jlRdvoEz0L4NRJCKl64=", "company"=>{"name"=>"ACME Brick", "locations_attributes"=>{"0"=>{"name"=>"Main House"}}, "users_attributes"=>{"0"=>{"first_name"=>"Testin", "last_name"=>"User", "full_name"=>"Test User", "email"=>"test#test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}}, "commit"=>"Submit"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = 7 ORDER BY "users"."id" ASC LIMIT 1
Role Load (0.3ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles"."deleted_at" IS NULL AND "roles_users"."user_id" = $1 [["user_id", 7]]
(0.1ms) BEGIN
Location Exists (0.3ms) SELECT 1 AS one FROM "locations" WHERE "locations"."identifier" = '3b7febb35ea740488788d43fcc5e989c' LIMIT 1
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = 'test#test.com' LIMIT 1
(0.1ms) ROLLBACK
Rendered company/new.html.erb within layouts/application (5.0ms)
Completed 200 OK in 108ms (Views: 32.2ms | ActiveRecord: 1.9ms | Solr: 0.0ms)
** Company Table **
class CreateCompanies < ActiveRecord::Migration
def change
create_table :companies do |t|
t.string :name
t.timestamps
end
end
end
** Location Table **
class CreateLocations < ActiveRecord::Migration
def change
create_table :locations do |t|
t.belongs_to :company, index: true
t.string :identifier
t.string :name
t.timestamps
end
end
end
** User Table **
class CreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.belongs_to :company, index: true
t.string :username
t.string :first_name
t.string :last_name
t.string :full_name
t.string :time_zone, :default => "Central Time (US & Canada)"
t.string :avatar_file_name
t.string :avatar_content_type
t.integer :avatar_file_size
t.datetime :avatar_updated_at
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :phone_number
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
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
## Token authenticatable
t.string :authentication_token
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
create_table :roles_users, :id => false do |t|
t.references :role, :user
end
end
def self.down
drop_table :users
drop_table :roles_users
end
end
** The error from logs **
Started POST "/signup" for 127.0.0.1 at 2015-08-07 18:12:54 -0400
Processing by CompanyController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"aAc83zKKlV4w1i2GhTqTo3ehtXP+tPvYbBBRq1ccYzA=", "company"=>{"name"=>"Test Co.", "locations_attributes"=>{"0"=>{"name"=>"Main"}}, "users_attributes"=>{"0"=>{"first_name"=>"John", "last_name"=>"Smith", "full_name"=>"John Smith", "email"=>"john#acme.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}}, "commit"=>"Submit"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = 7 ORDER BY "users"."id" ASC LIMIT 1
Role Load (0.3ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles"."deleted_at" IS NULL AND "roles_users"."user_id" = $1 [["user_id", 7]]
(0.1ms) BEGIN
Location Exists (0.3ms) SELECT 1 AS one FROM "locations" WHERE "locations"."identifier" = '0d759e5405084663a1c110d37f04573a' LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = 'john#acme.com' LIMIT 1
(0.1ms) ROLLBACK
Completed 422 Unprocessable Entity in 75ms
** [Airbrake] Notice was not sent due to configuration:
Environment Monitored? false
API key set? true
ActiveRecord::RecordInvalid (Validation failed: Locations company can't be blank):
app/controllers/company_controller.rb:10:in `create'
app/controllers/application_controller.rb:95:in `set_time_zone'
Rendered /Users/godzilla/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.9ms)
Rendered /Users/godzilla/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.7ms)
Rendered /Users/godzilla/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.2ms)
Rendered /Users/godzilla/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (15.6ms)
It references that the location identifier already exists, but it doesn't. This is something that is made on the fly when trying to create a new Location (notice the method generate_identifier in the location.rb model). On top of that, the user doesn't exist either.
Any ideas how to get around this problem?
When you write validates_presence_of :company it means that your company record has to exist at the time of location creation, but it is not fully saved yet. However, your location is still associated with the company object, and it will be saved correctly without this validation. I think you can validate on presence of company_id instead because company id becomes available during saving.
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.