I have a simple test as such:
it "should create a post through a user for a blog." do
@user.blogs.create(title: @blog.title)
@user.blogs.find_by_title(@blog.title).posts.create(title: 'some title')
post = Post.find_by_title('some title')
post.title.should == 'some title'
end
This fails. Why? Because we don't have any blogs for a user. Ok lets throw a binding.pry
in their:
it "should create a post through a user for a blog." do
@user.blogs.create(title: @blog.title)
binding.pry
@user.blogs.find_by_title(@blog.title).posts.create(title: 'some title')
post = Post.find_by_title('some title')
post.title.should == 'some title'
end
Now that were in the console, lets see if @user.blogs
gives us anything.
@user.blogs
=> [#<Blog id: nil, title: "user_blog_26">]
Ok .... But thats not the whole command. Lets see if @blogs has anything.
@blog
=> #<Blog id: 26, title: "user_blog_26">
Ok we are getting some where, we see that @user
has the same blog associated to them. (although the id is missing in @user.blogs
... (Note: The relationship between users and blogs is: User has_and_belongs_to_many :blogs, join_table: 'blogs_users'
)
So lets do:
@user.blogs.find_by(title: @blog.title)
=> nil
Um .....
Whats going on?
Whats going on?
Models
class User < ActiveRecord::Base
include Promiscuous::Subscriber
subscribe :first_name, :email, :user_name, :last_name
has_and_belongs_to_many :blogs, join_table: 'blogs_users'
has_many :posts, through: :blogs
validates :first_name, presence: true
validates :email, presence: true, uniqueness: true
validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
end
class Blog < ActiveRecord::Base
has_many :posts
validates :title, presence: true, uniqueness: true
end
@blog
=> #<Blog id: 26, title: "user_blog_26">
@blog
has an id
assigned to it. So, that means its an existing record in blogs
table with id = 26
.
@user.blogs.create(title: @blog.title)
This line means that create a new record in blogs table with title same as that of @blog.title
(i.e., user_blog_26
)
Now, in Blog
model you have
validates :title, presence: true, uniqueness: true ## title must be unique
A uniqueness check on the title
field. So, obviously @user.blogs.create(title: @blog.title)
failed as a record with title user_blog_26
already exists in the blogs
table (Recall @blog here). This is the reason why @user.blogs
shows a blog with id = nil
as the associated blog
creation failed.
@user.blogs.find_by(title: @blog.title)
=> nil
As the associated blog
with title user_blog_26
was not created for @user
. This query returns nil
.
Possible Solution
You already have a blog
record in the database referred by @blog
. To assign that blog to your @user
, simply update the example as below:
it "should create a post through a user for a blog." do
@user.blogs << @blog ## This will set @blog.user_id = @user.id
@user.blogs.find_by_title(@blog.title).posts.create(title: 'some title')
post = Post.find_by_title('some title')
post.title.should == 'some title'
end