Reputation: 275
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 :
on publishers list user can click link "Issues" placed near each publisher. then he goes to Issues list but filtered only for proper publisher. He can click "create new issue" and goes to form for add new issue. On this form i don't need to show him a select list to choose publisher
on Issues list user can click "create new issue" and go to form but this time he should choose publisher from select, which will be related to created issue.
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
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