Domanda

Assume you have a Question and an Answer models, and that new answers are submitted from the questions#show page (like StackoverFlow).

Unless the questions#show and the answers#create actions load identical data, the answers#create will throw an exception (usually no method on nil class) if there is a validation error on a new answer. It's not a major issue, but when you add filters and other types of data, the code starts to smell, and you get tight coupling between both actions. Changing one requires changing the other--something easy to forget.

I'm wondering what do experienced Rails developers do, if anything, to avoid this coupling?

  # Assume Discussion = Question, and Response = Answer
  # Discussions#show
  def show
    @discussion = Discussion.find(params[:id]) # The question
    @responses = @discussion.responses.includes(:author) # Existing answers
    @response = @discussion.responses.build # New answer object for the form
    order = 'users.role'
    if params[:filter].present?
      order = case params[:filter]
      when 'new'
        then 'responses.created_at DESC'
      end
    end
    @responses = @responses.order(order)
  end

Now let's look at the responses#create action, which has to load the same data for render to work (if validation fails):

  # Responses#create
  def create
    # @discussion is loaded using a before filter
    @response = @discussion.responses.build(params[:response])
    @response.author = current_user
    @responses = @discussion.responses.includes(:author)
    order = 'users.role'
    if params[:filter].present?
      order = case params[:filter]
      when 'new'
        then 'responses.created_at DESC'
      end
    end
    @responses = @responses.order(order)
    respond_to do |format|
      if @response.save
        format.html { redirect_to @discussion }
        format.js
      else
        format.html { render 'discussions/show' } # fails if discussions#show and responses#new do not load the same data.
      end
    end
  end
È stato utile?

Soluzione

It seems like your issue is that you have very tight coupling between unrelated controller actions, since the answers#create is trying to be a discussions#show as well.

One option is to redirect to @discussion on validation errors as well as success, and pass in the submitted answer parameters to the redirect. Then you can handle the "special" case that there is answer data in the question show action.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top