use reserved rails word in scaffolding - ruby-on-rails

I'm new to rails, but not to programming. I'm trying to create a Case Management app, I'm running the command
ruby script/generate scaffold Case casename:string caseid:string
This works fine, however because Case is a reserved word I'm getting errors when trying to view localhost:3000/Cases
Is there anyway around this or do I just have to use a different name?
Thanks in advance.

Is there anyway around this or do I just have to use a different name?
There are some words that you can't work around (see below). There may be a way to work around 'case' but you'll make life easier on yourself by changing the name. Don't sweat the small things - there're are plenty of real problems to worry about :-)
Other reserved words here and here
Good luck!

Think you are going to cause yourself more grief than it's worth, personally I would avoid reserved words if at all possible.
The errors are specific to using the word case, so if you still want to, you can make things work if you alter the default views from:
<% #cases.each do |case| %>
<tr>
<td><%=h case.casename %></td>
…
to:
<% #cases.each do |c| %>
<tr>
<td><%=h c.casename %></td>
…

This is an old question I see, but I try to use alternate spellings of such words. In this example, "Kase" could be used on the backend for cases. Another example would be "Transaktion" for "transactions."
As for handling this on front end, the built-in i18n support (http://guides.rubyonrails.org/i18n.html) may make things easier. For example:
# /config/locales/en.yml
en:
helpers:
label:
kase:
name: "Case name"
Also, I believe there are tricks you can use in the routes file to modify the URLs used, but I haven't tested any of this before.

Related

middleman blockquote ruby function

I am trying to create a method in ruby to handle block quotes from my slim blog posts. Right now, I have the following view helper:
def blockquote(content,author,source=nil,source_link=nil)
data = '
<blockquote>
<p>'+content.html_safe+'</p>
<footer>
<strong>'+author+'</strong>'
if source && source_link
data = data + '
<cite>
'+source+'
</cite>
'
end
data = data + '</footer></blockquote>'
return data
end
Which works for posts like..
= blockquote("When you grow up you tend to get told that the world is the way it is and you're life is just to live your life inside the world. Try not to bash into the walls too much. Try to have a nice family life, have fun, save a little money. That's a very limited life. Life can be much broader once you discover one simple fact: Everything around you that you call life was made up by people that were no smarter than you. And you can change it, you can influence it… Once you learn that, you'll never be the same again.","Steve Jobs, Apple Computers")
however, would there be a better way? I want to wrap the text in something like
- blockquote
When you grow up you tend to get told that the world is the way it is and you're life is just to live your life inside the world. Try not to bash into the walls too much. Try to have a nice family life, have fun, save a little money. That's a very limited life. Life can be much broader once you discover one simple fact: Everything around you that you call life was made up by people that were no smarter than you. And you can change it, you can influence it… Once you learn that, you'll never be the same again.
but I need a way to pass in the author, and option source + source link.
The current method also requires the quote to be on a single line, instead of multiple lines. Thoughts?
I would create a quote_template partial instead of coding html into a method like you did. Then just do something like this:
def blockquote(options={})
... #checks and business logic
render partial: 'quote_template', options
end
And you can initialize it like:
blockquote({
author: "Steve Jobs",
quote: "Some awesome quote...",
...
})
_quote_template.html.erb partial might look something like this:
<blockquote>
<p><%= options[:quote] %></p>
<footer>
<strong><%= options[:author] %></strong>
<% if options[:source] %>
<cite>
<%= options[:source] %>
</cite>
<% end %>
</footer>
</blockquote>
I created the following slim template in my partials directory:
blockquote
p
= locals[:quote]
footer>
strong
= locals[:author]
- if locals[:source]
cite
a[href="#{locals[:source_link]}"]
= locals[:source]
which can be called via middleman partials like:
= partial "components/blockquote", locals: {\
author: "Steve Jobs, Apple Computers",\
quote: "When you grow up you tend to get told that the world is the way it is and you're life is just to live your life inside the world. Try not to bash into the walls too much. Try to have a nice family life, have fun, save a little money. That's a very limited life. Life can be much broader once you discover one simple fact: Everything around you that you call life was made up by people that were no smarter than you. And you can change it, you can influence it… Once you learn that, you'll never be the same again."}

Rails 4 Fragment Caching

I'm trying to increase performance for my app so I'm looking into fragment caching.
I'm trying to understand what to cache. For example, on all pages of my site I display a list of recent articles.
In my application controller I have a filter that sets:
#recent_articles = Article.get_recent
I have the following in my view/footer:
- cache(cache_key_for_recent_articles) do
%h3 RECENT ARTICLES
- #recent_articles.each do |article|
.recent-article
= link_to add_glyph_to_link("glyphicon glyphicon-chevron-right", article.name), article_path(article, recent: true)
- if Article.count > 4
= link_to "MORE ARTICLES", articles_path(), class: "btn btn-primary more-articles"
My question is. Am I properly caching this? I'm tailing the logs, but I see a query for the articles so I'm assuming no. It's not clear to me what this would do when I query in the controller, but cache a section of the page.
Is this a place for low level caching rather than fragment caching?
Thanks.
You're doing it right. It might seem silly, because it always has to make the db hit anyway, but the gains can be substantial. Imagine each article had threaded comments, with images. In this case, if you kept the controller the exact same, using the same caching construct would save you a tremendous amount of db effort. So, yeah, if you can pull from memcached instead of running through haml with a bunch of rails helpers (those link_tos aren't free) you'll save a bit for sure, but the real gains are found when you can subtly restructure your architecture (as lazy as possible) in order to really take advantage. And that initial hit on Articles? Your db should do a pretty good job of caching that call, I'm not sure you would want to cache it too aggressively, in this case anyway, given the name of the method called.

