SitePoint Sponsor

User Tag List

Results 1 to 12 of 12

Hybrid View

  1. #1
    SitePoint Guru downtroden's Avatar
    Join Date
    Dec 2004
    Location
    illinois
    Posts
    971
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    alternating rendered partial base on model type

    So i'm using Single Table inheritance for a Entry model. There is Text and File. Is there a best practice for outputting a partial and alternating between the two based on the 'type' column (WITHOUT using the type column as i've read this is bad practice).
    your brain reacts in the same way whether you are
    looking at something or thinking about it...

  2. #2
    SitePoint Guru downtroden's Avatar
    Join Date
    Dec 2004
    Location
    illinois
    Posts
    971
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    no one?
    your brain reacts in the same way whether you are
    looking at something or thinking about it...

  3. #3
    SitePoint Wizard Darren884's Avatar
    Join Date
    Aug 2003
    Location
    Southern California, United States
    Posts
    1,616
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So one file is HTML and the other is text?
    Have a good day.

  4. #4
    SitePoint Guru downtroden's Avatar
    Join Date
    Dec 2004
    Location
    illinois
    Posts
    971
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    one 'entry' type is text in the database and one is a link to a file on the system.

    here's what i came up with after TONS of searching and no luck
    Code Ruby:
    <% if entry_row[:type] == "TextEntry" %>
        <%# html for text entry %>
    <% else %>
        <%# html for file enty %>
    <% end >

    in this instance, is it even possible to remove the decision from the view?
    your brain reacts in the same way whether you are
    looking at something or thinking about it...

  5. #5
    SitePoint Wizard Darren884's Avatar
    Join Date
    Aug 2003
    Location
    Southern California, United States
    Posts
    1,616
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You could by looping through it and reorganizing the model in the controller but this method is probably best because it doesn't require as much 'intelligence'.
    Have a good day.

  6. #6
    SitePoint Guru downtroden's Avatar
    Join Date
    Dec 2004
    Location
    illinois
    Posts
    971
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    okay... there's a ruby guy downstairs and i was finally able to catch him... here's what he suggested (for all those that look at this in the future).
    stripped for generality
    Code Ruby:
    <% @variable_name.each do |row| -%>
    	<% if row.is_a? ClassNameA -%>
    		<%= render :partial => "ClassNameA" -%>
    	<% else -%>
    		<%= render :partial => "ClassNameB" -%>
    	<% end -%>
    <% end -%>

    Apparently is_a? is inheritance aware so, if I ever have to create a subclass of type_a OR type_b, those will be picked up as well... my first method would only pick up the class mentioned and NOT any subclasses.
    your brain reacts in the same way whether you are
    looking at something or thinking about it...

  7. #7
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    270
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    And if you were serious about moving the decision out of the view, the first thing is to move the "what kind" decision into the model. basically, you'd create either a boolean or some similar indicator method for the model then use that flag in the controller to dictate which view you're going to render.

    Remember, you're going to want to keep most of your logic in the model, so complicated decision trees go there, with simple operations in the controller.

  8. #8
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Surely the decision on which view to show belongs in the controller and not in the model!

    Model - processes the data

    Controller - decides where and when that data is to be presented

    View - displays the data

  9. #9
    SitePoint Guru downtroden's Avatar
    Join Date
    Dec 2004
    Location
    illinois
    Posts
    971
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    but in this instance, i'm not seeing how you could put the partial decision in the controller.

    each partial is a 'row' of information, in which there's two different types.
    your brain reacts in the same way whether you are
    looking at something or thinking about it...

  10. #10
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Then Arlen is right - the logic should be in the model (or class that defines the row objects if they aren't coming from a classic Rails model). Something like:
    Code:
    def partial_to_use
      if self.is_a? ClassNameA
        return "ClassNameA"
      else
        return "ClassNameB"
      end
    end
    Then your view simplifies to:
    Code:
    <% @variable_name.each do |row| -%>
        <%= render :partial => row.partial_to_use -%>
    <% end -%>
    I'd also be tempted to change the partial names to something more descriptive like "file_row" and "text_row". So:
    Code:
    def partial_to_use
      if self.is_a? ClassNameA
        return "file_row"
      else
        return "text_row"
      end
    end

  11. #11
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've thought on this over-night and I think my previous post is wrong. I don't think the model should know anything about the view.

    The MVC scheme only works if you split the code by what it does. Not how complicated it is. Not what looks tidiest.

    What you are doing is making a choice about the view partials to use. I think that code therefore belongs in a helper.

    So I'd do this:

    helper code:
    Code:
    def partial_for_row(row)
      if row.is_a? ClassNameA
        "file_row"
      else
        "text_row"
      end
    end
    And the view code
    Code:
    <% @variable_name.each do |row| -%>
        <%= render :partial => partial_for_row(row) -%>
    <% end -%>

  12. #12
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    270
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I should have been clearer. When I said the "what kind" decision belonged in the model, I meant "what kind of record am I?" decision. A simple boolean, perhaps called "is_text?" or "is_html?" is added to the model, and the function returns T/F depending on the result of the decision. The controller should not know what making this decision involves, it should only know what the result of the decision is.

    Now the controller looks at that simple boolean and renders the correct template.

    If you expand the choices beyond binary (html/text to, say, html/text/xml/csv or whatever) then you'd probably dispense with the binary and create a simple variable you can use in a case statement.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •