Belongs_to only recognized by console, not server - ruby-on-rails

I've got a really weird problem with my project. I've got 2 models, the one is Link and the other Category. I've got a index view where all the links should be listed, together with the corresponding category names. When running the server and trying to use
<%= link.category.name %>
I get an error page with the following:
undefined method `name' for nil:NilClass
But when I open the console and write:
link = Link.find(1) #there is currently only one link
link.category.name
It returns the correct category name.
Here are my Models and schema.rb:
class Link < ActiveRecord::Base
attr_accessible :category_id, :description, :title, :url, :visible
belongs_to :category
scope :visible, lambda { where(visible: true) }
end
.
class Category < ActiveRecord::Base
attr_accessible :name
has_many :links
end
.
ActiveRecord::Schema.define(:version => 20130420070717) do
create_table "categories", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "categories", ["id"], :name => "index_categories_on_id"
create_table "links", :force => true do |t|
t.string "title"
t.text "description"
t.string "url"
t.integer "category_id"
t.boolean "visible"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "links", ["category_id"], :name => "index_links_on_category_id"
add_index "links", ["id"], :name => "index_links_on_id"
end
How can this happen? Thank you very much for your help!

Maybe I can help others facing the same issue.
The category_id was assigned to the link by a form which queries the existing categories from the db.
<%= f.select(:category_id, #categories.collect { |c| c.name }) %>
The category I wanted to assign has the id = 1. After selecting the category from the dropdown menu, the link.category_id was 0, it should have been 1.
UPDATE:
I fixed the wrong index by:
<%= f.collection_select :category_id, #categories, :id, :name, :prompt => "Select a category" %>

Related

I keep getting this error <undefined method `category_id' for #<ActionController::Parameters>>

Im currently trying to create a search form and everytime I try to send a request rails always report me the NoMethodError above. Below is my code.
controller
#search_cat = params['search_cat']
if #search_cat.present?
category_id = #search_cat['category_id']
#tasks = Task.where(user_id: current_user.id, category_id: category_id.to_i)
end
view
<%= simple_form_for :search_cat, url: tasks_index_path, method: "GET", html: { class: 'form-inline' } do |f| %>
<%= f.input :category_id, collection: current_user.categories,as: :select %>
<%= f.submit "Search", class: "btn btn-primary" %>
<% end %>
def tasks_params
params.require(:task).permit(:deadline_at,:title, :tags, :note, :is_done, :category_id, :user_id, {tag_ids: []})
end
edit:
class Task < ApplicationRecord
belongs_to :user, optional: true
belongs_to :category, optional: true
has_many :tag_associations, dependent: :destroy
has_many :tags, through: :tag_associations
end
schema
create_table "tasks", force: :cascade do |t|
t.datetime "deadline_at"
t.string "title"
t.string "note"
t.boolean "is_done"
t.integer "user_id"
t.integer "category_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["category_id"], name: "index_tasks_on_category_id"
t.index ["user_id"], name: "index_tasks_on_user_id"
I basiclly just trying send the input from the search form to query controller.
enter image description here
My guess would be that you don't have a category reference set in your task table. I would double check your schema to make sure you have all the columns within your task table match your params that you are permitting in your controller. Also make sure you have your relationships set within your models between your task model and category model.

How to use a form to add to both joined tables in Rails

I have a joined table but looking for a way to input the information from a form into both tables, or have it work in general:
My schema:
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "categories_listings", id: false, force: :cascade do |t|
t.integer "category_id", null: false
t.integer "listing_id", null: false
end
create_table "listings", force: :cascade do |t|
t.string "name"
t.text "description"
t.decimal "price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image"
t.integer "user_id"
end
Models:
class Category < ApplicationRecord
has_and_belongs_to_many :listings
end
Listing < ApplicationRecord
belongs_to :category, required: false
belongs_to :categories_listings, required: false
end
Views
<%= form_with(model: listing, local: true) do |form| %>
...
<div class="space">
<%= form.select :category_ids, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select a Category", :multiple => true %>
</div>
...
Before i joined the tables, I had it working with a categories element (i believe thats the right term) within the listing tables that was attached to a categories table... You can see my previous post on SO where I was suggested to do this: Allowing multiple records in category to submit to listing
When i click submit, nothing enters into the categories_listings tables. Suggestions on how I make this happen?
The associations in your Listing model are wrong. It should be just
Listing < ApplicationRecord
has_and_belongs_to_many :categories
end
I suggest you to read has_and_belongs_to_many

