Rails not getting value from associations - ruby-on-rails

I have 2 tables named : order_items and orders in schema. Following is sample of my schema
create_table "orders", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "token"
t.decimal "sub_total"
t.string "mobile"
t.string "address"
and
create_table "order_items", force: :cascade do |t|
t.integer "order_id", null: false
t.integer "item_id", null: false
t.integer "quantity", null: false
t.decimal "price", precision: 15, scale: 2, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
For Models,
order.rb
has_many :order_items
order_item.rb
belongs_to :order
belongs_to :item
I thought I would have been able to get Order.orderitem.quantity with this association, but not able to get it. I get error as undefined method 'orderitems' for nil:NilClass

try Order.first.order_items
this will return all the order items for first order
then you can loop through them
Order.first.order_items.each do |item|
item.quantity
....
end
or take the item out with index
items = Order.first.order_items
items[0].quantity

Related

How to use a Link table with Active Record query interface

I am still relatively new to Active Record and have a (hopefully simple) question.
I have four tables Recipes(Name of recipe), Food(lettuce, Pepper), Units(oz, tbsp), and Ingredients(Id's of the other tables and the numeric quantity).
What I'd like to do is something like this Recipes.Ingredients and get "Peppered Lettuce, 5 tbsp pepper, 10 oz Lettuce".
How would I accomplishes that with the following schema. And if not possible with this schema what should I build in its place.
The Schema looks like this:
create_table "food", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "ingredients", force: :cascade do |t|
t.bigint "recipes_id"
t.bigint "units_id"
t.bigint "food_id"
t.decimal "quantity"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["food_id"], name: "index_ingredients_on_food_id"
t.index ["recipes_id"], name: "index_ingredients_on_recipes_id"
t.index ["units_id"], name: "index_ingredients_on_units_id"
end
create_table "recipes", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
create_table "units", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
so what I understand from your question is you want to get results like:
Peppered Lettuce, 5 tbsp pepper, 10 oz Lettuce in which Peppered Lettuce is Recipe name, and Pepper and Lettuce are Food items with numeric quantities of ingredients.
You don't need 4 tables to obtain this result. You only need 3. Food, Recipe and an in-between table for their many-to-many association.
Recipe can have multiple Food items in it and 1 Food item can be a part of multiple Recipe objects. So Food and Recipe model will have a many-to-many association. And for this kind of association, you need another table. You can name it Foods_Recipes or simply Ingredients.
Your Ingredient model will then have a food_id,recipe_id,numeric_quantity and unit_type
The Schema would look like this:
create_table "foods", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "ingredients", force: :cascade do |t|
t.bigint "recipe_id"
t.bigint "food_id"
t.decimal "quantity"
t.string "unit_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["food_id"], name: "index_ingredients_on_food_id"
t.index ["recipe_id"], name: "index_ingredients_on_recipe_id"
end
create_table "recipes", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
Your models would look like this:
Food model:
class Recipe < ApplicationRecord
has_many :ingredients
has_many :foods,through: :ingredients
end
Ingredient model:
class Ingredient < ApplicationRecord
belongs_to :recipe
belongs_to :food
end
Food model:
class Food < ApplicationRecord
has_many :ingredients
has_many :recipes,through: :ingredients
end

rails: ActiveModel::MissingAttributeError: can't write unknown attribute `division_id`

I am working on a simple support ticket system , however I'm getting a weird error. Here is the error :
ActiveModel::MissingAttributeError: can't write unknown attribute division_id
and here is the code :
user.rb:
class User < ApplicationRecord
belongs_to :division
has_many :teckets
has_many :teckets , through: :user_tecket
has_secure_password
end
division.rb:
class Division < ApplicationRecord
has_many :users
has_many :users, through: :user_division
has_many :teckets
has_many :teckets, through: :teckets_divisions
end
tecket.rb :
class Tecket < ApplicationRecord
belongs_to :division
belongs_to :user
has_one :status
has_one :status, through: :tecket_statuses
end
teckets_division.rb :
class TecketsDivision < ApplicationRecord
belongs_to :tecket
belongs_to :division
end
schema.rb:
ActiveRecord::Schema.define(version: 20171001063612) do
create_table "divisions", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "replies", force: :cascade do |t|
t.string "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "statuses", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "tecket_replies", force: :cascade do |t|
t.integer "tecket_id"
t.integer "reply_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "tecket_statuses", force: :cascade do |t|
t.integer "tecket_id"
t.integer "status_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "teckets", force: :cascade do |t|
t.string "title"
t.string "content"
t.string "platform"
t.string "version"
t.string "client_anme"
t.string "client_phone"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "teckets_divisions", force: :cascade do |t|
t.integer "tecket_id"
t.integer "division_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "user_divisions", force: :cascade do |t|
t.integer "user_id"
t.integer "division_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "user_teckets", force: :cascade do |t|
t.integer "user_id"
t.integer "tecket_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.string "passwrod"
t.string "password_digest"
t.integer "division_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
I get the error when I try to create a user from the console
Edit : I have added the schema.rb file as requested
either remove the division_id from the user table and has_many :users from divisions model
or (and the simpler approach),
remove user_divisions join table and this line from division model:
has_many :users, through: :user_division
also - You have a lot of join tables it seems, but I don't see the need for their use. You could direct relate them in most of the cases you have shown.

ActiveModel::MissingAttributeError: can't write unknown attribute `book_id`

I have this problem, but don't know why.
I create models with generator:
bin/rails generate model Book name:string author:string description:text cover:string
bin/rails generate model Episode name:string description:text art:string
ant other...
book.rb
class Book < ApplicationRecord
has_many :episodes
end
episode.rb
class Episode < ApplicationRecord
belongs_to :book
has_many :scenes
end
When in console i try to: book.episodes << episode i had an error: ActiveModel::MissingAttributeError: can't write unknown attribute "book_id"
My schema.rb
ActiveRecord::Schema.define(version: 20170320111956) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "answers", force: :cascade do |t|
t.text "text"
t.string "next_scene"
t.string "next_episode"
t.string "voiceover"
t.integer "end"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "books", force: :cascade do |t|
t.string "name"
t.string "author"
t.text "description"
t.string "cover"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "episodes", force: :cascade do |t|
t.string "name"
t.text "description"
t.string "art"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "scenes", force: :cascade do |t|
t.string "name"
t.text "text"
t.integer "choise"
t.string "next_scene"
t.string "next_episode"
t.string "art"
t.string "music"
t.string "sound_fx"
t.string "voiceover"
t.integer "end"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
In schema i haven't id_book, but why? I also do db:migrate and have error again.
By default, Rails uses the convention of naming the primary as the autogenerated column id. If you wish to specify a different primary key, such as book_id, you could do the following:
class Book < ApplicationRecord
self.primary_key = "book_id"
end

Ruby on Rails - Order objects by field of a has_many relation

I'm rails begginer.
how to load database that has following condition.
I want show lecture list that has order by comment.created_at DESC
schema.rb
create_table "comments", force: :cascade do |t|
t.text "content"
t.integer "user_id"
t.integer "lecture_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "likedcount", default: 0
end
create_table "lectures", force: :cascade do |t|
t.string "subject"
t.string "professor"
t.string "major"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "uptachi", default: 0
t.integer "hatachi", default: 0
end
lecture.rb
has_many :comments
comment.rb
belongs_to: lectures
You need to write it as:
has_many :comments, -> { order("comments.created_at DESC") }
As per the OP's comment, it seems, what he want is a named scope. Like,
scope :order_by_comments, -> { joins(:comments).order("comments.created_at DESC") }

Application_controller define method to only show future dates

In my Ruby on Rails application I have a cinema system and am trying to show only show times for films that are either in the future or today (so not in the past).
I am trying to do this in my _form.html.erb in a drop down menu:
<%= f.grouped_collection_select :showing_id, live_films.order(:title), :showings, :title, :id, :showing_times %>
Where live_films is the method in application_controller.rb:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :active_menu, :live_films
def live_films
Film.includes(:showings).where('showings.show_date > ?', Date.current.beginning_of_day)
end
end
But I get this error:
ActiveRecord::StatementInvalid in Bookings#new
SQLite3::SQLException: no such column: showings.show_date: SELECT "films".* FROM "films" WHERE (showings.show_date > '2015-02-20 00:00:00.000000') ORDER BY "films"."title" ASC
My db/schema:
ActiveRecord::Schema.define(version: 20150219091141) do
create_table "bookings", force: :cascade do |t|
t.integer "user_id"
t.integer "showing_id"
t.integer "seat_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "categories", force: :cascade do |t|
t.string "genre"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "certificates", force: :cascade do |t|
t.string "age_rating"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "certificate_img_url"
end
create_table "films", force: :cascade do |t|
t.string "title"
t.string "synopsis"
t.string "director"
t.string "cast1"
t.string "cast2"
t.string "cast3"
t.date "release_date"
t.string "warnings"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_url"
t.string "certificate_id"
t.integer "category_id"
t.integer "hours"
t.integer "minutes"
t.string "video_url"
end
create_table "screens", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "seats", force: :cascade do |t|
t.string "row_letter"
t.integer "row_number"
t.integer "screen_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "showings", force: :cascade do |t|
t.date "show_date"
t.time "show_time"
t.integer "film_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "screen_id"
end
add_index "showings", ["film_id"], name: "index_showings_on_film_id"
create_table "users", force: :cascade do |t|
t.string "password_digest"
t.string "role"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "first_name"
t.string "last_name"
t.string "house_no"
t.string "street"
t.string "town"
t.string "postcode"
t.string "email"
end
The column name show_date is correct as is the table name showings but for some reason it isn't working.
Can someone please help?
Here is the solution:
Film.joins(:showings).where('showings.show_date > ?', Date.current.beginning_of_day).preload(:showings)

Resources