1

I am trying to make an app in Rails 4.

I have an industries model and a profiles model.

My industries table has:

create_table "industries", force: :cascade do |t|
    t.string   "sector"
    t.string   "icon"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "industries_organisations", id: false, force: :cascade do |t|
    t.integer "industry_id"
    t.integer "organisation_id"
  end

  add_index "industries_organisations", ["industry_id"], name: "index_industries_organisations_on_industry_id", using: :btree
  add_index "industries_organisations", ["organisation_id"], name: "index_industries_organisations_on_organisation_id", using: :btree

  create_table "industries_profiles", id: false, force: :cascade do |t|
    t.integer "industry_id"
    t.integer "profile_id"
  end

  add_index "industries_profiles", ["industry_id"], name: "index_industries_profiles_on_industry_id", using: :btree
  add_index "industries_profiles", ["profile_id"], name: "index_industries_profiles_on_profile_id", using: :tree

The associations are:

profile.rb

has_and_belongs_to_many :industries

industry.rb

has_and_belongs_to_many :profiles

In my profiles show, I am trying to show the industry (sector attribute) associated with that profile.

I'm not sure how to do this using the HABTM join table association.

My current attempt is:

<% unless @profile.industries.blank? %>
                     <!-- @profile.industry.first.try(:sector) -->
                     <%= @Industry.sector.first = Industry.includes(:profile).where(profile: { @profile })  %>

                <% end %>

The commented out line is my previous attempt.

I found this resource which I think I have followed Rails - HABTM Relationship -- How Can I Find A Record Based On An Attribute Of The Associated Model

How can I show a profile's industry sector?

Profiles controller has:

class ProfilesController < ApplicationController
  before_action :set_profile, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!
  after_action :verify_authorized

  # GET /profiles
  # GET /profiles.json
  def index
    @profiles = Profile.all
    authorize @profiles
  end

  # GET /profiles/1
  # GET /profiles/1.json
  def show
  end

  # GET /profiles/new
  def new
    @profile = Profile.new
    @profile.qualifications_build
    @profile.build_vision
    @profile.build_personality 
    @profile.addresses_build
    @profile.industries_build

    authorize @profile

  end

  # GET /profiles/1/edit
  def edit
    @profile.build_personality unless @profile.personality
    @profile.qualifications_build unless @profile.qualifications
    @profile.build_vision unless @profile.vision
    @profile.addresses_build unless @profile.addresses
    @profile.industries.build unless @profile.industries

  end

  # POST /profiles
  # POST /profiles.json
  def create
    @profile = Profile.new(profile_params)
    authorize @profile

    respond_to do |format|
      if @profile.save
        format.html { redirect_to @profile }
        format.json { render :show, status: :created, location: @profile }
      else
        format.html { render :new }
        format.json { render json: @profile.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /profiles/1
  # PATCH/PUT /profiles/1.json
  def update

    # successful = @profile.update(profile_params)

    # Rails.logger.info "xxxxxxxxxxxxx"
    # Rails.logger.info successful.inspect
    # user=@profile.user
    # user.update.avatar
    respond_to do |format|
      if @profile.update(profile_params)
        format.html { redirect_to @profile }
        format.json { render :show, status: :ok, location: @profile }
      else
        format.html { render :edit }
        format.json { render json: @profile.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /profiles/1
  # DELETE /profiles/1.json
  def destroy
    @profile.destroy
    respond_to do |format|
      format.html { redirect_to profiles_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_profile
      @profile = Profile.find(params[:id])
      authorize @profile
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def profile_params
     params.require(:profile).permit(:user_id, :title, :hero, :overview, :research_interest, :occupation, :external_profile, 
        :working_languages, :tag_list,
          user_attributes: [:avatar],
          personality_attributes: [:average_day, :fantasy_project, :preferred_style],
          vision_attributes: [:id, :profile_id, :long_term, :immediate_challenge], 
          qualifications_attributes: [:id, :level, :title, :year_earned, :pending, :institution, :_destroy],
          addresses_attributes: [:id, :unit, :building, :street_number, :street, :city, :region, :zip, :country, :latitude, :longitude, :_destroy],
          industries_attributes: [:id, :sector, :icon] )
    end
end

The profiles form includes a form partial for the industry attributes as:

profiles form

          <%= render 'industries/industry_selector', f: f %>  

industries form

<%= simple_fields_for :industries do |iff| %>

                <div class="form-inputs">

                    <%= iff.label "Choose your industry" %>



<%= iff.select :sector, options_from_collection_for_select(Industry.alphabetically, 'id', 'sector', @profile.industries.map{ |j| j.id }), :multiple => true %>

TAKING OLEG'S SUGGESTION BELOW

I try changing my show action in the profile controller to:

def show
    @profile = Profile.includes(:industries).find(params[:id])

  end

I get the same result - nothing shows for industry.

THE SOLUTION

The problem was that I named the join table industries profiles. I think its meant to be industry singular. This problem was resolved by naming the join table in the models so that it matches the definition I gave it in the schema.

Community
  • 1
  • 1
Mel
  • 2,481
  • 26
  • 113
  • 273

1 Answers1

1

use if instead unless and industries is plural

<%- if @profile.industries.any? %>
  <%= @profile.industries.first.try(:sector) %>
<% end %>

EDIT

in controller show action use includes

@profile = Profile.includes(:industries).find(params[:id])
Baldrick
  • 23,882
  • 6
  • 74
  • 79
Oleh Sobchuk
  • 3,612
  • 2
  • 25
  • 41