How can I display the name instead of an ID in rails

I am trying to have a drop down from the other model and display its name in the index page
I have a 3 tables "students", "classrooms", and "classroom_students"
what I am trying is when a student is created he should be able to add the classroom from a dropdown which is populated from classroom table, at the moment the drop down is working however it is getting the id from the dropdown
How to get the classroom name to display in index page
classroom model
class Classroom < ApplicationRecord
belongs_to :user
has_many :classroom_students
has_many :students, through: :classroom_students
end
student model
class Student < ApplicationRecord
has_many :classroom_students
has_many :classrooms, through: :classroom_students
validates :student_fname, presence: true, length: { minimum: 3, maximum: 50 }
end
classroom_student model
class ClassroomStudent < ApplicationRecord
belongs_to :classroom
belongs_to :student
end
students controller
def student_params
params.require(:student).permit(:student_fname, :student_lname, :gender, :dob, :aboriginal, :esl, :special_provisions, :user_id, :classroom_id, :group_id, :active)
end
classrooms controller
def classroom_params
params.require(:classroom).permit(:classroom_name, :classroom_year, :classroom_student)
end
students views form
<%= form.select :classroom_id, Classroom.where(:user_id => current_user.id).map {|r| [r.classroom_name, r.id]} %>
student index
at the moment it is id but I want it to be classroom name
<td><%= student.classroom_id %>
Schema file
create_table "classroom_students", force: :cascade do |t|
t.integer "classroom_id"
t.integer "student_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "classrooms", force: :cascade do |t|
t.string "classroom_name"
t.date "year"
t.string "classroom_student"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "users_id"
t.integer "user_id"
t.string "classroom_year"
t.index ["users_id"], name: "index_classrooms_on_users_id"
end
create_table "students", force: :cascade do |t|
t.string "student_fname"
t.string "student_lname"
t.boolean "gender"
t.string "dob"
t.boolean "aboriginal"
t.boolean "esl"
t.text "special_provisions"
t.integer "user_id"
t.integer "classroom_id"
t.integer "group_id"
t.boolean "active"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "classroom_name"
end
Your association says that student has many classrooms but your database schema says you have a clasroom_id too in the students table. Remove that classroom_id first if you need to associate a student to multiple classrooms. Then your select says:
<%= form.select :classroom_id, Classroom.where(:user_id => current_user.id).map {|r| [r.classroom_name, r.id]} %>
Now as you have multiple classrooms associated to one student so this will not work because classroom_id is not valid. Instead it should be like this:
<%= f.select :classroom_ids, Classroom.where(user_id: current_user.id).map { |r| [r.classroom_name, r.id] }, {}, multiple: true %>
This will associate multiple classrooms with the student.
And donot forget to add classroom_ids in strong params:
def student_params
params.require(:student).permit(:student_fname, :student_lname, :gender, :dob, :aboriginal, :esl, :special_provisions, :user_id, :classroom_id, :group_id, :active, :classroom_ids => [])
end
Hope this helps.
First of all, you have an association User has_many :classrooms, so you can't think that you only have 1 classroom.
You can get all the classes associated to an user with something like this:
<%= f.form_for #student do |f| %>
<%= f.collection_select(:classrrom_id, Classroom.all, :id, :classroom_name,
{:prompt => "Select your classrooms"}, {:multiple => true}) %>
<% end %>
And at your students_controller.rb you should add classroom_ids to your params
def student_params
params.require(:student).permit(:student_fname, :student_lname, :gender,
:dob, :aboriginal, :esl, :special_provisions, :user_id, :classroom_id,
:group_id, :active, :classroom_ids => [])
end

