I have two models that I am trying to associate. I have Users that have_many jobs. I set the associations in each model and added a foreign_id to the job model. When a user fills out the form to post a job the user_id returns nil. What am I doing wrong? Do I need to add anything to my create action? Should there be an added field in my form for the foreign_key? Here's what I have so far. Thanks.
create_table "jobs", :force => true do |t|
t.string "category"
t.string "title"
t.text "description"
t.string "location"
t.integer "needed"
t.decimal "pay"
t.string "how"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.decimal "hours"
t.date "start_date"
t.integer "user_id"
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
class Job < ActiveRecord::Base
belongs_to :user
attr_accessible :category, :description, :how, :location, :needed, :pay, :start_date, :title,:hours
validates :category, :title, :description, :how, :location, :needed,:hours, :pay,:start_date, presence: true
validates :pay, :numericality => { :greater_than => 7.99 }
end
class User < ActiveRecord::Base
has_many :jobs, dependent: :destroy
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
# attr_accessible :title, :body
end
Yes, In your create action of JobsController you have to write something like:
current_user.jobs.build(params[:job])
or
#user.jobs.build(params[:job])
instead of
Job.new(params[:job])
Related
I'm having trouble creating Sign up to my rails app, I'm using Devise and Simple_form, I have 2 models (User and department), users belongs_to :department and department has_many :users, i get an error when i try to sign up saying that department must exits.
devise/registrations/new.html.erb
<h2>Sign up</h2>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :username, required: true, autofocus: true %>
<%= f.input :email, required: true %>
<%= f.input :password, required: true, hint: ("#{#minimum_password_length} characters minimum" if #minimum_password_length) %>
<%= f.input :password_confirmation, required: true %><br>
<%= f.association :department %>
</div>
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
user.rb :
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates_uniqueness_of :email, :username
belongs_to :department
has_and_belongs_to_many :courses
end
department.rb :
class Department < ApplicationRecord
has_many :users
has_many :courses
end
I populated the departments table using seeds.rb and checked through mysql console.
schema.rb :
ActiveRecord::Schema.define(version: 20180502071349) do
create_table "courses", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t|
t.string "name"
t.text "description"
t.bigint "department_id"
t.string "instructor_name"
t.integer "credit_hours"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["department_id"], name: "index_courses_on_department_id"
end
create_table "departments", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t|
t.string "name"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "enrollments", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t|
t.bigint "user_id"
t.bigint "courses_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["courses_id"], name: "index_enrollments_on_courses_id"
t.index ["user_id"], name: "index_enrollments_on_user_id"
end
create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "username", default: "", null: false
t.bigint "department_id"
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", null: false
t.datetime "updated_at", null: false
t.index ["department_id"], name: "index_users_on_department_id"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["username"], name: "index_users_on_username", unique: true
end
add_foreign_key "courses", "departments"
add_foreign_key "enrollments", "courses", column: "courses_id"
add_foreign_key "enrollments", "users"
add_foreign_key "users", "departments"
end
migration files:
class CreateDepartments < ActiveRecord::Migration[5.1]
def change
create_table :departments do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
# frozen_string_literal: true
class DeviseCreateUsers < ActiveRecord::Migration[5.1]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
t.string :username, null: false, default: ""
t.references :department, foreign_key: true
## 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, 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
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :username, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
class CreateCourses < ActiveRecord::Migration[5.1]
def change
create_table :courses do |t|
t.string :name
t.text :description
t.references :department, foreign_key: true
t.string :instructor_name
t.integer :credit_hours
t.timestamps
end
create_table :enrollments do |t|
t.references :user, foreign_key: true
t.references :courses, foreign_key: true
t.timestamps
end
end
end
P.S., I'm just starting out with rails and thanks for your help.
Error screenshot:
Devise doesn't know anything about your none standard department_id field and filters it as unpermitted parameter.
Create your own registrations controller (which extends Devise) and then customize these methods:
def sign_up_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :department_id)
end
This is just a sample. Feel it in with your real field names
Rails since 5.1 or so has a required belongs_to validation with newly generated apps.
You can disable that by:
class User < ApplicationRecord
belongs_to :department, optional: true
end
In this way, you can create users with an empty department first.
error: thrown from the form
undefined method `profession_id' for #<DirectoryMember:0xa12be40>
env:
Rails: 5.0.0.1
Ruby: 2.2.4
form.html.erb
<%= f.collection_select(:profession_id, #professions, :id, :title, {:include_blank => true, :prompt => true}) %>
routes.rb
resources :directory_members
directory_members.rb
#professions = Profession.all.order(:title)
def directory_member_params
params.require(:directory_member).permit(
:user_id,
:directory_id,
:name,
:company,
:profession_id,
:address,
:phone,
:facebook,
:video,
:twitter,
:linkedin,
:google_plus,
:youtube
)
end
schema.rb
create_table "directory_members", force: :cascade do |t|
t.integer "user_id"
t.integer "directory_id"
t.string "name"
t.string "company"
t.text "address"
t.string "phone"
t.string "facebook"
t.string "video"
t.string "twitter"
t.string "linkedin"
t.string "google_plus"
t.string "youtube"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "profession_id"
end
I have ran rake db:migrate and all seems fine until the page is rendered.
Any clues as to why this is throwing the error would be awesome. Thanks
I am using Simple Form and the Invoicing gem, but when I try to render the form, I get "RuntimeError in InvoicingLedgerItems#new" with "Association :sender_id not found". I want to save the primary key of the Users table (Devise gem) in the sender_id field (because the user is the sender of the invoice). I tried using the foreign_key option in the model, but it didn't seem to have any effect. Here's my code without using the foreign_key option.
Models:
class InvoicingLedgerItem < ActiveRecord::Base
acts_as_ledger_item
belongs_to :user
has_many :line_items, class_name: 'InvoicingLineItem', foreign_key: :ledger_item_id
accepts_nested_attributes_for :line_items
end
class User < ActiveRecord::Base
has_many :invoicing_ledger_items
end
View:
<%= simple_form_for #invoicing_ledger_item do |f| %>
<%= f.association :sender_id %>
<%= f.button :submit %>
<% end %>
Schema:
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.datetime "deleted_at"
end
create_table "invoicing_ledger_items", force: true do |t|
t.integer "sender_id"
t.integer "recipient_id"
t.string "type"
t.datetime "issue_date"
t.string "currency", limit: 3, null: false
t.decimal "total_amount", precision: 20, scale: 4
t.decimal "tax_amount", precision: 20, scale: 4
t.string "status", limit: 20
t.string "identifier", limit: 50
t.string "description"
t.datetime "period_start"
t.datetime "period_end"
t.string "uuid", limit: 40
t.datetime "due_date"
t.datetime "created_at"
t.datetime "updated_at"
end
You Need to Make a relation with user model through foreign key 'sender_id'
Model
class InvoicingLedgerItem < ActiveRecord::Base
acts_as_ledger_item
belongs_to :user, foreign_key: :sender_id
has_many :line_items, class_name: 'InvoicingLineItem', foreign_key: :ledger_item_id
accepts_nested_attributes_for :line_items
end
Need to make association with user as hidden field
View:
<%= simple_form_for #invoicing_ledger_item do |f| %>
<%= f.association :user, :as => :hidden, :input_html => { :value => curren_user.id } %>
<%= f.button :submit %>
<% end %>
You should use user_id instead of sender_id in the schema first.Then use alias_attribute :user_id, :sender_id in InvoicingLedgerItem model, through this helper method you can assign a new name to the field name.
For more reference visit http://api.rubyonrails.org/classes/Module.html.
When viewing a user's Show page, I Would like to display the teams the user is on followed by the number of members on each team. I am trying to understand how to write methods in the model for this functionality to happen.
class Membership < ActiveRecord::Base
attr_accessible :team_id, :user_id
belongs_to :team
belongs_to :user
end
class Team < ActiveRecord::Base
attr_accessible :name, :user_id
belongs_to :admin, :class_name => "User",:foreign_key => "user_id"
has_many :memberships
has_many :members, through: :memberships, source: :user
has_many :users, through: :memberships
end
class User < ActiveRecord::Base
belongs_to :team
has_many :teams, through: :memberships
has_many :memberships
end
ActiveRecord::Schema.define(:version => 20140211214838) do
create_table "memberships", :force => true do |t|
t.integer "team_id"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "teams", :force => true do |t|
t.string "name"
t.integer "user_id"
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, :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.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "username"
t.string "bio"
t.string "location"
end
end
You have the associations in place, you just need to iterate over the teams in the view. E.g something like:
# users/show.html.erb
...
<% #user.teams.each do |team| %>
<div><%= "#{team.name} (#{team.members.count})" %></div>
<% end %>
...
Depending on what else you're doing with the teams and members data, for performance reasons it may be a good idea to eager load some of the associations with the user.
I keep getting this exception: "SQLite3::SQLException: no such column: books.user_id: SELECT "books".* FROM "books" WHERE ("books".user_id = 4)". Which sounds like there is no user_id in the books table.
So I just installed the Foreigner plugin and added "t.integer :user_id, :null => false" and "add_foreign_key(:books, :users)" in the book migration file. I ran "rake db:migrate", but still it is giving me the same exception.
I am using Rails 3 in Windows and Devise to authenticate user.
HOME VIEW
<p><%= link_to "Add new Book",:controller =>"book", :action => 'new' %></p>
<% #books.each do |b| %>
<p><%= b.author%></p>
<p><%= b.title%></p>
<%end%>
HOME CONTROLLER
class HomeController < ApplicationController
def index
#user = current_user
#user.books||=Book.new
#books=#user.books
end
end
BOOK CONTROLLER
class BookController < ApplicationController
def new
#books = Book.new
# redirect_to :controller=>"home" ,:action=>"index"
end
def create
#books = Book.new(params[:book])
if #books.save
render "home/index"
#redirect_to :controller=>"home" ,:action=>"index"
else
render :action => 'new'
end
end
CREATE TABLE/BOOK MIGRATION
class CreateBooks < ActiveRecord::Migration
def self.up
create_table :books do |t|
t.text :title
t.text :author
t.integer :user_id, :null => false
t.timestamps
end
add_foreign_key(:books, :users)
end
BOOK VIEW
<h1>Book#new</h1>
<%= form_for(:book) do |f| %>
<p><%= f.text_field :title %></p>
<p><%= f.text_field :author %></p>
<p><%= f.submit "Add book"%>
BOOK MODEL
class Book < ActiveRecord::Base
belongs_to :user
end
USER MODEL
class User < ActiveRecord::Base
has_many :books
# Include default devise modules. Others available are:
# :token_authenticatable, :lockable, :timeoutable and :activatable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation,:firstname,:lastname,:school,:major,:sex,:zipcode
end
ROUTE
Campus::Application.routes.draw do
get "book/index"
get "book/edit"
get "book/new"
get "home/edit"
devise_for :users
resources :book
root :to=> "home#index"
match '/book/new' =>"home#index"
end
DATABASE SCHEMA
ActiveRecord::Schema.define(:version => 20110609055608) do
create_table "books", :force => true do |t|
t.text "title"
t.text "author"
t.integer "user_id", :null => false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "courses", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "strong_ins", :force => true do |t|
t.string "subject"
t.string "topic"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "password_salt", :default => "", :null => false
t.string "reset_password_token"
t.string "remember_token"
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"
t.datetime "updated_at"
t.string "firstname"
t.string "lastname"
t.text "school"
t.text "major"
t.string "sex"
t.integer "zipcode"
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
create_table "weak_ins", :force => true do |t|
t.string "subject"
t.string "topic"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
end
end
The user_id column should appear in the schema after running the migration. It's not in your listing, so I'd say that's the problem. Make sure rake db:migrate is completing without errors. You can redo the migration with rake db:rollback && rake db:migrate, if necessary.