i'm using rails 4 and was wondering if anyone could find what's wrong in my code.
I have project model and I created a team model that has a belongs_to - has_one relation with project.
project model:
class CrmProject < ActiveRecord::Base
has_one :crm_team
team model
class CrmTeam < ActiveRecord::Base
belongs_to :crm_project
accepts_nested_attributes_for :crm_project
belongs_to :crm_section
belongs_to :manager, class_name: "User"
has_many :users
accepts_nested_attributes_for :users
end
When submitting the form to create a new team i get this error:
ActiveModel::MissingAttributeError in CrmTeamsController#create
can't write unknown attribute `crm_team_id`
and log from server :
Parameters: {"crm_team"=>{"crm_project"=>"5", "manager"=>"3", "user_ids"=>["", "2"]}, "co
mmit"=>"Create Crm team"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1
[["id", 1]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]]
(0.1ms) begin transaction
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'email#gmail.com' AND "users"."
id" != 2) LIMIT 1
SQL (0.2ms) INSERT INTO "crm_teams" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2020-03-1
1 07:29:19.735115"], ["updated_at", "2020-03-11 07:29:19.735115"]]
(0.2ms) rollback transaction
Completed 500 Internal Server Error in 9ms (ActiveRecord: 1.0ms)
When you use a has_one relation like this
has_one :crm_team
Rails expects you to add crm_team_id to your crm_project, in order to understand which crm_team is related with crm_project object. Adding it going to solve your problem.
In my opinion defining opposite like this much better in logic. Because in future these teams can have multiple projects.
class CrmProject < ActiveRecord::Base
belongs_to :crm_team
class CrmTeam < ActiveRecord::Base
***has_one/has_many(pick one)*** :crm_project
accepts_nested_attributes_for :crm_project
belongs_to :crm_section
belongs_to :manager, class_name: "User"
has_many :users
accepts_nested_attributes_for :users
end
Related
I have a problem with my rails application when i create a customer for an environment, the action itself if omitting the parameter environment_id in the insert statment.
This is my customer.rb model:
class Customer < ActiveRecord::Base
belongs_to :environment, inverse_of: :customers
has_many :all_services, class_name: 'Service'
has_many :services, inverse_of: :customer
has_paper_trail ignore: %i[created_at updated_at]
end
This is my environment.rb model:
class Environment < ActiveRecord::Base
has_many :all_customers, class_name: 'Customer', dependent: :destroy
has_many :customers, inverse_of: :environment
has_many :all_services, class_name: 'Service', dependent: :destroy
has_many :services, inverse_of: :environment
has_many :all_versions, class_name: 'Version', dependent: :destroy
has_many :versions, inverse_of: :environment
has_many :all_role_permissions, class_name: 'RolePermission', dependent: :destroy
has_many :role_permissions, inverse_of: :environment
has_paper_trail ignore: %i[created_at updated_at]
end
This is the customer_controller.rb create action:
def create
if customer_params.permitted?
render json: Customer.create!(customer_params), status: :ok
else
render json: { message: Api::V1::INVALID_PARAMETERS }, status: :bad_request
end
end
def customer_params
params.require(:customer).permit(:environment_id, :full_name, :document_type, :document_value, :customer_type)
end
And this is the server log:
Started POST "/api/v1/customers" for 127.0.0.1 at 2021-06-02 18:18:44 +0100
Processing by Api::V1::CustomersController#create as HTML
Parameters: {"full_name"=>"cvbcv", "document_type"=>"bcvbc", "document_value"=>"vbcvbcv", "customer_type"=>"bcvbcvb", "environment_id"=>1, "customer"=>{"full_name"=>"cvbcv", "document_type"=>"bcvbc", "document_value"=>"vbcvbcv", "customer_type"=>"bcvbcvb", "environment_id"=>1}}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."uid" = $1 LIMIT $2 [["uid", "test1#test.cl"], ["LIMIT", 1]]
(0.5ms) BEGIN
↳ app/services/api/customers.rb:20:in `create_customer'
Environment Load (0.5ms) SELECT "environments".* FROM "environments" WHERE "environments"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/services/api/customers.rb:20:in `create_customer'
Customer Create (1.4ms) INSERT INTO "customers" ("full_name", "document_type", "document_value", "customer_type", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["full_name", "cvbcv"], ["document_type", "bcvbc"], ["document_value", "vbcvbcv"], ["customer_type", "bcvbcvb"], ["created_at", "2021-06-02 17:18:44.378509"], ["updated_at", "2021-06-02 17:18:44.378509"]]
↳ app/services/api/customers.rb:20:in `create_customer'
(1.2ms) ROLLBACK
↳ app/services/api/customers.rb:20:in `create_customer'
Completed 500 Internal Server Error in 22ms (ActiveRecord: 4.3ms | Allocations: 6384)
ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR: null value in column "environment_id" violates not-null constraint
DETAIL: Failing row contains (28, cvbcv, bcvbc, vbcvbcv, bcvbcvb, null, 2021-06-02 17:18:44.378509, 2021-06-02 17:18:44.378509).
):
I tried everything i can possible know, i triple checked the migrations and schema.
I also checked active record gem version from previous projects and everything is ok.
One thing that might be relevant, this that the project have a front-end in Angular.
Rails validates for Environment presence in the database because Customer belongs_to to it.
Query below in your log is trying to load Environment with ID=1:
Environment Load (0.5ms) SELECT "environments".* FROM "environments" WHERE "environments"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
After this Rails try to INSERT new Customer without Environment reference because it seems that Environment with ID=1 doesn't exist in the database.
multiple ways of solving it.
problem: the environment_id is nil and already as not nil defined in the postgres DB.
you can add a required: true to the association, which rails then checks for existence. in your case a validation error would throw.
you can add a validates :enviroment_id, presence: true which would do the same
you merge the id into the params
example to always merge the environment_id into the params
def customer_params
params.require(:customer).permit(:full_name, :document_type, :document_value, :customer_type).merge(environment_id: GET_ME_THE_ENV_ID)
end
I am doing a simple project which has four model Owner Store Product Warehouse
Owner
class Owner < ApplicationRecord
has_one :store
end
Store
class Store < ApplicationRecord
has_many :ware_houses
has_many :products, through: :ware_houses
end
Product
class Product < ApplicationRecord
has_many :ware_houses
has_many :stores, through: :ware_houses
end
WareHouse
class Product < ApplicationRecord
has_many :ware_houses
has_many :stores, through: :ware_houses
end
first I add o1 as Owner by
o1 = Owner.new(name: "o1") then save it
then add s1 as store by s1 = Store.new(name: "s1")
assign s1 to o1 by writing
o1.store = s1
I tried to add three product by using p1 = Product.new(name: "p1")
but When I wanted to assign p1,p2,p3 to s1 by s1.products = [p1, p2]
it will show this
Product Load (0.2ms) SELECT "products".* FROM "products" INNER JOIN "ware_houses" ON "products"."id" = "ware_houses"."product_id" WHERE "ware_houses"."store_id" = ? [["store_id", 1]]
(0.1ms) begin transaction
Product Create (0.8ms) INSERT INTO "products" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "P1"], ["created_at", "2020-06-23 17:35:41.028631"], ["updated_at", "2020-06-23 17:35:41.028631"]]
(0.1ms) rollback transaction
Traceback (most recent call last):
1: from (irb):16
ActiveRecord::NotNullViolation (SQLite3::ConstraintException: NOT NULL constraint failed: products.store_id)
was following a tutorial online, not quite sure about this unfinished process..
it seems like p1,p2 is not successfully assign to s1.
quite confused, would like to know how to fix it..
thanks a lot!
I am implementing counter_cache concept to my Forums app. It is working fine for one model that has a simple belongs_to association but not working for a polymorphic association.
My app structure is like this. I have 3 models, Forum, Post and Comment.
class Forum < ApplicationRecord
has_many :posts
end
Post Model:
class Post < ApplicationRecord
belongs_to :forum, counter_cache: true
has_many :comments, as: :parent
end
Comment Model:
class Comment < ApplicationRecord
belongs_to :parent,polymorphic: true, counter_cache: true
has_many :comments, as: :parent
end
My Comments Model is basically a polymorphic one, so a comment can belong to a post or a comment can belong to another comment (in this way it will be considered a reply of a comment)
I have a posts_count field in Forum model which is working fine and auto-incrementing and decrementing is working.
I also have a comments_count field in Post model.
Whenever a new comment is created, the comments_count field is incremented in the associated Post.
But when I try to create a comment whose parent (polymorphic association) is another comment (so basically a reply of a comment), I hit an error:
Started POST "/comments" for 103.255.4.86 at 2018-10-18 20:48:39 +0000
Cannot render console from 103.255.4.86! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by CommentsController#create as JS
Parameters: {"utf8"=>"✓", "comment"=>{"body"=>"testing a reply", "parent_id"=>"812", "parent_type"=>"Comment"}}
Post Load (0.8ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT $2 [["id", 7], ["LIMIT", 1]]
(0.4ms) BEGIN
Comment Load (1.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."id" = $1 LIMIT $2 [["id", 812], ["LIMIT", 1]]
SQL (0.9ms) INSERT INTO "comments" ("body", "parent_type", "parent_id", "owner_type", "owner_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["body", "testing a reply"], ["parent_type", "Comment"], ["parent_id", 812], ["owner_type", "User"], ["owner_id", 46], ["created_at", "2018-10-18 20:48:39.141170"], ["updated_at", "2018-10-18 20:48:39.141170"]]
(0.4ms) ROLLBACK
Completed 500 in 43ms (ActiveRecord: 7.2ms)
ActiveModel::MissingAttributeError (can't write unknown attribute `comments_count`):
What am I missing here? Any hint would be really appreciated, Thanks!!
I have got it working by removing counter_cache: true from Comment model and defining my own methods for increment and decrement of the counter in Comment model. So here is my final Comment model:
class Comment < ApplicationRecord
belongs_to :parent,polymorphic: true,touch: true
has_many :comments,dependent: :destroy,as: :parent
after_create_commit { self.parent_post.increment!(:answers_count,1) }
after_destroy { self.parent_post.decrement!(:answers_count,1) }
def parent_post
(self.parent if parent_type == "Post") || self.parent.parent
end
end
If anyone comes up with another answer please post it here. Thanks.
The counter_culture counter cache gem supports polymorphic associations natively: https://github.com/magnusvk/counter_culture
My model is
class TelecomOperator < ActiveRecord::Base
has_many :users
class User < ActiveRecord::Base
belongs_to :telecom_operator
When I do TelecomOperator.first.users it gives me all users but When I do
User.first.telecom_operator it always give me nil
SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 LIMIT 1 [["id", 2]]
=> nil
When I do
User.includes(:telecom_operator).find(2)
It works fine
User:
class User < ActiveRecord::Base
attr_accessible :email, :username, :password, :password_confirmation, :remember_me
has_many :tasks_users, :dependent => :destroy, :conditions => {:is_owner => true}
has_many :tasks, :through => :tasks_users, :source => :task
Task:
class Task < ActiveRecord::Base
include RankedModel
ranks :sort_order
acts_as_taggable
has_many :tasks_users
has_many :users, :through => :tasks_users
TasksUser:
class TasksUser < ActiveRecord::Base
attr_accessible :is_owner
belongs_to :user
belongs_to :task
validates_uniqueness_of :user_id, :scope => [:user_id, :task_id]
end
They key here is dependent destroy.
Whenever I try to destroy my user, which should destroy the join model, I end up getting this odd sql error:
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 17]]
(0.1ms) begin transaction
ActsAsTaggableOn::Tagging Load (0.1ms) SELECT "taggings".* FROM "taggings" WHERE "taggings"."tagger_id" = 17 AND "taggings"."tagger_type" = 'User'
TasksUser Load (0.1ms) SELECT "tasks_users".* FROM "tasks_users" WHERE "tasks_users"."user_id" = 17 AND "tasks_users"."is_owner" = 't'
Could not log "sql.active_record" event. NoMethodError: undefined method `name' for nil:NilClass
**SQLite3::SQLException: no such column: tasks_users.: DELETE FROM "tasks_users" WHERE "tasks_users"."" = ?**
(0.1ms) rollback transaction
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: tasks_users.: DELETE FROM "tasks_users" WHERE "tasks_users"."" = ?
from /home/steveq/.rvm/gems/ruby-1.9.3-p194#rails32/gems/sqlite3-1.3.7/lib/sqlite3/database.rb:91:in `initialize'
The line with the double asterisk is the line in question - it appears to be searching for a record in "tasks_users"."".
If all I do is change :conditions => {:is_owner => false}, the sql executes without a problem:
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 17]]
(0.1ms) begin transaction
ActsAsTaggableOn::Tagging Load (0.2ms) SELECT "taggings".* FROM "taggings" WHERE "taggings"."tagger_id" = 17 AND "taggings"."tagger_type" = 'User'
TasksUser Load (0.1ms) SELECT "tasks_users".* FROM "tasks_users" WHERE "tasks_users"."user_id" = 17 AND "tasks_users"."is_owner" = 'f'
List Load (0.2ms) SELECT "lists".* FROM "lists" WHERE "lists"."owner_id" = 17
Relationship Load (0.1ms) SELECT "relationships".* FROM "relationships" WHERE "relationships"."user_id" = 17
SQL (0.3ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 17]]
(299.4ms) commit transaction
Any ideas about what's happening here, and why having the condition of is_owner change from true to false allows the query and delete statement to execute?
Thanks
Ugh - Hopefully I can save someone else from banging their heads against this wall for an hour.
Problem was how I specified the :conditions.
It needed to be put in double quotes:
has_many :tasks_users, :dependent => :destroy, :conditions => "is_owner = 'true'"
That was it.