HTML "class" and "id" attributes using hyphens instead of undescores in Rails 4

Rails fills the id and class of an element generated with various input tag helpers (text_field for example) by itself. For example, in a form_for(#athlete), adding a text_field :height generates
<input name="athlete_height" ... />
I am a strong advocate of the use of hyphens in HTML ids and classes (and in CSS selectors consequently) (by reading MDN, because I like to write using the conventions dictated by the language - like in data-stuff - and because it's just better looking).
I read here and there that in Rails you can't fix this. This would be quite disappointing.
Do you know a way around this problem?
I'm afraid, underscores are hardcoded. From https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/form_helper.rb, lines 446-450:
options[:html].reverse_merge!(
class: as ? "#{action}_#{as}" : dom_class(object, action),
id: (as ? [namespace, action, as] : [namespace, dom_id(object, action)]).compact.join("_").presence,
method: method
)
you can always provide your own id and class, or patch code of ActionView, which may be hard, tedious and error-prone
Recently ran into this very same situation and #lobanovadik has a good solution: just write your own helper method.
# app/helpers/dom_helper.rb
module DomHelper
dom_id_helper(model)
dom_id(model).dasherize
end
end
# view.html.erb
<%= link_to "Text", path, id: dom_id_helper(#model) %>
#=> Text
This has the benefit of not monkey-patching Rails or messing with any default methods/configuration. Thus, you won't "break" any updates to Rails.
It also gives you greater flexibility because you can now use both dashes or underscores depending on the situation. For instance, let's say there's a gem that expects IDs to have underscores...you won't break it.
As a personal preference, I always append _helper to all my own helper methods, so that I know it's a helper method and that it came from me and not from Rails (easier to debug).

Is there a way to do an early exit or "return" from a view in Rails?

Does Rails offer any way to exit early or "return" from a view that is being rendered?
For example, I have a view structured as follows:
<h1>Your records summary</h1>
<% if #current_user.has_records? %>
<p>You don't have any records.</p>
<% else %>
... long block of view emission code here ...
<% end %>
In non-erb code, I'd just return from that if condition, and wouldn't need to put that long block inside an else. It would look like:
<h1>Your records summary</h1>
<% if #current_user.has_records? %>
<p>You don't have any records.</p>
<% return (or something) %>
<% end %>
... long block of view emission code here ...
Is there a way to do something like that in the erb?
EDIT: To be clear, I'm not asking for alternate approaches, such as have been suggested. I'm not a Rails noob. I really just want to know whether Ruby provides a mechanism for what I suggested or not.
This is an old question, but I figured I'd take the time to spare future people the hour or so of their lives trying to figure out if this is doable.
I've discovered that, as far back as Rails 3.2, this is actually possible.
It requires some knowledge of ActionView internals and I do not advocate anyone do this in production code. Further, this particular implementation only works with the built-in ERB engine used by Rails which, itself, uses Erubi.
Alright, now that we're done with the warnings, on to the action!
The surprisingly simple answer is to return #output_buffer.to_s.
As long as you've closed all your HTML tags before returning, it seems to work and everything is correctly rendered.
For the curious, this output buffer is currently configured in the initializer for the Erubi ERB handler. With the rest of the work done by the underlying Erubi::Engine implementation.
I've poked around at something that provides a less brittle way to go about returning early, but I've unsuccessful so far.
In Rails 3.2.2, return inside a template works just fine for me.
<% return unless allowed_tags %>
IIRC there's no built-in mechanism for exiting a template early. This is in line with how (I think) a view layer should behave, although erb isn't quite a template engine.
The old-timey solution was to wrap your template in a catch and throw something from within the template, like a symbol.
You could also embed the eval inside a lambda, allowing return to work.
Still ew, though.
The best way is to handle the conditional in your controller before rendering the template. There you can early return a different template (like the Add Record form) or the results template.
You can also offload that logic to Javascript in the view itself.

Rails View DRYness - Do you set variables in the view or just make clean methods?

I have a view in which I have the same link 3 times (actual view is large):
%h1= link_to "Title", model_path(#model, :class => "lightbox")
= link_to "Check it out", model_path(#model, :class => "lightbox")
%footer= link_to "Last time", model_path(#model, :class => "lightbox")
That model_path(#model, :class => "lightbox") call, though fairly clean, can be made even leaner wrapping it in this (maybe you had some more options, so doing this was worthwhile):
def popup_model_path(model)
model_path(model, :class => "lightbox")
end
My question is, I am having to recalculate that path 3 times in a view. What is the preferred way of a) DRYing this up and b) optimizing performance?
I think setting variables at the top of the view might be a good idea here:
- path = model_path(#model, :class => "lightbox")
-# ... rest of view
It's almost like mustache in the end then. What are your thoughts?
I think using variables in the view is a good idea here. Since these method calls are exactly the same.
The solution as proposed by Matt i prefer in some cases, but not in this case, because i find it confusing: the fact that it is cached in the method is not clear, and if i want to see two different models in one page i still get the first cached link for both models.
So in this case I would choose the somewhat more explicit approach and assign it to a variable in the view.
I really hate putting variables in the view. I would change your helper to
def popup_model_path(model)
#model_path ||= {}
#model_path[model] ||= model_path(model, :class => "lightbox")
end
to "memoize" it, and just keep the three function calls.
This seems like a possible case of premature optimization. Making a function like popup_model_path is a fantastically DRY idea. Especially if that bit of code, however terse it may be originally, is going to be used frequently across multiple views. However, worrying about the performance impact of calculating the path 3 times in one view is, in my opinion, needless. Unless we're talking about something that is going to be used dozens or hundreds of times per view, and you're expecting many many simultaneous users, and the app is running on a shared server or something I really don't see what you have currently having any perceptible impact on performance.
As a general rule, I do my best to avoid variables in my view code. They make it harder to read and with a few exceptions (such as variables directly related to loops that display stuff like lists) I feel they kinda go against the whole MVC concept as I understand it.
I think above all else you should strive for code that is easily readable, understandable, and maintainable; both for yourself and others not previously familiar with your project. popup_model_path as you have it now is simple enough to where anyone who knows Rails can follow what you're doing. I don't see any need to make it any more complicated than that since it's not terribly repetitive. I wish I could find this excellent blog post I remember reading a while ago that made the point that DRYing up your code is great, but it has its limits, and like all great things the law of diminishing returns eventually kicks in.

Resources