DormoTheNord
DormoTheNord

Reputation: 999

How to move logic out of views and into controller in Rails

I am writing an imageboard in Ruby on Rails.

I have a form for creating new posts. In that form, there is logic to figure out whether the post was created from board#show or topic#show and act accordingly. It is:

  <% if @board != nil %>
    <%= f.hidden_field :board_id, :value => @board.id %>
  <% end %>

  <% if @topic != nil %>
    <%= f.hidden_field :topic_id, :value => @topic.id %>
  <% end %>

The form is rendered on board#show and topic#show with this piece of code:

<%= render :partial => 'posts/form'%>

Should I move that logic to the controller? How would I go about doing that?

Upvotes: 2

Views: 401

Answers (3)

Stefan Kanev
Stefan Kanev

Reputation: 3040

You should also consider a polymorphic relationship for this one. I'm not sure if it is a good fit, but it might be worth a try.

Otherwise, it's fine too pass nils. You can just do:

<%= f.hidden_field :board_id, :value => @board.try(:id) %>
<%= f.hidden_field :topic_id, :value => @topic.try(:id) %>

Come to think of it, ideally the controller should assign the fields to whatever you have in f and then the code should just be:

<%= f.hidden_field :board_id %>
<%= f.hidden_field :topic_id %>

Just do @post.board_id = @board.id in board#show and the equivalent code for topic#show. You can even do @post = @board.posts.build and that should assign the id automatically.

Upvotes: 0

Edd Morgan
Edd Morgan

Reputation: 2923

As it is, in the view, it's probably fine. However, you could (possibly, depending on your app) refine it a little by putting the board/topic information in the URL using nested routes. Routes that would look something like this:

/boards/4/posts
/topics/133/posts

Then your "is it from a board or a post" logic could happen in your PostsController. Again, whether or not this is 'better' is dependent on your requirements, but that's an alternative way of approaching this.

As a side note, you can slim down your conditionals a little. if @board is the same as if @board != nil (unless you have a special case for @board being false. nil and false will both evaluate as false).

Upvotes: 1

bioneuralnet
bioneuralnet

Reputation: 5301

I don't think it's necessary to put it in the controller. I would use :locals. So in board#show:

<%= render :partial => 'posts/form', :locals => {:resource => @board} %>

Do the same in topic#show, but using @topic. Then in your form partial:

<%= f.hidden_field "#{resource.model_name.downcase}_id", :value => resource.id %>

There are probably more elegant ways to get the model_name, but that's the direction I'd take it.

Upvotes: 1

Related Questions