I have an instance of type A that has_many Bs. When the A.foo = value method gets called, I actually want to write a method that delegates to that foo= call the first of the A's Bs.
class A < ActiveRecord::Base
has_many :bs, autosave: true
def foo
bs.first.foo
end
def foo=(val)
bs.first.foo = val
end
end
class B < ActiveRecord::Base
belongs_to A
end
rails generate model A
rails generate model B a:references foo:string
2.3.0 :001 > a = A.create!
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "as" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2016-10-08 18:03:18.255107"], ["updated_at", "2016-10-08 18:03:18.255107"]]
(7.8ms) commit transaction
=> #<A id: 1, created_at: "2016-10-08 18:03:18", updated_at: "2016-10-08 18:03:18">
Create an A and call it a.
2.3.0 :002 > b = B.create!(a: a, foo: "initial")
(0.4ms) begin transaction
SQL (0.4ms) INSERT INTO "bs" ("a_id", "foo", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["a_id", 1], ["foo", "initial"], ["created_at", "2016-10-08 18:03:40.658035"], ["updated_at", "2016-10-08 18:03:40.658035"]]
(8.3ms) commit transaction
=> #<B id: 1, a_id: 1, foo: "initial", created_at: "2016-10-08 18:03:40", updated_at: "2016-10-08 18:03:40">
Create a B and call it b. Make it a child of A. Set it's foo property to "initial".
2.3.0 :003 > a.reload.foo
A Load (0.2ms) SELECT "as".* FROM "as" WHERE "as"."id" = ? LIMIT 1 [["id", 1]]
B Load (0.2ms) SELECT "bs".* FROM "bs" WHERE "bs"."a_id" = ? ORDER BY "bs"."id" ASC LIMIT 1 [["a_id", 1]]
=> "initial"
Check that a sees it's new child's foo: yes. As expected.
2.3.0 :004 > a.foo = "set"
B Load (0.1ms) SELECT "bs".* FROM "bs" WHERE "bs"."a_id" = ? ORDER BY "bs"."id" ASC LIMIT 1 [["a_id", 1]]
=> "set"
2.3.0 :005 > a.foo
B Load (0.4ms) SELECT "bs".* FROM "bs" WHERE "bs"."a_id" = ? ORDER BY "bs"."id" ASC LIMIT 1 [["a_id", 1]]
=> "initial"
Whaaat? I just called a.foo = "set". Now when I call a.foo again to read the value back, I get "initial"? That's not the way it works for has_one relationships. Why is ActiveRecord reloading from the DB every time, instead of caching it's queries?
Ultimately, my intention is to call a.save!, and have it autosave down to the b. But that's not possible if the relationship gets amnesia about every pending change. What's going on here?!
Set up a has_one relationship between A and B and delegate :foo to the has_one association.
class A
has_many :bs
has_one :first_b, -> { first },
class_name: 'B'
delegate :foo, to: :first_b
end
To avoid the query for B you can use .joins, includes or eager_load.
Related
User Model
class User < ApplicationRecord
belongs_to :tenant, dependent: :destroy
end
Tenant Model
class Tenant < ApplicationRecord
has_many :users
end
Controller
class Accounts::RegistrationsController < Devise::RegistrationsController
Using build_
def create
#tenant = Tenant.new
#user = #tenant.build_user(params)
#tenant.save
end
Using Model
def create
#tenant = Tenant.new
#user = User.build(params)
#tenant.save
end
SQL:
Foreign key is added.
Working
Able to add User model data separately.
Able to add tenant model data separately.
Not working
Not able to map id from the tenant table to the user table's tenant_id.
I tried many possibilities, but not working. Kindly guide me.
DB Screenshot
**Note:*
I am using Devise Gem.
The problem is that build_ is created for the model belonging to.
For example you can do:
Loading development environment (Rails 5.2.1)
2.4.1 :001 > user = User.new(name:'James Kirk')
=> #<User id: nil, name: "James Kirk", created_at: nil, updated_at: nil, tenant_id: nil>
2.4.1 :002 > user.build_tenant(name:'Enterprise')
=> #<Tenant id: nil, name: "Enterprise", created_at: nil, updated_at: nil>
2.4.1 :003 > user.save
(0.1ms) begin transaction
Tenant Create (0.6ms) INSERT INTO "tenants" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "Enterprise"], ["created_at", "2018-12-30 15:05:52.531519"], ["updated_at", "2018-12-30 15:05:52.531519"]]
User Create (0.6ms) INSERT INTO "users" ("name", "created_at", "updated_at", "tenant_id") VALUES (?, ?, ?, ?) [["name", "James Kirk"], ["created_at", "2018-12-30 15:05:52.534295"], ["updated_at", "2018-12-30 15:05:52.534295"], ["tenant_id", 2]]
(1.3ms) commit transaction
=> true
The above saves the tenant then passes the id to the user and saves the user.
But you can not:
2.4.1 :004 > tenant = Tenant.new(name:'Hazzard')
=> #<Tenant id: nil, name: "Hazzard", created_at: nil, updated_at: nil>
2.4.1 :005 > tenant.build_user(name:'Uncle Jesse')
NoMethodError: undefined method `build_user' for #<Tenant:0x007ff2bbd9b650>
Option for your workflow:
Save the Tenant instance before, get the id then save the User instance:
2.4.1 :009 > tenant = Tenant.new(name:'Hazzard')
=> #<Tenant id: nil, name: "Hazzard", created_at: nil, updated_at: nil>
2.4.1 :010 > tenant.save
(0.1ms) begin transaction
Tenant Create (0.7ms) INSERT INTO "tenants" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "Hazzard"], ["created_at", "2018-12-30 15:12:36.122931"], ["updated_at", "2018-12-30 15:12:36.122931"]]
(1.7ms) commit transaction
=> true
2.4.1 :011 > user = User.new(name:'Uncle Jesse', tenant_id: tenant.id)
=> #<User id: nil, name: "Uncle Jesse", created_at: nil, updated_at: nil, tenant_id: 4>
2.4.1 :012 > user.save
(0.1ms) begin transaction
Tenant Load (0.2ms) SELECT "tenants".* FROM "tenants" WHERE "tenants"."id" = ? LIMIT ? [["id", 4], ["LIMIT", 1]]
User Create (0.4ms) INSERT INTO "users" ("name", "created_at", "updated_at", "tenant_id") VALUES (?, ?, ?, ?) [["name", "Uncle Jesse"], ["created_at", "2018-12-30 15:12:52.119957"], ["updated_at", "2018-12-30 15:12:52.119957"], ["tenant_id", 4]]
(0.9ms) commit transaction
=> true
As per the description mentioned in the post, it seems like the reference of tenant is not saving in the users table.
Since tenant is having a has_many relationship with users, thus something like menioned below can make it to work:
def create
#tenant = Tenant.find(params[:id])
#user = #tenant.users.build(params)
#user.save
end
Note: the params will be having the attributes of user model, whereas you will be passing the id of the tenant already saved in the database to reference it in user table.
https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
I have a model called as Template which has self referential has-many through association with a join model called as RelatedTemplate.
The Template model is written like this:
has_many :related_templates, :foreign_key => :parent_id
has_many :children, :through => :related_templates, :source => :child
has_many :inverse_related_templates, class_name: "RelatedTemplate", :foreign_key => :child_id
has_many :parents, :through => :inverse_related_templates, :source => :parent
validates :name, presence: true, uniqueness: { case_sensitive: false },
length: { maximum: 100, too_long: "should be maximum %{count} characters" }
The join-model RelatedTemplate is:
belongs_to :parent, class_name: 'Template'
belongs_to :child, class_name: 'Template'
In the console when i tried to create a child template with the same name as the parent name then the validation doesn't work:
rails c --sandbox
Loading development environment in sandbox (Rails 4.2.5)
Any modifications you make will be rolled back on exit
irb(main):001:0> a = Template.new
=> #<Template id: nil, client_id: nil, something_id: nil, name: nil, description: nil, another_something_id: nil, video_id: nil, container_id: nil>
irb(main):002:0> a.something_id=1
=> 1
irb(main):003:0> a.name="Hamza"
=> "Hamza"
irb(main):004:0> a.another_something_id=16
=> 16
irb(main):005:0> a.container_id=2
=> 2
irb(main):006:0> a.children.build(name: "Hamza", another_something_id: 16, container_id: 2)
=> #<Template id: nil, client_id: nil, something_id: nil, name: "Hamza", description: nil, another_something_id: 16, video_id: nil, container_id: 2>
irb(main):007:0> a.save
(0.9ms) SAVEPOINT active_record_1
Template Exists (1.3ms) SELECT 1 AS one FROM "templates" WHERE LOWER("templates"."name") = LOWER('Hamza') LIMIT 1
Container Load (0.7ms) SELECT "containers".* FROM "containers" WHERE "containers"."id" = $1 LIMIT 1 [["id", 2]]
Template Exists (0.5ms) SELECT 1 AS one FROM "templates" WHERE LOWER("templates"."name") = LOWER('Hamza') LIMIT 1
Container Load (0.2ms) SELECT "containers".* FROM "containers" WHERE "containers"."id" = $1 LIMIT 1 [["id", 2]]
SQL (0.3ms) INSERT INTO "templates" ("something_id", "name", "another_something_id", "container_id") VALUES ($1, $2, $3, $4) RETURNING "id" [["something_id", 1], ["name", "Hamza"], ["another_something_id", 16], ["container_id", 2]]
SQL (0.2ms) INSERT INTO "templates" ("name", "another_something_id", "container_id") VALUES ($1, $2, $3) RETURNING "id" [["name", "Hamza"], ["another_something_id", 16], ["container_id", 2]]
SQL (0.6ms) INSERT INTO "related_templates" ("parent_id", "child_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["parent_id", 156], ["child_id", 157], ["created_at", "2016-05-05 07:03:51.496346"], ["updated_at", "2016-05-05 07:03:51.496346"]]
(0.2ms) RELEASE SAVEPOINT active_record_1
=> true
Now the query:
irb(main):016:0> a.name
=> "Hamza"
irb(main):017:0> a.children.first.name
Template Load (1.9ms) SELECT "templates".* FROM "templates" INNER JOIN "related_templates" ON "templates"."id" = "related_templates"."child_id" WHERE "related_templates"."parent_id" = $1 ORDER BY "templates"."id" ASC LIMIT 1 [["parent_id", 158]]
=> "Hamza"
Dont know what is wrong here ?
Both object only exist in memory, when you validate them. The uniqueness validation passes in both cases, because the validation checks if there is a similar record in the database already.
Have a look at the logs:
# you call save
irb(main):007:0> a.save
(0.9ms) SAVEPOINT active_record_1
# Rails validates the first object
Template Exists (1.3ms) SELECT 1 AS one FROM "templates" WHERE LOWER("templates"."name") = LOWER('Hamza') LIMIT 1
Container Load (0.7ms) SELECT "containers".* FROM "containers" WHERE "containers"."id" = $1 LIMIT 1 [["id", 2]]
# Rails validates the second object
Template Exists (0.5ms) SELECT 1 AS one FROM "templates" WHERE LOWER("templates"."name") = LOWER('Hamza') LIMIT 1
Container Load (0.2ms) SELECT "containers".* FROM "containers" WHERE "containers"."id" = $1 LIMIT 1 [["id", 2]]
# At this point Rails thinks that both records will be fine, because the validation passed
# Rails saved the first object
SQL (0.3ms) INSERT INTO "templates" ("something_id", "name", "another_something_id", "container_id") VALUES ($1, $2, $3, $4) RETURNING "id" [["something_id", 1], ["name", "Hamza"], ["another_something_id", 16], ["container_id", 2]]
# Rails saved the second object
SQL (0.2ms) INSERT INTO "templates" ("name", "another_something_id", "container_id") VALUES ($1, $2, $3) RETURNING "id" [["name", "Hamza"], ["another_something_id", 16], ["container_id", 2]]
This is good example why Rails uniqueness validations are not 100% secure. Another example might be race conditions, when multiple requests hit the application at the same time.
The only way to avoid this kind of problems, is to add a unique index to the database table.
I'm trying to create a Rails plugin. For the most part, what I've written works. However, there's a problem with associations. When I try to call an association, I get this error:
ActiveRecord::Base doesn't belong in a hierarchy descending from ActiveRecord
At the moment, the plugin looks like this:
module ControlledVersioning
module ActsAsVersionable
extend ActiveSupport::Concern
included do
has_many :versions, as: :versionable
after_create :create_initial_version
end
module ClassMethods
def acts_as_versionable(options = {})
cattr_accessor :versionable_attributes
self.versionable_attributes = options[:versionable_attributes]
end
end
private
def create_initial_version
version = versions.create
end
end
end
ActiveRecord::Base.send :include, ControlledVersioning::ActsAsVersionable
Again, the error message is triggered whenever I try to call the association. I used debugger in the after_create callback and tried running:
> versions.create
*** ActiveRecord::Base doesn't belong in a hierarchy descending from ActiveRecord
> versions
*** ActiveRecord::Base doesn't belong in a hierarchy descending from ActiveRecord
> Version.new
#<Version id: nil, versionable_id: nil, versionable_type: nil>
There are a few things you need to change in your code in order for it to work.
First, versions is a reserved keyboard from rails -- you can't have a relationship with that name - (I used the name versionings in order to make it work)
Also, you want to make sure to just add has_many versionings for the models that want to acts_as_versionable - meaning, move has_many :versionings, as: :versionable, class_name: 'Version' and after_create :create_initial_version calls to inside the acts_as_versionable method.
Here's how all together will look like:
module ControlledVersioning
module ActsAsVersionable
extend ActiveSupport::Concern
module ClassMethods
def acts_as_versionable(options = {})
has_many :versionings, as: :versionable, class_name: 'Version'
after_create :create_initial_version
cattr_accessor :versionable_attributes
self.versionable_attributes = options[:versionable_attributes]
end
end
private
def create_initial_version
version = versionings.create
end
end
end
ActiveRecord::Base.send :include, ControlledVersioning::ActsAsVersionable
Doing those changes made the plugin work for me:
irb(main):003:0> Post.create!
(0.1ms) begin transaction
Post Create (0.7ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2019-07-16 08:55:13.768196"], ["updated_at", "2019-07-16 08:55:13.768196"]]
Version Create (0.2ms) INSERT INTO "versions" ("versionable_type", "versionable_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["versionable_type", "Post"], ["versionable_id", 3], ["created_at", "2019-07-16 08:55:13.772246"], ["updated_at", "2019-07-16 08:55:13.772246"]]
(2.0ms) commit transaction
=> #<Post id: 3, created_at: "2019-07-16 08:55:13", updated_at: "2019-07-16 08:55:13", name: nil>
irb(main):004:0> Post.last.versionings
Post Load (0.2ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT ? [["LIMIT", 1]]
Version Load (0.2ms) SELECT "versions".* FROM "versions" WHERE "versions"."versionable_id" = ? AND "versions"."versionable_type" = ? LIMIT ? [["versionable_id", 3], ["versionable_type", "Post"], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Version id: 2, versionable_type: "Post", versionable_id: 3, created_at: "2019-07-16 08:55:13", updated_at: "2019-07-16 08:55:13">]>
irb(main):005:0>
I would try extending active record in an initializer instead of including it.
initializers/acts_as_versionable.rb
ActiveRecord::Base.extend(ControlledVersioning::ActsAsVersionable)
Also in development; or any environment that reloads the files you'll likely see an error like has been removed from the module tree but is still active. Make sure you're plugin file is in config.eager_load_paths and not actually in a concern path.
I have this class:
class Payment < ActiveRecord::Base
attr_accessible :amount, :invoice_id
belongs_to :invoice
validates :amount, :numericality => { :greater_than => 0, :less_than_or_equal_to => :maximum_amount }
after_save :update_amount_payable
after_destroy :update_amount_payable
private
def maximum_amount
invoice.amount_payable
end
def update_amount_payable
invoice.update_amount_payable
end
end
class Invoice < ActiveRecord::Base
has_many :payments
after_save :update_amount_payable
def update_amount_payable
update_column(:amount_payable_in_cents, new_amount_payable)
end
private
def new_amount_payable
(total - payments.map(&:amount).sum) * 100
end
end
The code above works. But how can I validate that no payment amount can ever cause invoice.amount_payable to be less than 0?
Especially when multiple payments for the same invoice are possible, this turns out to be tricky.
I've been trying to get my head around this for hours, but to no avail. Maybe an after callback to rollback the database can be used here?
Thanks for any help.
One cross-database solution that will work is to use optimistic locking. Essentially, it requires a special lock_version column, that is checked whenever an update is made. If the lock_version at the time an UPDATE is called is different than what the model is expecting, it throws an error noting that something outside of this model caused the record to change (thus invalidating the update). ActiveRecord supports this out of the box, and it will likely suffice for your needs if you don't mind blocking concurrent transactions altogether.
A case that it won't work is where you want to allow concurrent updates. In this case, you'll need to manually check the result during your update:
def update_amount_payable
new_value = new_amount_payable
raise "Payment amounts can't be greater than total invoice amount" if new_value < 0
count = Invoice.where(id: id, amount_payable_in_cents: amount_payable_in_cents).
update_all(amount_payable_in_cents: new_value)
raise ActiveRecord::StaleObjectError.new(self, 'update amount_payable_in_cents') if count != 1
end
private
def new_amount_payable
(total - payments.sum(:amount)) * 100 # get the amount sum from the database
end
I would change the field names. But given the current database schema try the following code:
app/models/invoice.rb
class Invoice < ActiveRecord::Base
has_many :payments
def still_open_amount
self.amount_payable_in_cents - self.payments.sum('amount_in_cents')
end
end
app/models/payment.rb
class Payment < ActiveRecord::Base
belongs_to :invoice
validates :amount_in_cents, :numericality => { :greater_than => 0 }
before_validation :check_all_payments
private
def check_all_payments
if self.new_record?
if (self.invoice.payments.sum('amount_in_cents') + self.amount_in_cents) > self.invoice.amount_payable_in_cents
errors.add(:amount, 'the invoice would be overpaid')
end
else
if (self.invoice.payments.sum('amount_in_cents') - self.amount_in_cents_was + self.amount_in_cents) > self.invoice.amount_payable_in_cents
errors.add(:amount, 'the invoice would be overpaid')
end
end
end
end
This will through a validation error if you try to create a overpaying payment:
~/Desktop/testapp ᐅ rails c
Loading development environment (Rails 4.0.0.beta1)
1.9.3-p286 :001 > i = Invoice.create(amount_payable_in_cents: 100)
(0.1ms) begin transaction
SQL (6.8ms) INSERT INTO "invoices" ("amount_payable_in_cents", "created_at", "updated_at") VALUES (?, ?, ?) [["amount_payable_in_cents", 100], ["created_at", Mon, 13 May 2013 19:23:24 UTC +00:00], ["updated_at", Mon, 13 May 2013 19:23:24 UTC +00:00]]
(0.8ms) commit transaction
=> #<Invoice id: 1, amount_payable_in_cents: 100, created_at: "2013-05-13 19:23:24", updated_at: "2013-05-13 19:23:24">
1.9.3-p286 :003 > p1 = i.payments.create(amount_in_cents: 90)
(0.1ms) begin transaction
Invoice Load (0.2ms) SELECT "invoices".* FROM "invoices" WHERE "invoices"."id" = ? ORDER BY "invoices"."id" ASC LIMIT 1 [["id", 1]]
(0.2ms) SELECT SUM("payments"."amount_in_cents") AS sum_id FROM "payments" WHERE "payments"."invoice_id" = ? [["invoice_id", 1]]
SQL (0.4ms) INSERT INTO "payments" ("amount_in_cents", "created_at", "invoice_id", "updated_at") VALUES (?, ?, ?, ?) [["amount_in_cents", 90], ["created_at", Mon, 13 May 2013 19:24:10 UTC +00:00], ["invoice_id", 1], ["updated_at", Mon, 13 May 2013 19:24:10 UTC +00:00]]
(1.0ms) commit transaction
=> #<Payment id: 1, invoice_id: 1, amount_in_cents: 90, created_at: "2013-05-13 19:24:10", updated_at: "2013-05-13 19:24:10">
1.9.3-p286 :004 > p2 = i.payments.create(amount_in_cents: 20)
(0.1ms) begin transaction
Invoice Load (0.2ms) SELECT "invoices".* FROM "invoices" WHERE "invoices"."id" = ? ORDER BY "invoices"."id" ASC LIMIT 1 [["id", 1]]
(0.1ms) SELECT SUM("payments"."amount_in_cents") AS sum_id FROM "payments" WHERE "payments"."invoice_id" = ? [["invoice_id", 1]]
(0.1ms) commit transaction
=> #<Payment id: nil, invoice_id: 1, amount_in_cents: 20, created_at: nil, updated_at: nil>
1.9.3-p286 :005 > p2.errors
=> #<ActiveModel::Errors:0x007fd57b8e36d8 #base=#<Payment id: nil, invoice_id: 1, amount_in_cents: 20, created_at: nil, updated_at: nil>, #messages={:amount=>["the invoice would be overpaid"]}>
1.9.3-p286 :006 >
This Question is more than a single question so breaking it up into more managable pieces: Rails Engines - simple possible engine to (1) add a model and (2) add the association in the containing class
I am testing out building a Rails engine and am curious whether I can add an association to a specific model in the hosting / container app.
The hosting app has a user model class (yes, this will never chnage) and my engine is called abc and I have a model in my engine called posts (so Abc::Post and the table is abc_posts). I'd like to add to the User class in the main app this association. As a drop dead simple try, I created in my engine:
#located in the engine at: abc/app/models/user.rb
class User < ActiveRecord::Base
has_many :abc_posts
end
the post file:
#located in the engine at: abc/app/models/abc/post.rb
module Abc
class Post < ActiveRecord::Base
attr_accessible :body, :header, :user_id
belongs_to :user
end
end
Via rails console, I was able to create records in the table (easy part) but the User class doesn't know about the association. Any ideas on how to get this done?
thx in advance
edit 1
I've tried using the decorators gem as used in forem (see comment below) and have this file:
#abc/app/decorators/lib/abc/user_class_decorator.rb
Object.const_get(User).class_eval do
has_many :abc_posts, :class_name => "Abc::Post", :foreign_key => "user_id"
end
I have included the decorators via:
lib/abc.rb
require "decorators"
but his doesn't seem to be working. Not sure if this is right strategy or whether syntax is even correct.
That should do the job - specify the class for the relationship:
class User < ActiveRecord::Base
has_many :posts, :class_name => "Abc::Post"
end
Hmmm, I created an example and it does work ...
class Parent < ActiveRecord::Base
has_many :children, :class_name => "Abc::Child"
end
The module with the class Child is in the model/abc.
module Abc
class Child < ActiveRecord::Base
belongs_to :parent
end
end
Here the journal
1.9.3-p194 :001 > Parent.create(:name => 'Mr Daddy')
(0.1ms) begin transaction
SQL (9.4ms) INSERT INTO "parents" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Fri, 03 May 2013 10:49:54 UTC +00:00], ["name", "Mr Daddy"], ["updated_at", Fri, 03 May 2013 10:49:54 UTC +00:00]]
(1.9ms) commit transaction
=> #<Parent id: 1, name: "Mr Daddy", created_at: "2013-05-03 10:49:54", updated_at: "2013-05-03 10:49:54">
1.9.3-p194 :002 > Abc::Child.create(:name => 'Sammy boy', :parent => Parent.first )
Parent Load (0.3ms) SELECT "parents".* FROM "parents" ORDER BY "parents"."id" ASC LIMIT 1
(0.1ms) begin transaction
SQL (117.3ms) INSERT INTO "children" ("created_at", "name", "parent_id", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Fri, 03 May 2013 10:49:58 UTC +00:00], ["name", "Sammy boy"], ["parent_id", 1], ["updated_at", Fri, 03 May 2013 10:49:58 UTC +00:00]]
(2.1ms) commit transaction
=> #<Abc::Child id: 1, name: "Sammy boy", parent_id: 1, created_at: "2013-05-03 10:49:58", updated_at: "2013-05-03 10:49:58">
1.9.3-p194 :003 > Abc::Child.create(:name => 'Milly girl', :parent => Parent.first )
Parent Load (0.3ms) SELECT "parents".* FROM "parents" ORDER BY "parents"."id" ASC LIMIT 1
(0.2ms) begin transaction
SQL (0.8ms) INSERT INTO "children" ("created_at", "name", "parent_id", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Fri, 03 May 2013 10:50:15 UTC +00:00], ["name", "Milly girl"], ["parent_id", 1], ["updated_at", Fri, 03 May 2013 10:50:15 UTC +00:00]]
(2.7ms) commit transaction
=> #<Abc::Child id: 2, name: "Milly girl", parent_id: 1, created_at: "2013-05-03 10:50:15", updated_at: "2013-05-03 10:50:15">
1.9.3-p194 :004 > Parent.first.children.first
Parent Load (0.4ms) SELECT "parents".* FROM "parents" ORDER BY "parents"."id" ASC LIMIT 1
Abc::Child Load (0.3ms) SELECT "children".* FROM "children" WHERE "children"."parent_id" = ? ORDER BY "children"."id" ASC LIMIT 1 [["parent_id", 1]]
=> #<Abc::Child id: 1, name: "Sammy boy", parent_id: 1, created_at: "2013-05-03 10:49:58", updated_at: "2013-05-03 10:49:58">
1.9.3-p194 :005 > Parent.first.children.last
Parent Load (0.5ms) SELECT "parents".* FROM "parents" ORDER BY "parents"."id" ASC LIMIT 1
Abc::Child Load (0.4ms) SELECT "children".* FROM "children" WHERE "children"."parent_id" = ? ORDER BY "children"."id" DESC LIMIT 1 [["parent_id", 1]]
=> #<Abc::Child id: 2, name: "Milly girl", parent_id: 1, created_at: "2013-05-03 10:50:15", updated_at: "2013-05-03 10:50:15">
1.9.3-p194 :006 > Parent.first.children.count
Parent Load (0.3ms) SELECT "parents".* FROM "parents" ORDER BY "parents"."id" ASC LIMIT 1
(0.3ms) SELECT COUNT(*) FROM "children" WHERE "children"."parent_id" = ? [["parent_id", 1]]
=> 2