Scope and Filters for Views in Rails [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I have a small app going that lets 'Employees' check in and check out 'Items' by virtue of 'Transactions'. Those are the models in play. I'm having a hard time showing the items that are CURRENTLY checked out - and while I've read about scopes I'm having a hard time getting the associations, scopes, and views to work. I'm pulling my hair out - and I'm new to rails, so please be gentle.
I'm not too worried about performance with this app, and I know that nested conditionals within views are a terrible thing, and I know that I should be using partials, but this is really just for an MVP.
db/schema.rb
ActiveRecord::Schema.define(:version => 20130516162824) do
create_table "employees", :force => true do |t|
t.string "phone"
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "items", :force => true do |t|
t.string "description"
t.string "assettag"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "transactions", :force => true do |t|
t.boolean "status"
t.integer "item_id"
t.integer "employee_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "transactions", ["employee_id"], :name => "index_transactions_on_employee_id"
add_index "transactions", ["item_id"], :name => "index_transactions_on_item_id"
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
models/employee.rb
class Employee < ActiveRecord::Base
attr_accessible :name, :phone
has_many :transactions
has_many :items, :through => :transactions
end
models/item.rb
class Item < ActiveRecord::Base
attr_accessible :assettag, :description
has_many :transactions
has_many :employees, :through => :transactions
scope :checked_out, -> { last_transaction.checkout }
end
models/transaction.rb
class Transaction < ActiveRecord::Base
attr_accessible :employee_id, :item_id, :status
belongs_to :employee
belongs_to :item
delegate :phone, :name, to: :employee
delegate :description, :assettag, to: :item
scope :last_transaction, -> { order('created_at DESC').limit(1) }
scope :checkin, where(:status => true)
scope :checkout, where(:status => false)
end
app/views/employees/show.html.erb
<% if #employee.items.checked_out %>
<h3>Currently Checked-OUT Items</h3>
<table>
<tr>
<th>Item ID</th>
<th style="padding-left:30px">Asset Tag</th>
</tr>
<% #employee.transactions.items.checked_out.reverse.each do |transaction| %>
<tr>
<td style="padding-left:30px">
<%= transaction.description %>
</td>
<td style="padding-left:30px">
<%= transaction.assettag %>
</td>
</tr>
<% end %>
</table>
<% end %>
The problem is that you want the employee's items, but the field that supplies the condition is on the model in between the items and conditions. One way is to add some more associations to your employee model.
class Employee < AR::Base
has_many :current_transactions, :conditions => { :status => CHECKED_OUT }
has_many :checked_out_items, :through => :current_transactions
end
last_transaction is defiend on transaction which is is why you get the no method error. That scope should be
scope :checked_out, -> { transactions.last_transaction.checkout }
if you want all the transactions then remove last_transactions scope
scope :checked_out, -> { transactions.checkout }

Can't get association working in form

I'm having difficulties getting an association to work with simple_form.
I have the following models.
class Product < ActiveRecord::Base
belongs_to :Retailer
end
and
class Retailer < ActiveRecord::Base
has_many :Products
end
My form partial (products/_form.html.erb) contains the following
<%= simple_form_for(#product) do |f| %>
...
<% f.input :currency %>
<% f.association :retailer %>
...
It works without the association, but with it I get the following error:
undefined method `retailer_id' for #<Product:0x007ffbe0f7d530>
I'm (obviously) quite new to this, but haven't been able to work this out.
edit: checked I'd run migrations and they are up-to-date. The Retailer table has an id column!
> Retailer.all
Retailer Load (0.2ms) SELECT "retailers".* FROM "retailers"
=> [#<Retailer id: 1, name: "Retailer 1" etc...
chema file:
ActiveRecord::Schema.define(:version => 20120308195055) do
create_table "alerts", :force => true do |t|
t.string "url", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "products", :force => true do |t|
t.string "title", :null => false
t.integer "price_cents", :default => 0, :null => false
t.string "currency", :null => false
t.string "asin", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "retailers", :force => true do |t|
t.string "name", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end
Since you have belongs_to :Retailer and <% f.association :retailer %> in your model and form for Product respectively, you'll need to add a retailer_id column to your products table.
You are missing t.references :retailer in your migration file for creating products table.
That is why, I quote you "it works without the association, but with it the error is undefined method 'retailer_id' for #<Product:0x007ffbe0f7d530>"
Yes, the retailers table has an id column but in order to reference a retailer from a product, your products table requires a retailer_id column.

Resources