Rails I18n: shorten the translate calls (at least in the views) - ruby-on-rails-3

What is the DRY way to translate certain fields?
In my RESTful views, I have some repeating snippets, like this in a show-view:
...
<dt><%= t("activerecord.attributes.user.firstname") %></dt>
<dd><%= #user.firstname %></dd>
...
Now, instead of writing t("activerecord.attributes.user.attr_name") over and over again, I'd like to write only t(:attr_name) (similar to f.label :firstname in the form-views).
Basically, this should not be a problem (at least for the RESTful views), since the I18n module could query the controller method to extrapolate the model name and then just guess the correct translation string.
My question: Did anyone have practical experience with this approach? Could there even be a RubyGem for it? Or: are there pitfalls, I didn't think of?

I seems, ActiveModel::Translation#human_attribute_name does the trick (e.g. <%= User.human_attribute_name :firstname %>).

The recommended way to do this is to put this into a partial (e.g. app/views/user/_form.html.erb or even app/views/user/_user.html.erb), and then precede the name with a leading dot, thus:
<dt><%= t(".firstname") %></dt>
<dd><%= user.firstname %></dd>
More information: examples (from Agile Web Development with Rails); Rails documentation

Related

Rails 5 after removal of assigns function for controller tests

I used assert_template and assigns extensively before Rails 5 in my controllers tests. For example to test that a link in the view is correct:
assert_select ".left-off-canvas-menu ul li a[href=?]", event_all_items_path(assigns(:event)), "Back to all items"
I figured that assert_template was not difficult to get rid of.
However, I don't know how to replace test cases like the one above.
I know about the gem to include those functions, but I'd like to try without them. So alternatives would be:
Would you make a case to keep the assigns function or would you say it is meant to be hard coded?

rails form fields_for serialize hash

I need to create a check list for a comment form on which users to notify about a comment.
I have a comment model and i have a column called comment_meta which i want to store as a serialize hash.
My comment form has a fields_for comment_meta example;
<%= f.fields_for :comment_meta do |comment_form| %>
<%= comment_form.check_box(contact.id) %>
<% end %>
The params being passed are "comment_meta"=>{"155"=>"0", "156"=>"1", "157"=>"0"}},
but my db is saving an empty hash.
The field type for comment_meta is a text.
Is there a way to save this?
Your comment_meta hash seems to be a 'key-value pair' of ids and Boolean values, respectively. If this is true, then you may be better off going with a users_comment_metas 'through' table.
You would benefit from restructuring to this methodology because:
db indexing is fast - rails hash serialization/parsing to and from the db is slow (unless your using postgres's h-store, but thats another story)
Dynamic reporting about all data in your db will be much more intuitive/query-able as a developer attempting to display readable reports (which is very important at my job at least).
Your goal of using Rails' built in form helpers will be much easier.
If you truly want to go the hash route you've suggested, there could be a variety of things preventing it from saving. Here's how I would troubleshoot:
First make sure you have the line 'serialize comment_meta, Hash' in your Comment model.
Remove ALL validations you may have in the Comment model for testing purposes.
Now, type 'debugger' (no quotes) in your controller create and/or update
action in your comments_controller (or the controller you are
requesting from the form)
when you hit your debugger statement in your terminal, type the words
'eval comment_params' to check the comment params you've submitted (I am assuming you are using the strong parameters gem, seeing as you typed 'ruby-on-rails-4' in your tags for this post).
The hash should have this structure as you've suggested above (if it looks different,
something is wrong in your form, or you have strong paramters set up incorrectly, more info here):
"comment_meta"=>{"155"=>"0", "156"=>"1", "157"=>"0"}
type 'n' until you've passed the line initializing a new object with the params
#comment = Comment.new(comment_params)
Now type 'eval #comment' to see your new object, and then type 'eval #comment.comment_meta' to see if the hash is being stored. If it's returning nil, then type 'eval #comment.valid?'. If it returns true, then type #comment.errors to see what is wrong, and fix accordingly.
If all else fails, make sure you can do a manual assignment of any given hash to comment_meta of a new Comment object in your rails console:
#comment = Comment.new()
#comment.comment_meta = {"test"=>"1"}
#comment.save!
I hope this gets you on the right track.

Dashes in property name not getting NoMethodError

I'm using the Linkedin gem to pull profile information for RoR 3.
Gem: https://github.com/pengwynn/linkedin
API Doc: https://developer.linkedin.com/documents/profile-fields#positions
Everything works except when I get to a property with a dash in the name.
<%=position.title %> displays correctly but<%= position.start-date %> return a NoMethodError in Users#show - undefined method start.
I've tried different operations like "startDate", "start_date", quotes around "start-date" but none have worked.
Is there a proper way to escape the dash/hyphen in the property name?
The expression in your ERB will be parsed as subtracting the value of the date variable from the result of a call to the start() method of the position object. Hyphens aren't valid in identifiers within Ruby.
I'm not familiar enough with the LinkedIn gem to suggest a solution, except to say that since it's based on an XML API, you should look for a way to manually pull data out of a tag pair. Most similar gems offer such a method. Also, this is a great case for using IRB as an exploratory tool: fire up an IRB session and see what happens when you call position.methods, after properly creating the position variable of course. My guess would be that you'll see something in that list which suggests an answer.
Looks like it returns a Hashie::Mash which converts keys, with a few extra rules:
https://github.com/pengwynn/linkedin/blob/master/lib/linked_in/mash.rb
You said you'd already tried position.start_date right? That should work. But if not, have you tried position['start-date'] or position['start_date'] one of those two should also work, since it's a Mash.

Ruby on Rails 3: rails_admin + puret?

Did someone try to integrate puret into rails_admin? I can't make a language switch to edit different translations :(
Changing I18n.locale forces whole rails_admin to use specified locale.
Now I got the solution. The two can work together well. In short:
Delete the pureted column(s) in your model
If you have the column pureted still in your model, rails form helper will bypass puret. That is, if a model called Post has a field called contents to be i18ned, the table posts SHOULD NOT have the column contents.
Actually we should use globalize3 instead. With this you do not need to remove the original column. And puret doens't support nested attributes assignment. globalize3 works very well.

Mongoid: Changing the order of documents in an embeds_many relation

I have a mongoid document which embeds other documents with a relation like
this:
embeds_many :blocks
Creating new blocks works fine, but I cannot manage to change the
order of existing embedded documents. For example I have three
embedded blocks and I want to move the last one to the first
position.What's the correct way to do that?
I had to deal with this with mongoid's recursively_embeds_many feature, but it's essentially the same. There's nothing wrong as far as I can tell with literally rewriting the document. Write a model method to do something like:
def reverse_blocks
reversed_blocks = blocks.to_a.reverse
blocks.clear
reversed_blocks.each do |b|
blocks.create b.attributes
end
save
end
That's not great code above, but it gives you an idea of how to do what you want to do. I'm not thrilled with having to go through that just to reorder stuff in an array, but there it is.
I think, that really correct way is make in your embedded docs field "weight" and query them with asc(:weight) or desc(:weight). You don't rely on the order of persisted non-embedded docs, so you shouldn't in embedded.
But if you urgently need to make this, your embedded docs in mongoid are just array, so you can do such way:
doc.embedded_docs = [doc.embedded_docs.last] + doc.embedded_docs[0..-2]