Rails Associations - значения правильные, но ассоциация нулевая

Я работал над этим весь день, и я так близко, но мой мозг просто пропускает что-то простое, но я не вижу этого.

На этом сайте пользователь может создавать клубы и вступать в них. Когда пользователь вступает в клуб, он становится его членом. Члены клуба могут размещать сообщения в клубе. По какой-то причине я не могу заставить своего члена клуба правильно работать с почтой. Значение заполняется правильным идентификатором, но когда я проверяю ассоциацию в консоли, я получаю ноль. Моя цель - получить имя пользователя члена клуба, который разместил сообщение.

Модель пользователя

has_many :club_memberships, :class_name => 'ClubMembership', :foreign_key => :member_id, :primary_key => :id 
has_many :clubs, :through => :club_memberships 

Клубная модель

has_many :club_memberships
has_many :members, :through => :club_memberships
has_many :posts

Модель членства в клубе

belongs_to :club 
belongs_to :member, :class_name => "User", :foreign_key => :member_id, :primary_key => :id 
has_many :posts

Почтовая модель

belongs_to :club
belongs_to :club_membership

Соответствующие маршруты

resources :clubs do
    resources :posts
end
  resources :club_memberships, :only => [:index, :create, :destroy] 

Контроллер сообщений

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]
  before_action :set_club
  before_action :set_membership_id

  def new
    @post = Post.new
  end

  def show
    @posts = Post.find(params[:id])
  end

  def create
    @post = Post.new(post_params)
    @post.member_id = @club_membership.id
    @post.club_id = @club.id

    if @post.save
      redirect_to @club
    else
      render 'new'
    end
  end


  private
    def set_post
      @post = Post.find(params[:id])
    end

    def set_club
      @club = Club.find(params[:club_id])
    end

    def set_membership_id
      @club_membership = @club.club_memberships.find_by(member_id: current_user)
    end

    def post_params
      params.require(:post).permit(:title, :postcontent)
    end
end

Сообщение создается путем перехода по ссылке new_club_post_path(@club) link_to со страницы клуба. Сообщение создано правильно, и значения верны.

Консольный результат недавнего поста

> @post = Post.find(7)
  Post Load (0.2ms)  SELECT  `posts`.* FROM `posts` WHERE `posts`.`id` = 7 LIMIT 1
 => #<Post id: 7, member_id: 29, club_id: 22, title: "fdsafsadfas", postcontent: "fsdafsadfsadfsadfasdf", created_at: "2015-10-16 22:39:28", updated_at: "2015-10-16 22:39:28"> 

Вызов @post.club возвращает true

> @post.club
  Club Load (0.2ms)  SELECT  `clubs`.* FROM `clubs` WHERE `clubs`.`id` = 22 LIMIT 1
 => #<Club id: 22, club_name: "new test club", club_type: "Movies", created_at: "2015-10-16 22:34:51", updated_at: "2015-10-16 22:34:51"> 

но когда я пробую @post.club_membership, результат нулевой, и я не могу понять, почему это так.

> @post.club_membership
 => nil 

Если я попытаюсь установить определенное значение для @club, я могу вызвать @club.club_memberships, поэтому я думаю, что ассоциация работает нормально. У меня просто проблема с переходом от post к club_membership. Я надеюсь вызвать что-то вроде этого @post.club_membership.username и получить значение, возвращающее связанное имя пользователя сообщения. Если я назову это сейчас, я получу

NoMethodError: undefined method `username' for nil:NilClass

Спасибо!

edit-- Вот создание миграции для таблицы сообщений.

class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.integer :member_id
      t.integer :club_id
      t.string :title
      t.text :postcontent

      t.timestamps null: false
    end
  end
end

ОБНОВЛЕННЫЙ ответ Благодаря замечательным пользователям этого сайта я смог это понять.

Моя модель сообщения должна иметь это как ассоциацию:

belongs_to :club_membership, :class_name => 'ClubMembership', :foreign_key => :member_id, :primary_key => :id 

Это позволяет мне вызвать @post.club_membership.member.username, чтобы отобразить имя пользователя постера.


person mochimantis    schedule 16.10.2015    source источник
comment
У вас есть метод post.member_id, и похоже, что это должно быть ClubMembership, но вы явно не указываете внешний ключ в модели сообщения. Похоже, что member_id относится к Пользователю в модели членства в клубе.   -  person Mark Swardstrom    schedule 17.10.2015
comment
Я только что обновил почтовую миграцию. Честно говоря, меня очень смущают внешние ключи, поэтому я стараюсь не упоминать их, если только не нахожу что-то, где кто-то другой использовал это аналогичным образом, и я могу понять это. Это, вероятно, ужасный способ для меня учиться, но я доберусь до него.   -  person mochimantis    schedule 17.10.2015
comment
В этом случае я бы рекомендовал вам сопоставить внешний ключ с таблицей. Внешние ключи — это просто идентификаторы класса, с которым они связаны. Belongs_to — единственные с внешними ключами. Вам не понадобится явный внешний ключ, если столбец имеет то же имя с суффиксом _id, что и класс.   -  person Mark Swardstrom    schedule 18.10.2015
comment
Спасибо! Ваши ответы вместе с @smathy действительно помогли мне понять это.   -  person mochimantis    schedule 19.10.2015


Ответы (1)


Как вы показали в своем (отличном) вопросе, ваше сообщение имеет следующие атрибуты (а также временные метки и идентификатор):

member_id: 29
club_id: 22
title: "fdsafsadfas"
postcontent: "fsdafsadfsadfsadfasdf"

Ваша модель Post имеет следующие ассоциации:

belongs_to :club
belongs_to :club_membership

Первый из них будет искать атрибут с именем club_id (и найдет его), второй будет искать атрибут с именем club_membership_id и не найдет его. Так что метод ассоциации никогда не сработает.

Судя по вашему коду и вопросу, я подозреваю, что это все, что вам нужно, чтобы кто-то указал, но, пожалуйста, дайте мне знать, если ваша проблема вам не ясна.

person smathy    schedule 16.10.2015
comment
Большое спасибо за то, что направили меня в правильном направлении, а не просто дали мне ответ! :) Я был своего рода вызовом для меня, так как я все еще новичок в рельсах, но мне понравилась головоломка, и было очень приятно найти решение. Я обновил свой вопрос решением для будущих пользователей. - person mochimantis; 19.10.2015