I'm new to rails, and right now I've got a simple application with a controller and view. The page loads up and the controller does a ton of http requests (can't change this) and populates an array of structs. The controller sorts it and the view iterates through and displays it in a table.
I would like the user to be able to click one of several buttons and sort the data in different ways. Right now, I simply pass a :sort variable with a page reload, sort a different way and voila. But, I was wondering if there was a way to sort this array without having to repopulate it. This might be a super simple question and I'm just not searching for the right thing. Basically, can I pass the array back to the controller so it can sort and reload the page? Thanks for any help.
There is a good cast about sorting, I'm sure you find your answer here: http://asciicasts.com/episodes/240-search-sort-paginate-with-ajax
you can use JQuery table which will not fires the server request.
For Demo check
http://datatables.net/
Related
I'm trying to build a website that users create contents of a table and display them. I'm using Ruby on Rails to work on this project. So far I can let users create new rows and display, which is nearly a default function when building an application.
However, I need to know how to limit the number of rows, let's say 15 rows at once, then a user needs to click next button or navigation number (ex, 1,2,3...5) to call next 15 rows of data in the table.
I'm not really sure how to approach this matter.
If I can help on this, that would be a great help.
Thanks!
The easiest way to do what you want is with pagination. There are a number of gems which offer this but I find kaminari the most robust and flexible of these.
Install the Kaminari Gem
https://github.com/kaminari/kaminari -- Add to you gemfile and run bundle install
gem 'kaminari'
Call the Kaminari method in the controller
In your controller, make sure the object collections uses the kaminari method.
#model = Model.all.order(:name).page(params[:page]).per(15)
This is most likely pretty obvious, but just for clarity: The order by is not required for kaminari, the page method will take the parameters from the URL (params are added to the URL when a user clicks on a certain page number or clicks next or prev), and the per method is the number of records allowed on each page.
Add pagination to your view
Now in your view - just call the pagination helper with your object to add the pagination links (Prev 1 2 3 4 5 Next)
= paginate #model
You can also change the look and feel the pagination links, just read the documentation, it's pretty straighforward.
Since this is your first post I will also add:
WELCOME!! Thanks for your post. New questions keep the community on their toes.
Next time you post, keep in mind that everyone here is happy to help, but if you add a few things to your post the answers will come quicker and you won't be downvoted:
Add code snippets and samples to your post, its easier for answers to come if they can see your work and also improves answers if they can mock up code responses based on your original question, less confusion that way
Give links to tutorials you might be using
State what you've tried, and why it's not working as you'd expect / prefer
My application feature a "main" page where most of the action happens: There are tags for filtering and a list of results in a (paginated) table, plus the possibility to select some or all results in a "shopping cart".
This page has to keep track of a whole lot of things: what tags are selected, what items are selected, and how the result table is sorted and what page it's on. Everything has to persist, so if I select a new tag, the page must partially reload but remember everything (sorting, what's selected).
Right now I'm handling everything with parameters, and for each action taken on the page, all links (select a tag/item, change page, sort table) are updated to include previous parameters + the relevant new addition. This works, obviously, but it feels kind of inefficient, as I have to reload more of the page than I want to. How is this situation normally handled? I can't find that much info on google at all, but it doesn't feel like a particularly uncommon case.
tl;dr: How to best make sure all links (to the same page) always include everything previously selected + the new action. There are a lot of links (one per tag to select/deselect, one per result item to select/deselect, one per sort option, one per page)
There are five ways to do that:
Method 1: By parameters
You mentioned this. I never think of this as it's too troublesome. Anyway it's still a solution for very simple case.
Method 2: By cookie
Save the settings to a cookie and read the cookie in controller to arrange layout settings.
Method 3: By LocalStorage
Similar to cookie but allows more space.
Method 4: By Session
If you are using ActiveRecord to save session, this could be the best solution for pure pages loading. Save the user preferences into session and load it in next layout.
Method 5: Use Ajax
This is the best solution IMO. Instead of whole page loading, use Ajax to refresh/retrieve changes you need. Using together with above method, a user can even continue his last preferences. This is the most powerful and should be applicable to your case which looks like a web app than a website.
Have you tried creating model for all those attributes? and just always load the 'latest' when on the page load, if you dont need them you can always have a flag for that session.
It's not often that I find myself completely baffled as to how to go about solving a problem, but for this one, I honestly haven't a clue.
I'm building a site that has many projects, and on the homepage, I'd like people to be able to browse these projects by turning on and off filters. One of the filter types, for example, is GENRE. The user sees a list of genres which, when clicked, filter out all projects that match that genre. Furthermore, if you click on two different genres, you'll see only the projects that match BOTH of those genres.
The problem is, this all needs to be done via AJAX, and that's when things start to get confusing for me. How can I make an ajax call that not only sets up a new filter, but remembers the filters that are currently in place? When the page is loaded, I could do something like
First Genre
Second Genre
But the problem is that when I click two at a time, I end up only filtering by a single genre. I could, perhaps, update all the links to contain an array of already-selected genres using JS each time one is clicked, but this seems incredibly sloppy. Each and every link would then have something like:
First Genre
Another thought I had was to maybe store all current filters in a cookie and then when a link is clicked, add that new filter to the list of filters in the cookie, but again, this seems sloppy.
Point is, I have no idea what the proper way to do this is, and I'm feeling a bit lost. To anyone out there who's had success doing something like this before, help!!
Ajax filters always create two issues from user point of view. one is user can't bookmark filter urls and can't use back button.
For example, user click on filter 1, then click filter 2. if user click on back button or reload page, user will lose all filter data.
Here is one method to manage all
You can use this method Jquery BBQ http://benalman.com/projects/jquery-bbq-plugin/
on click of genre filter, you can append filter values into hash of url by using above plugin and whenever user reload page or use back button, you have all selected genres into hash.
I have a search page which finds candidates.
From this page you can click view to find more information about the candidate.
When on the candidate view you can click edit or do a number of other actions which would return you too the candidates view.
My problem is from the candidates view I need to add a button to go back to the search results.
I originally thought of using a JS button with history -1 but because the user can do other action from inside the view this won't work.
I am still quite new to rails so not sure of my options... I am thinking some sort of caching of the results and then maybe a hidden field to keep track of the location of the cache(don't think this is the best solution as keeping track of the hidden value could get abit messy!)
Thanks, Alex
I would probably use a session variable to store this information.
First, make sure your form that posts to the search page is a GET operation, this way the search details are in your query string. Then in your search action, you can grab the request URL and store it in the session:
session[:search_results] = request.url
Now in your view for the results, you can do your "Back to search results" like this:
link_to "Back to search results", session[:search_results]
You have a couple of options:
Cache the results, as you've suggested. The potential downsides to this are that it takes memory, and if new valid records get added, you won't see them. You could store the cache in Session, or in the database (though in the latter case, you don't gain much).
I'd suggest just remembering the last search term, either in session or using hidden fields. You end up re-running the query when you go to the search results page, but in a properly indexed DB, that shouldn't be a big deal.
Good luck!
You can include the parameters for the query on the subpage. Eg.: /foo/search?q=stuff displays search result. Each result then has a link like /foo/:id?q=stuff. And on the subpage, you will have the parameter available to link back to the main page.
This solution doesn't use any server side state, which is generally accepted as the better way to build web applications. Not only does it mean that you browser will behave as expected, with respect to bookmarks, multiple tabs etc., but it also ensures that proper caching can be employed. Further, it lowers the complexity of your application, making it easier to debug and extend.
You could put the search results in a "search_results" table keyed by the user id. Then when the user hits the page, always load from a query on that table.
If anybody does come across this page and you need a button that goes back to the previous page and still display those search results (just like the google chrome button), just use :back.....
<%= link_to(image_tag("back.svg"), :back, :class => 'back_btn') %>
I am working on some code that scrapes a page for two css classes on a page. I am simply using the Hpricot search method for this as so:
webpage.search("body").search("div.first_class | div.second_class")
...for each item found i create an object and put it into an array, this works great except for one thing.
The search will go through the entire html page and add an object into an array every time it comes across '.first_class' and then it will go through the document again looking for '.second_class', resulting in the final array containing all of the searched items in the incorrect order in the array, i.e all of the '.first_class' objects, followed by all the '.second_class' objects.
Is there a way i can get this to search the document in one go and add an object into the array each time it comes across one of the specified classes, giving me an array of items that is in the order they are come across in on the page i am scraping?
Any help much appreciated. Thanks
See the section here on "Checking for a Few Attributes":
http://wiki.github.com/why/hpricot/hpricot-challenge
You should be able to stack the elements in the same way as you do attributes. This feature is apparently possible in Hpricot versions after 2006 Mar 17... An example with elements is:
doc.search("[#href][#type]")
Ok so it turned out i was mistaken and this didn't do anything different to what i previously had at all. However, i have come up with a solution, wether it is the most suitable or not i am not sure. It seems like a fairly straight forward for an annoying problem though.
I now perform the search for the two classes above as i mentioned above:
webpage.search("body").search("[#class~='first_class']|[#class~='second_class']")
However this still returned an array firstly containing all the divs with a class of 'first_class' followed by all divs with a class of 'second_class'. So to fix this and get an array of all the items as they appear in order on the page, i simply chain the 'add_class' method with my own custom class e.g. 'foo_bar'. This then allows me to perform another search on the page for all divs with just this one tag, thus returning an array of all the items i am after, in the order they appear on the page.
webpage.search("body").search("[#class~='first_class']|[#class~='second_class']").add_class("foo_bar")
webpage.search("body").search("[#class~='foo_bar']")
Thanks for the tip. I hadn't spotted that in the documentation and also found another page i hadnt seen either. I have fixed this with the following line:
webpage.search("body").search("[#class~='first_class']|[#class~='second_class']")
This now adds an object into the array each time it comes across one of the above classes in the document. Brilliant!