Karol85
Karol85

Reputation: 275

How to manage both nested and not nested resources

I wonder what is a proper way to resolve the following problem.

I have two models :

Publisher and Issue. Publisher has_many issues.

I want to manage issues both from Publishers list and from Issues list.

For example :

Simply speaking i need crud action for issue alone and for publisher issue.

First I try to make a :

  resources :issues

  resources :publishers do
    resources :issues
  end

and in issue controller :

before_filter :find_issue

def find_issue
 @publisher = Publisher.find(params[:publisher_id]) if params[:publisher_id]
 @issues = @publisher ? @publisher.issues : Issue
end

but i have to make many if condition in my views and controller.

For example if issue is created from publisher , on success i want to redirect to publisher_issues_path instead of issue_path a vice versa. Same problem with all link like "back to list" and similar. So code is in my opinion not very transparent.

Now i wonder to use namespaces.

namespace :publishers,  do
  resources :issues
end

and make

# app/controllers/publishers/issues_controller.rb
module Publishers
  class IssuesController < ApplicationController
    # actions that expect a :publisher_id param
  end
end

# app/controllers/issues_controller.rb
class IssuesController < ApplicationController
  # your typical actions without any publisher handling
end

and make separate view for both controller actions.

Is there a better or cleaner way to resolve this kind of problem? I want to make my code dry as possible. Many thanks for reply.

Upvotes: 6

Views: 1168

Answers (1)

Hesham
Hesham

Reputation: 2347

Routes:

resources :issues
resources :publishes do
  resources :issues
end

Controller:

class IssuesController < ApplicationController
  before_filter :build_issue, only: [:new, :create]
  before_filter :load_issue,  only: [:show, :edit, :update, :destroy]

  def index
    @issues = issues.page(params[:page])
  end

  ... all other actions will have access to @issue

private
  def issues
    if params[:publisher_id].present?
      Publisher.find(params[:publisher_id]).issues
    else
      Issue
    end  
  rescue ActiveRecord::RecordNotFound
    redirect_to issues_path(alert: 'Publisher not found')
  end

  def build_issue
    @issue = issues.new(issue_params)
  end

  def load_issue
    @issue = issues.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    redirect_to issues_path(alert: 'Issue not found')
  end

  def issue_params
    # whitelisted attributes goes here
  end
end

To avoid using conditions, use actions instead of full named path, i.e:

redirect_to action: :index
link_to 'Issues', {action: :index}

Upvotes: 3

Related Questions