Reputation: 2715
I am making an app in Rails 4.
I have an address model, which is polymorphic.
My associations are:
profile.rb
has_many :addresses, as: :addressable
address.rb
belongs_to :addressable, :polymorphic => true
In my address.rb, I have a method for:
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
In my profile views folder, I have a partial to display a user's country, as:
<span class="profilesideinfo">
<% if @addresses.country_name.present? %>
<%= @addresses.country_name.titlecase %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
</span>
I have also tried:
<% if @profile.addresses.country_name.present? %>
<%= @profile.addresses.country_name.titlecase %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
And I have also tried (changing country_name (which is the method in my model) to country (which is the attribute in my address table))
Im getting stuck, because I can successfully create an address, but then that country name should show in the profile show partial. It doesn't. Instead, I get an error that says:
undefined method `country_name' for nil:NilClass
Is there something else that needs to happen for a reference to a polymorphic instance to show in the parent.
Can anyone see what needs to happen to get this to work?
I have tried making a scope in my profile model as:
Profile.joins(:addresses).where("addresses.profile_id = ?", profile_id)
I'm not sure this is adding any value. I'm not sure how to use it or whether it works, given that the address model doesn't have a foreign key for profile_id.
When I save this and try to reload the page, I get this error:
undefined local variable or method `profile_id' for #<Class:0x007fbacaec2d18>
Taking SurreyMagpie's suggestion below, I change the partial to:
<% if @profile.addresses.country_name.any? %>
<%= @profile.address.country_name.first.titlecase %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
I am checking if there are any addresses and then displaying the first country name.
When I try this, I get this error:
undefined method `country_name' for #<ActiveRecord::Associations::CollectionProxy []>
Upvotes: 0
Views: 72
Reputation: 327
The polymorphic nature of the association is not responsible for your difficulties here.
When you define country_name
as a method in your Address class, that is known as an instance method. As such, you are able to call it on a single Address object. So, if in the rails console you run Address.first.country_name
you should receive a result for that specific instance of Address.
However, when you query a has_many
association, in your case @profile.addresses
, you get an ActiveRecord::Associations::CollectionProxy returned, even if there is only a single Address record. It is not exactly an array but has very similar behaviour.
The point is: you cannot call your instance method on the whole set at once. You need to iterate through the collection and call the method on each instance. For example:
<% if @profile.addresses.any? %>
<% @profile.addresses.each do |address| %>
<span class="profilecountry">
<%= address.country_name.titlecase %>
</span>
<% end %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
may be what you need - though how you choose to display multiple countries is up to you.
Upvotes: 0