Ruby on Rails div_for vs <div> - ruby-on-rails

I'm new to Ruby on Rails. In my erb files, is there any reason to use the div_for helper over just typing out the <div> tags and setting the properties as HTML? What advantage is there to using div_for, and is there a recommended best practice?

I think the main reason people use the div_for helper is because it can accept an array of ActiveRecord objects as an argument. That way it becomes a short-hand combination of a loop iterator and a tag generator.
<%= div_for(#people, :class => "foo") do |person| %>
<%= person.name %>
<% end %>

div_for does some "magic" for you, in that it sets the class and ID of the element it generates.
There is no reason to choose it over a simple <div> tag if you don't intend to use those properties, or intent to use different values for them.
There is no strong convention either way. I've been writing Rails code for years and have literally never used it, put it out of your mind, it doesn't matter. There are far, far more important decisions to make, like choosing erb or haml or slim, or deciding whether to adpot CoffeeScript. Decisions that will fundamentally alter the way you write Rails code.

In many cases, rails 'helpers' are like training wheels on a bicycle. They help when you are just starting out, but at some point, you jettison the training wheels and start doing wheelies, sliding skids, and jumping homemade ramps.
But helpers vary, some are so helpful you never get rid of them, others get in the way when you want to start doing wheelies.
If you find using any particular 'helper' is cramping your style, stop using it!

Related

Rails - Creating a custom ERB tag for i18n

Since I write so often this in Rails...
<%= t 'whatever' %>
I was wondering: Is it possible to create a custom tag to make it even shorter? Something like...
<%t 'whatever' %>
It would be fun if I could create my custom tags and make them output anything based on its content.
How would such a thing be doable?
PS: I realize that I am just saving just 1 character. As I said it is for fun. And besides, if creating custom tags is not too complicated, it could have even more applications.

Is it ever OK to call a model class method from within a view

I was in the process of implementing a slide show for my spree store, when I came across a gem that does it. In part of the ReadMe file, I noticed it calls a model class method directly from the view: https://github.com/priviterag/spree_slider#or-roll-your-own
Here's the code:
<% if Spree::Slide.published.count > 0 %>
<section id="slideshow">
<ul class="slide">
<% Spree::Slide.published.order('position ASC').each do |s| %>
<li>
<h1><%= s.slide_name %></h1>
<%= link_to image_tag(s.slide_image.url), url_for(s.slide_link) %>
</li>
<% end %>
</ul>
<a title="<%= t(:previous) %>" class="slider-prev"><%= t(:previous)%></a>
<a title="<%= t(:next) %>" class="slider-next"><%= t(:next) %></a>
</section>
<% end %>
I was doing the same with my own slider, but had flagged the model call as something to move into the relevant controllers (there'd be a few) later. However, really, it seems like it's most self-contained, and easiest to understand and maintain, when the model is called directly from the view like this.
I'd always been lead to believe a View accessing a Model class directly gave good programers nightmares. But in this context, is fetching data directly from the view OK? Why or why not?
I would not, mostly because your view is making a pile of assumptions that are going to be a pain to change later. Your view is assuming that it's using:
an ActiveRecord class,
with certain table columns,
with other objects it's directly calling the properties of.
Here's my take on a view:
<% if slides.count > 0 %>
<section id="slideshow">
<ul class="slide">
<% slides.each do |s| %>
<li>
<h1><%= s.name %></h1>
<%= link_to image_tag(s.image_url), url_for(s.link) %>
</li>
<% end %>
</ul>
<a title="<%= t(:previous) %>" class="slider-prev"><%= t(:previous)%></a>
<a title="<%= t(:next) %>" class="slider-next"><%= t(:next) %></a>
</section>
<% end %>
And with a presenter:
# eg. app/presenters/slide_presenter.rb
class SlidePresenter
extend Forwardable
def initialize(slide)
#slide = slide
end
def_delegator :#slide, :name, :slide_name
def_delegator :#slide, :link, :slide_link
def image_url
#slide.slide_image.url
end
end
And the controller action itself:
slides = Spree::Slide.published
.order('position ASC')
.map {|s| SlidePresenter.new(s) }
render 'theview', locals: { slides: slides }
The benefits of using a Presenter instead of directly using the model in the view is that it restricts how the model is used. Instead of calling any of the hundreds of methods on the ActiveRecord model (with all the variations in parameters), you know exactly how it's being used because you've only defined four methods on the presenter.
(Hiding the model behaviour behind the presenter also gives you an interface that doesn't change: that is, changing the model means changing the guts of the presenter itself, but not all the views that use the presenter.)
I'm not a big fan of the direct ActiveRecord business in the controller in my example above, but you can choose to move it into something like a FetchOrderedSlides service class or helper method, further restricting the known uses of the hundreds of methods on Slides to a handful in very specific parts of your codebase.
Most things passed into Rails views are AREL proxy objects, via which the data is fetched and returned when they are rendered in the view. In that respect, "fetching data directly from the view" is not only acceptable, it's the norm, if your question is about the ordering of events and what actually happens.
But I think what you are getting at is: why should Views be isolated from Models? What bad things happen when they are not?
There are a lot of patterns related to MVC but different. (e.g. http://en.wikipedia.org/wiki/Model_View_ViewModel) MV is one such example. In MV, views know all about models but models don't know about views. You could write an entire application with the MV pattern. A small one maybe. :P The example you posted looks like MV.
I honestly feel like MVC dos and donts gets to firebrand rules lawyering from software architects really quickly. It frustrates me. People should calm down and consider their options. I recommend reading Refactoring by Martin Fowler if you haven't, and I think reading up about the history of MVC and Presentation Model would be fruitful also. MVC is not the only game in town. You should break out classes when it's useful to do so but also collapse and merge classes when you overengineered. In that vein, I think there are times when MV is adequate and MVC is overkill. Little examples pasted onto the web may be one such time, even though some people may interpret them a little bit too literally when transplanting them into a bigger application.
MVC can handle situations where the complexity of the application is such that separating out every niggling little concern is the only way to manage the sheer amount of code involved. The presumption of MVC is that your app is going to be big and complex. Think about apps like Microsoft Word. In that context, you may have an MDI (Multiple Document Interface) scenario where there are multiple views of the same model that need to be kept in sync via events. You may have different kinds of models that can be rendered the same way. In fact, if you can imagine a spanner to throw in the works, very complex application requirements will probably throw it. So you can pick MV and get started and eventually it will start to get messy. You may have a very large amount of Controllery logic such as wiring up event callbacks and orchestrating request handling stuck inside Views (like MVC-less PHP) at which point you would want to break that out to manage it better.
The nightmares you refer to are probably those of developers who started with MV and ended up running up against the limits of simpler patterns and been left in dead ends with huuuuge amounts of technical debt to swap to MVC or something else. Given the nature of having to cope with HTTP and its idiosyncrasies, and the complexity of HTML and CSS and everything you have to deal with there, and databases and persistence, let alone business logic, I think MVC is almost always justified for web apps.
Focused little gems that only have a few classes to deal with, fill a specific need and whose component views are unlikely to be reused in any other context? I wouldn't be so strict about it.

Ruby/Rails: The right way to override rails methods?

I'm creating a rails gem that adds functionality to Rails' fields_for method, and I'd like it to be callable from any form builder. To keep things concise, inheritable (from form_for, nested_fields_for, etc), and backwards-compatible, I'm beginning to think overriding the fields_for method is the best way to go about it.
I've not done this before though, and I can envision some ugly problems. Specifically:
I need to call the original fields_for method (via alias_method) in the new one. If Rails changes how that method works in the future, I'm guessing my gem will break all fields_for functionality(?)
If another gem overrides fields_for, I suspect either my or the other gems' fields_for method will be ignored(?)
In general, the idea of overwriting an existing rails method just seems pretty shifty.
I'm sure this is something other developers face, and I'm just wondering - what's the standard approach to overwriting rails methods? Is it a big taboo amongst better developers? Is there another approach to this sort of issue? Should I just sod my attempt for a concise, elegant solution and do it up with a different method name after all?
Any suggestions appreciated.
Rather than overriding your methods, I would take a page from simple_form and formtastic. Both of which effectively change the form_for method, but they create a new method on top.
<%= simple_form_for #model do |f| %>
<% end %>
This way you can delate out to form_for for everything you don't respond to, and stay insulated from method signature changes.

Collection_select has always only 1 item, not an array? In ruby on rails

I am implementing in Ruby on Rails and I am trying to work with the collection_select, I'm a newbie. I just want to do, I have a list with groups and a list with roles. These are both models. So, I list my groups, and next to that, I have a dropdown list with the role for the group. each group has 1 role.
I implemented some code already, but the collection_select always only remembers the last item. So I want a list with groups, connected with the desired role. But, now I only have 1 item. This is my view:
<% #groups.each do |group| %>
<li>
<%= collection_select('group', 'role_id', #roles, 'id', 'name') %>
</li>
<% end %>
I don't really know what to do now? Someone who knows what I am doing wrong?
Thanks
So, I assume that you're doing a form? What model does the form belong to?
To help debug this sort of thing, usually it'd be a good idea to check your development.log file to see what parameters the form is passing to the controller. Something like:
Parameters: {"commit"=>"Save", "action"=>"update", "_method"=>"put",
"id"=>"6168", "group"=>{"role_id"=>"2", ...}, "controller"=>"groups"}
Now, usually a Rails controller is expecting a form with the data for a single model. If you're wanting to update multiple models or rows at the same time, you're going to have to get creative.
First thing to do might be to try returning an array of groups. Your form at the moment is not using an array. I doubt that these Rails helpers will help you though. Helpers like these are designed to update one ActiveRecord object at once.
It's possible you may need to rethink the design of your app to better fit the Rails way, or roll your own form and iterate over the array that it passes through. Doing it the Rails way is the recommended option, it just might take some brain bending from your end to figure that part out. If you need help, maybe provide more information on what you're actually trying to achieve.

way of implementing links in rails

I have a project I am doing in rails. I want to implement this sort of links
{user} has {action} on {file} in {project}
each of the words wrapped by curly braces are entities in my system (models). how do I implement saving these changes in the project and how do I get all of the changes from the database and display them to the user?
I am using rails 2.3.8 if it matters
example of the links I need to display (image)
There are some plugins available to keep track of activities in models:
https://github.com/grosser/record_activities
https://github.com/linkingpaths/acts_as_scribe
https://github.com/face/activity_streams
I normally use acts_as_scribe, it's the simplest of them.
I would recommend acts_as_audited. It works very well. It saves all your changes on a model in the form of a hash, so using it becomes as easy as
audit = Audit.first #just for example
In your view
<%= link_to User.find(audit.user_id), user(:id => audit.user_id) %> has
<%= audit.action %>
Of course you will have to customize how your messages will finally appear. And of course its better not to use find methods in your view. I've used it here just for illustration purposes.

Resources