Reputation: 69
Following are models:
class User < ActiveRecord::Base
has_many :companies_users
has_many :companies, :through => :companies_users
end
class Company < ActiveRecord::Base
has_many :companies_users
has_many :users, :through => :companies_users
accepts_nested_attributes_for :users
attr_accessible :name, :address_1, :address_2, :area, :city, :state, :zipcode, :country, :users_attributes
after_create :create_subscriptions
def create_subscriptions
subscription=Subscription.create(:company_id => self.id, :subscription_dt => Date.today, :is_active => 'Y', :user_id => self.users.first.id)
subscription.save
end
end
class CompaniesUser < ActiveRecord::Base
belongs_to :user
belongs_to :company
end
Following are spec/factories/factory.rb
FactoryGirl.define do
factory :company do |f|
f.name "TestCompany"
f.domain_url "test_url"
users {|t| [t.association(:user)] }
end
factory :user do |f|
f.first_name "John"
f.last_name "Doe"
f.password "password"
f.email "[email protected]"
f.mobile_no "25589875"
f.fax_no "25548789"
f.office_no "25578455"
end
factory :companiesuser do |f|
association :user
association :company
end
end
Following is my spec/model/company_spec.rb
context "Check methods" do
it "check after create methods" do
company = FactoryGirl.create(:company)
end
end
While executing above company_spec it creates an issue due to method subscription which exist in company model and call after create callback create_subscriptions.which require self.users.first.id which it did not get and provide me following error.
$ rspec spec/models/company_spec.rb
F
Failures:
1) Company Model: Check methods check after create methods
Failure/Error: company = FactoryGirl.create(:company)
RuntimeError:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
# ./app/models/company.rb:47:in `create_subscriptions'
# ./spec/models/company_spec.rb:45:in `block (3 levels) in <top (required)>'
Can anyone let me know what i need to do or its any association related issue? it create problem because first it enter values in company but not able to enter value in users table so not get user id which required in subscription method.
Upvotes: 2
Views: 497
Reputation: 69
I resolved above issue by change code in "spec/model/company_spec.rb" as follow:
context "Check methods" do
it "check after create methods" do
company = create(:company,"name"=>"mycom","domain_url"=>"test","users_attributes"=>{"0"=>{"email"=>"[email protected]","password"=>"password","password_confirmation"=>"password"}})
end
end
It created data in my join table also and worked successfully. Obviously its not done by factory join. I directly pass the user attributes here. So removed line
users {|t| [t.association(:user)] }
from company's factory.
Upvotes: 1
Reputation: 76774
I've done a nested has_many :through and you have to basically pass the attributes to the :companies_users model and then to the :users model
Form
#views/admin/posts/new
<%= form_for [:admin, resource], :html => { :multipart => true } do |f| %>
<table class="resource_table">
<thead>
<th colspan="2"><%= params[:action].capitalize %> <%= resource_class %></th>
</thead>
<tbody class="form">
<% attributes.each do |attr| %>
<tr class="<%= cycle('odd', '')%>">
<td><%= resource_class.human_attribute_name(attr) %></td>
<td>
<% if attr == "body" %>
<%= f.text_area attr, :rows => 60, :cols => 80, :class => "redactor" %>
<% else %>
<%= f.text_field attr, :value => resource.public_send(attr).to_s %>
<% end %>
</td>
</tr>
<% end %>
<%= f.fields_for :images_posts do |images_posts| %>
<%= images_posts.fields_for :image do |images| %>
<tr>
<td>Image</td>
<td><%= images.file_field :image %></td>
</tr>
<% end %>
<tr>
<td>Caption</td>
<td><%= images_posts.text_field :caption %></td>
</tr>
<% end %>
<tr class="dull">
<td colspan="2"><%= f.submit "Go" %></td>
</tr>
</tbody>
</table>
<% end %>
Models
#models/image_post.rb (the join model)
class ImagePost < ActiveRecord::Base
#Associations
belongs_to :post, :class_name => 'Post'
belongs_to :image, :class_name => 'Image'
#Validations
validates_uniqueness_of :post_id, :scope => :image_id
#Nested Association (Can upload & add images from form)
accepts_nested_attributes_for :image, :allow_destroy => true
end
#models/image.rb
class Image < ActiveRecord::Base
#Associations
has_many :products, :class_name => 'Product', :through => :images_products, dependent: :destroy
has_many :images_products, :class_name => 'ImageProduct'
has_many :posts, :class_name => 'Post', :through => :images_posts, dependent: :destroy
has_many :images_posts, :class_name => 'ImagePost'
has_many :brands, :class_name => 'Brand', :through => :brands_images, dependent: :destroy
has_many :brands_images, :class_name => 'BrandImages'
#Image Upload
Paperclip.options[:command_path] = 'C:\RailsInstaller\ImageMagick'
has_attached_file :image,
:styles => { :medium => "x300", :thumb => "x100" },
:default_url => "",
:storage => :s3,
:bucket => ''
:s3_credentials => S3_CREDENTIALS
#Validations
validates_presence_of :image, :message => "No Image Present!"
end
#models/post.rb
class Post < ActiveRecord::Base
#Images
has_many :images, -> { uniq }, :class_name => 'Image', :through => :images_posts, dependent: :destroy
has_many :images_posts, :class_name => 'ImagePost'
#Nested Association (Can upload & add images from form)
accepts_nested_attributes_for :images_posts, :allow_destroy => true
end
This was a BIG help for me: Rails nested form with has_many :through, how to edit attributes of join model?
Diagnosing Your Issue
I posted my code to give you a working example of what you can do (mine still needs refinement, but it works)
Looking at your code, you should add "accepts_nested_attributes_for" into your companies_users.rb model like this:
accepts_nested_attributes_for :user
In your companies model, change your accepts_nested_attributes_for to:
accepts_nested_attributes_for :companies_users
Upvotes: 0