models/message.rb
class Message < ActiveRecord::Base
has_ancestry
end
schema.rb
create_table "messages", force: :cascade do |t|
t.text "content"
t.integer "parent_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "ancestry"
end
after adding has_ancestry in model it gives error Argument Error.
"The scope body needs to be callable."
Please help me
Thanks
I am a new developer working on a Sinatra/Ruby/ActiveRecord app. I have established a 1:many (postgres) relationship between Category and Recipe. When I try to list the recipes in a category I get the error:
ActiveRecord::StatementInvalid at /category/5
PG::UndefinedColumn: ERROR: column recipes.category_id does not exist LINE 1: SELECT 1 AS one FROM "recipes" WHERE "recipes"."category_id... ^ : SELECT 1 AS one FROM "recipes" WHERE "recipes"."category_id" = $1 LIMIT 1
file: postgresql_adapter.rb location: prepare line: 637
app.rb
get('/category/:id') do
#category = Category.find(params.fetch('id'))
#recipes = #category.recipes
erb(:category)
end
category.erb
<% if #recipes.any?() %>
<% #recipes.each() do |recipe| %>
<ul>
<li><a href='/recipe/<%=recipe.id%>'> <%=recipe.recipe_name%></a></li>
</ul>
<%end%>
<%else %>
<p>You have no recipes!</p>
<%end%>
schema
ActiveRecord::Schema.define(version: 20150930234556) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "categories", force: :cascade do |t|
t.string "cat_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "images", force: :cascade do |t|
t.string "image_name"
t.string "url"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "alt"
t.integer "width"
t.integer "height"
t.integer "recipe_id"
end
create_table "ingredients", force: :cascade do |t|
t.string "ingredient_name"
t.integer "recipe_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "instructions", force: :cascade do |t|
t.string "instruction_name"
t.integer "recipe_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "recipes", force: :cascade do |t|
t.string "recipe_name"
t.string "source"
t.string "servings"
t.string "comment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "cat_id"
end
end
I have searched my project folders and cannot find category_id. Don't know why it's looking for that, my field names are category.id and recipe.cat_id.
This:
#recipes = #category.recipes
suggests that you have
has_many :recipes
in your Category model. That has_many will be looking for a category_id column in your recipes table (i.e. a category_id attribute in your Recipe model). But you don't have a recipes.category_id column, you have a recipes.cat_id column:
create_table "recipes", force: :cascade do |t|
#...
t.integer "cat_id"
end
I'd recommend renaming the recipes.cat_id column to recipes.category_id to match the conventions that Rails has a very strong preference for. If you can't rename the column then add a :foreign_key option to that has_many to tell Category how to resolve the relationship:
has_many :recipes, :foreign_key => :cat_id
OK, so it's been years since I've written any ruby code, and my design may be incorrect. With that in mind, I'm writing a small utility to clone project entities in TargetProcess via REST. Target Process has a data model that allows for several types of parent:child relationships:
project:epic:feature:user_story
project:feature:user_story
project:user_story
However, all the entities are nearly identical from a data structure perspective, so it seemed to make sense to use STI and use models to define the relationships and inheritance. I've created a new Rails app with only these models to verify the error I'm getting when I attempt to associate an Epic with a Feature:
ActiveModel::MissingAttributeError: can't write unknown attribute `epic_id`
Here are the models:
class TargetProcessEntity < ActiveRecord::Base
end
class Project < TargetProcessEntity
has_many :epics
has_many :features
has_many :user_stories
end
class Project < TargetProcessEntity
has_many :epics
has_many :features
end
class Epic < TargetProcessEntity
belongs_to :project
has_many :features
end
class Feature < TargetProcessEntity
belongs_to :project
belongs_to :epic
has_many :user_stories
end
class UserStory < TargetProcessEntity
belongs_to :feature
belongs_to :project
end
Here is the schema:
ActiveRecord::Schema.define(version: 20150929122254) do
create_table "epics", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "target_process_entity_id"
t.integer "project_id"
end
add_index "epics", ["project_id"], name: "index_epics_on_project_id"
add_index "epics", ["target_process_entity_id"], name: "index_epics_on_target_process_entity_id"
create_table "features", force: :cascade do |t|
t.integer "project_id"
t.integer "epic_id"
t.integer "target_process_entity_id"
end
add_index "features", ["epic_id"], name: "index_features_on_epic_id"
add_index "features", ["project_id"], name: "index_features_on_project_id"
add_index "features", ["target_process_entity_id"], name: "index_features_on_target_process_entity_id"
create_table "projects", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "target_process_entity_id"
end
add_index "projects", ["id"], name: "index_projects_on_id"
add_index "projects", ["target_process_entity_id"], name: "index_projects_on_target_process_entity_id"
create_table "target_process_entities", force: :cascade do |t|
t.string "type", null: false
t.string "name"
t.text "description"
t.integer "source_remote_id"
t.float "numeric_priority"
t.integer "owner"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "cloned_remote_id"
t.string "resource_type"
t.integer "project_id"
end
create_table "user_stories", force: :cascade do |t|
t.integer "project_id"
t.integer "feature_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "target_process_entity_id"
end
add_index "user_stories", ["feature_id"], name: "index_user_stories_on_feature_id"
add_index "user_stories", ["project_id"], name: "index_user_stories_on_project_id"
add_index "user_stories", ["target_process_entity_id"], name: "index_user_stories_on_target_process_entity_id"
end
While Epic and Feature both have a project_id, an instance of Feature does not have an epic_id attribute; attempting to assign an epic to feature blows up:
[20] pry(main)> epic = Epic.new
=> #<Epic:0x007fcab6c80590
id: nil,
type: "Epic",
name: nil,
description: nil,
source_remote_id: nil,
numeric_priority: nil,
owner: nil,
created_at: nil,
updated_at: nil,
cloned_remote_id: nil,
resource_type: "Epic",
project_id: nil>
[21] pry(main)> feature = Feature.new
=> #<Feature:0x007fcab6d3ba48
id: nil,
type: "Feature",
name: nil,
description: nil,
source_remote_id: nil,
numeric_priority: nil,
owner: nil,
created_at: nil,
updated_at: nil,
cloned_remote_id: nil,
resource_type: "Feature",
project_id: nil>
[22] pry(main)> epic.save
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "target_process_entities" ("type", "resource_type", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["type", "Epic"], ["resource_type", "Epic"], ["created_at", "2015-10-02 15:18:13.351578"], ["updated_at", "2015-10-02 15:18:13.351578"]]
(4.6ms) commit transaction
=> true
[23] pry(main)> feature.epic = epic
ActiveModel::MissingAttributeError: can't write unknown attribute `epic_id`
from /Users/kcallahan/.rbenv/versions/2.0.0-p647/lib/ruby/gems/2.0.0/gems/activerecord-4.2.4/lib/active_record/attribute.rb:138:in `with_value_from_database'
[24] pry(main)>
I realize it is extremely possible I am either doing something wrong or have made a poor design decision; any input is hugely appreciated as I've not been able to find anything on this and have been banging my head against it for days!
OK, I got it working almost by mistake! I added the xxx_id columns to the target_process_entities table. I assumed that the STI tables would be able to respond to the relationship definitions, though my understanding of the inner workings of STI and relationships are rusty and incomplete at best...
I may be wrong but it looks like your Feature table is a join table for many to many relationship between Project and Epic.
If that's the case, your models might look like this
class Project < TargetProcessEntity
has_many :features
has_many :epics, through: :features
end
class Epic < TargetProcessEntity
has_many :features
has_many :projects, through: :features
end
class Feature < TargetProcessEntity
belongs_to :project
belongs_to :epic
has_many :user_stories
end
the source is implied if you use the same name
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
I'm trying to create some referential integrity across several tables, and am tripping over the placement of add foreign keys. At best the statement is ignored, worst it throws an error.
class CreateCantons < ActiveRecord::Migration
def change
create_table :cantons do |t|
t.integer :canton_id
t.string :canton_name
t.timestamps null: false
end
end
end
class CreateResources < ActiveRecord::Migration
def change
create_table :resources do |t|
t.integer :resource_id
t.string :resource_name
t.integer :type_id
t.integer :canton_id
t.string :url
t.string :address
t.string :city
t.string :state
t.string :zip
add_foreign_key :cantons, :canton_id #ignored
add_foreign_key :types, :type_id #ignored
t.timestamps null: false
end
end
end
class CreateResourceContacts < ActiveRecord::Migration
def change
create_table :resource_contacts do |t|
t.integer :contact_id
t.integer :resource_id
add_foreign_key :resources, :resource_id
add_foreign_key :contacts, :contact_id
t.timestamps null: false
end
end
end
adding a t in front throws an error
t.add_foreign_key :contacts, :contact_id #error
How do I properly use this command?
you need to move the foreign_keys outside of the create table
class CreateResources < ActiveRecord::Migration
def change
create_table :resources do |t|
t.integer :resource_id
t.string :resource_name
t.integer :type_id
t.integer :canton_id
t.string :url
t.string :address
t.string :city
t.string :state
t.string :zip
t.timestamps null: false
end
add_foreign_key :resources, :cantons
add_foreign_key :resources, :types
end
end
see http://edgeapi.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_foreign_key
And also you need to tell it what tables you are adding it to.
How can I set one of my database table to created_at as default value. I did this but didn't work, I have checked in the DB and the value of code is null.
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
t.string :title
t.string :location
t.text :description
t.date :occurs_on
t.string :code, :default => Event::created_at
t.timestamps
end
end
end