Update on Rails 4 using :has_many :through many relationship for many (has_and_belongs_to_many)

Asked

Viewed 224 times

1

I’m having a question about how to update Rails 4 using :has_many :through, if there is a more correct and easier way, I am open to suggestions.

Error:

inserir a descrição da imagem aqui

app/views/Articles/_form.html.erb

 <label>Category</label>
  <% @categories.each do |category| %>
  <div class="field">
    <%= check_box_tag "categories[]", category.id, 
                        @article.category_ids.include?(category.id) %> 
    <%= h category.name %>
  </div>
  <% end %>

app/controllers/articles_controller.Rb

class ArticlesController < ApplicationController
  before_action :set_article, only: [:show, :edit, :update, :destroy]
  before_action :set_category, only: [:show, :edit, :update, :new]
  # GET /articles
  # GET /articles.json
  def index
    @articles = Article.all
  end

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

  # GET /articles/new
  def new
    @article = Article.new
  end

  # GET /articles/1/edit
  def edit
  end

  # POST /articles
  # POST /articles.json
  def create
    @article = Article.new(article_params)
    @article.categories = params[:categories]
    #raise params.to_yaml
    respond_to do |format|
      if @article.save
        format.html { redirect_to @article, notice: 'Article was successfully created.' }
        format.json { render :show, status: :created, location: @article }
      else
        format.html { render :new }
        format.json { render json: @article.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /articles/1
  # PATCH/PUT /articles/1.json
  def update
    respond_to do |format|
      if @article.update(article_params)
        @article.categories_up = params[:categories]
        #params[:article][:category_ids] ||= []
        format.html { redirect_to @article, notice: 'Article was successfully updated.' }
        format.json { render :show, status: :ok, location: @article }
      else
        format.html { render :edit }
        format.json { render json: @article.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /articles/1
  # DELETE /articles/1.json
  def destroy
    @article.destroy
    respond_to do |format|
      format.html { redirect_to articles_url, notice: 'Article was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_article
      @article = Article.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def article_params
      params.require(:article).permit(:title, :body, :categories)
    end

    def set_category
      @categories = Category.all
    end
end

app/models/article.Rb

class Article < ActiveRecord::Base
    has_many :has_categories
    has_many :categories, :through  => :has_categories
    after_save :save_categories
    after_update :update_categories_up

    # custom setter method
    def categories=(value)
        @categories = value
    end

    # custom setter method
    def categories_up=(value)
        @categories = value
    end

    private

    def save_categories
        #raise @categories.to_yaml
        @categories.each do |category_id|
            HasCategory.create(category_id: category_id, article_id: self.id)
        end
    end

    def update_categories_up
        #raise @categories.to_yaml
        @categories.each do |category_id|
            HasCategory.update(category_id: category_id, article_id: self.id)
        end
    end

1 answer

0


You have a callback calling the method Article#update_categories_up. This method is called at the controller line that calls the Article#update (if @article.update(article_params)). At that time the @categories in its object Article is nil because it was not set (you arrow it right after). Try setting the categories_up= before calling the update.

Another tip is to avoid using callbacks, they make code confusing and difficult to debug.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.