I have a model named Employee that has over a dozen fields making it impractical to display all fields at once. I would like to allow users to choose which columns are displayed by using either a multiple select box or a list of checkboxes, the result of which would ideally be stored in memory, not in the model since nothing will be saved long term, and be accessible for a loop to display the appropriate columns.
A sample of the view might be like so:
<% for employee in #employees %>
<tr>
<% for col in col_list %>
<td><%= employee.col %></td>
<% end %>
</tr>
<% end %>
where col_list is the list of columns selected by the user.
A better approach might be to output all the columns server side and do the filtering with javascript in the client. There are several libraries for this such as jQuery Datatables.
You can combine this with a preferences model which is persisted to the session or Redis instead of the main RDBMS if you want to remember the user prefs.
(Yes, you can use models for objects not stored in the DB. It gives you all the rails awesomeness of validations, form and param binding etc.)
As it is described, there is nothing particularly complicated in this feature.
If you have the users logged in somewhere, you can store a serialized list of columns somewhere in a preference for the user. The list of columns should probably be sanitized to avoid showing private columns.
If the user is not logged in, or you want a less persistent approach, simply store the list in a cookie.
If the list is not set (aka the cookie is empty), set it to a default or just render a default list of attributes.
Related
I'm trying to build a step by step form that transforms large sets of data in batches. I want to have the data saved to the database only on the last step. The way I've seen to create forms like this is to save the data in session storage.
session[:stored_data] = large_dataset
But this gives me a CookieOverflow error when trying to save to it.
What are my other options? Am I stuck with saving the data to the database between steps?
You could actually store it in the form itself.
On the first form you might have...
<%= f.text_field :name_of_dog %>
...and on the second form you could store the first form's fields but in a hidden field.
<%= f.hidden_field :name_of_dog %>
This way you carry the data through all the subsequent forms and when the final form is submitted, you have the complete data you need to persist to the database.
I do this for single db records where the amount of information may be overwhelming for the end user or when you're displaying a limited amount of record data per page (say, because you're in an iframe).
I often also have an attr_accessor called something like :page so when the create or edit action is called I know which page has submitted.
I'm trying to make a small app in rails where investors can see their balances. The balances are updated by an admin.
The investors are all in a Model called User - is there any way to set up one form in one view where User.balance can be updated for all Users?
The fields in the view can be populated using a <% User.each do |u| %> loop, I guess, but how can I handle the data in the controller?
Thanks!
It might be convenient to implement this in an index view, by using an Ajax-capable gem such as best_in_place, which would let the values be edited in place without the form being submitted.
Just doing some research on the best way to cache a paginated collection of items. Currently using jbuilder to output JSON and have been playing with various cache_key options.
The best example I've seen is by using the latest record's updated_at plus the amount of items in the collection.
def cache_key
pluck("COUNT(*)", "MAX(updated_at)").flatten.map(&:to_i).join("-")
end
defined here: https://gist.github.com/aaronjensen/6062912
However this won't work for paginated items, where I always have 10 items in my collection.
Are there any workarounds for this?
With a paginated collection, you're just getting an array. Any attempt to monkey patch Array to include a cache key would be a bit convoluted. Your best bet it just to use the cache method to generate a key on a collection-to-collection basis.
You can pass plenty of things to the cache method to generate a key. If you always have 10 items per page, I don't think the count is very valuable. However, the page number, and the last updated item would be.
cache ["v1/items_list/page-#{params[:page]}", #items.maximum('updated_at')] do
would generate a cache key like
v1/items_list/page-3/20140124164356774568000
With russian doll caching you should also cache each item in the list
# index.html.erb
<%= cache ["v1/items_list/page-#{params[:page]}", #items.maximum('updated_at')] do %>
<!-- v1/items_list/page-3/20140124164356774568000 -->
<%= render #items %>
<% end %>
# _item.html.erb
<%= cache ['v1', item] do %>
<!-- v1/items/15-20140124164356774568000 -->
<!-- render item -->
<% end %>
Caching pagination collections is tricky. The usual trick of using the collection count and max updated_at does mostly not apply!
As you said, the collection count is a given so kind of useless, unless you allow dynamic per_page values.
The latest updated_at is totally dependent on the sorting of your collection.
Imagine than a new record is added and ends up in page one. This means that one record, previously page 1, now enters page 2. One previous page 2 record now becomes page 3. If the new page 2 record is not updated more recently than the previous max, the cache key stays the same but the collection is not! The same happens when a record is deleted.
Only if you can guarantee that new records always end up on the last page and no records will ever be deleted, using the max updated_at is a solid way to go.
As a solution, you could include the total record count and the total max updated_at in the cache key, in addition to page number and the per page value. This will require extra queries, but can be worth it, depending on your database configuration and record count.
Another solution is using a key that takes into account some reduced form of the actual collection content. For example, also taking into account all record id's.
If you are using postgres as a database, this gem might help you, though I've never used it myself.
https://github.com/cmer/scope_cache_key
And the rails 4 fork:
https://github.com/joshblour/scope_cache_key
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.
I have designed an application consisting of 20+ tables, and utilizing Ruby on Rails.
I am using an authentication system for users to login. I want to display to the user, when he logs in, information related to him that can be found across many tables, between these tables there are all the possible relationships. How can I accomplish this in RoR? Should I consider using views, multiple joins? I did not managed to get information from one model further than 2 tables looking in the tables design using classical approaches like "has many", ":through" etc.
Can you please share your knowledge?
Thanks!
I assume that your User model has relationships with all the tables that contain related information.
Assuming that, you can have an action in UsersController and a corresponding view. In the action you can find out who is the currently connected user, and then get all the data you need from the related models. Return these data to the view and render them as you like.
I think your question is too general, but here are some thoughts...assuming you are making a conventional Rails app
"Should I consider using views?"
Views are what users see in conventional rails apps. So if you want to display data to your users, use views to display data that is made available in the controllers. Each action in the controller will grab data from the models, and have a corresponding view.
So to display books that belong to a user, you might have a Books controller. After a user logs in, you have an "index" action in the "Books" controller that says #user_books = #user.books. In this case, #user would be the user object from your authentication system. A user would have many books, and it is possible that a book would have many users. Then in your views/books/index.html.erb file you have something like:
<ul>
<% #user_books.each do |b| %>
<li> <%= b.name %> </li>
<% end %>
</ul>
to print a list of book names.
Joins are done automagically by Rails, so you don't have to worry about it quite yet. But if your app gets really big and queries are complicated, you may have to rewrite the SQL statements to improve scalability....but that is obviously a good problem to have.
Hope this helps!