Jump to content

The ultimate community for Ruby on Rails developers.


Photo

How to set session value in a select drop-down?

session select

  • Please log in to reply
25 replies to this topic

#1 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 16 August 2013 - 08:16 PM

I am grateful to this forum for helping me out yesterday and I'm wondering if you might get me over another hump today. I come from a .NET background and I can't seem to get the Rails way to do something that seems like it should be simple. I have read through so many posts about topics which almost address this, but nothing quite gets me all the way there. I would really appreciate your expertise. 

 

This is a student enrollment app with students, classes, enrollments, etc.

I am storing a term_id value in the session. It needs to be available to all pages, since most things are viewed by the term. I need each page to have a header with a dropdown menu, so that the user can change the term at any time (these are week-long terms : week 1, week 2, etc). This will display enrollments or classes, etc. filtered for the currently selected term.

 

In .NET I might have a code-behind event (like term_selectChanged) in which I would set the session value to the selected value. I am guessing that there is a Rails way which is just as simple, but I can't seem to find it. Even the book "Rails for .NET Developers" doesn't seem to talk about this. I have successfully implemented collection_select for existing forms, and have tried modifying various versions of select and form helpers, but my head is spinning and I am getting nowhere. I am loving Rails so I think there must be an easy way that is right under my nose.

 

I have also created a user_session model class (without a backing table) as suggested by Ryan Bates (http://railscasts.co...ion-based-model), which allows me to wrap the session in a helper method. I think I understand how that works, but I am not sure it helps me in any way with this.

 

I would really appreciate some guidance. I am open to not using session if there is a better way to have a variable available to all pages.



#2 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 16 August 2013 - 08:27 PM

Sorry, I forgot to mention that I am using the default cookie-based session.



#3 Andre Dublin

Andre Dublin

    Signalman

  • Members
  • 13 posts
  • LocationCharleston, SC

Posted 16 August 2013 - 08:36 PM

I think your on the right path with the user_session object.

 

You'll have to use that helper to access the session information and make it available for your views/controllers to display the proper information.

 

I am assuming that the helper method is made available to all your controller via the application controller

 

For example

class SomeController < ApplicationController
  def some_method
    @value = session_helper_returned_value # set the value from the session to an instance variable and now the view can parse this information.
  end
end


#4 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 16 August 2013 - 08:42 PM

Thanks, Andre,

 

I am familiar with how to get and set the session, I was just hoping that there was a simple way to do it in a select control. If you say ajax is the best way, I will try that. I was thinking that this was such a common thing to do that there might be a simpler way. Perhaps when I work out the ajax code, I will realize that it is in fact a simple way....

 

I appreciate the help!



#5 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 16 August 2013 - 08:56 PM

 

I think your on the right path with the user_session object.

 

You'll have to use that helper to access the session information and make it available for your views/controllers to display the proper information.

 

I am assuming that the helper method is made available to all your controller via the application controller

 

For example

class SomeController < ApplicationController
  def some_method
    @value = session_helper_returned_value # set the value from the session to an instance variable and now the view can parse this information.
  end
end

 

I like where you're going with this. I'll see if I can make it work. If not ....ajax.



#6 james

james

    Guard

  • Moderators
  • 221 posts
  • LocationLeeds, U.K.

Posted 16 August 2013 - 08:56 PM

Data still needs to be sent back to the server for persistence to occur.

You could use Ajax or Javascript to update the server and render any view changes on a change of the select box


Programming is just about problem solving!


#7 Jemagee

Jemagee

    Inspector

  • Members
  • 62 posts

Posted 16 August 2013 - 09:03 PM

I don't know the programming aspect it but it seems like it would be a pretty simple (oneline) ajax command, with an onchange hooked up to the drop down list.

 

OnChange session[:variable] = 'selected option'.

 

That seems as simple as simple gets.



#8 james

james

    Guard

  • Moderators
  • 221 posts
  • LocationLeeds, U.K.

Posted 16 August 2013 - 09:15 PM

An example

select('post', 'state', @suppliers.collect {|s| [s.supp_state, s.id]}, :onchange => "this.form.submit()")

Programming is just about problem solving!


#9 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 16 August 2013 - 10:48 PM

I appreciate the comments.

 

This is what I have so far, which is not quite working yet:

 

In the sections_controller:

def set_user_term(termid)
    user_session.set_term(termid)  #this is a helper method
 end

 

In the view:

<%= collection_select :section, :set_user_term, Term.by_school(session[:schoolid]), :id, :description %>

 (this seems to look right, but selection is not getting changed)

 

 

In the js:

jQuery(document).ready(function($){
   $('#section_set_user_term').change(function() {     
    var selectedid = $(this).val()
    alert("selected id: " + selectedid);  //this is showing the correct selectedid
    $.ajax({                                           //don't know yet if this is hitting the method
      url: "/sections/set_user_term",
      data: {termid: selectedid},
      success: function() {
      window.applicationCache.update();
      }
    });
    location.reload()   
  });
});
Any obvious errors?

Edited by Jamie, 17 August 2013 - 04:15 PM.
Added code tags


#10 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 16 August 2013 - 11:39 PM

The ajax call is not hitting the "/sections/set_user_term" method. Trying to figure out why. I have a lot to learn about debugging.



#11 Andre Dublin

Andre Dublin

    Signalman

  • Members
  • 13 posts
  • LocationCharleston, SC

Posted 17 August 2013 - 07:26 PM

Since your using the full $.ajax object in jquery, go ahead and define the error function

 

Ex.

$.ajax({
  url: "/sections/set_user_term",
  data: {termid: selectedid},
  success: function() {
    window.applicationCache.update();
  },
  error: function(jqXHR, textStatus, errorThrown) {
    console.log(jqXHR, textStatus, errorThrown);
  }
});

This way you can check the returned server error.

Or you can look in whichever browsers network inspector and see what the path returns.



#12 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 19 August 2013 - 03:39 PM

Thanks, Andre,

 

I added your error code. I couldn't see the console message, so I changed it to an alert and it is showing me just  [object Object] at this point.

 

It occurred to me that I was calling a class method but had created an instance method, so I changed the called method to

 

def self.set_user_term(termid)    
    user_session.set_term(termid)
 end
 
Not quite working yet, but I think you've got me very close now, I just have to debug and find an error somewhere...


#13 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 19 August 2013 - 03:42 PM

Thanks,Jamie, for adding the code tags. I'll do that next time. :rolleyes:



#14 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 19 August 2013 - 04:44 PM

In debugging, I am typing the path to the method that my ajax method is calling:

http://localhost:3000/sections/set_user_term?termid=2

and I am getting this error:

Couldn't find Section with id=set_user_term

I have this in the routes.rb file (below), but I think there is something about routes that I am not getting yet.

 

resources :sections do
  member do
     get :set_user_term   
  end
end


#15 Ohm

Ohm

    Guard

  • Members
  • 186 posts
  • LocationCopenhagen

Posted 19 August 2013 - 05:07 PM   Best Answer

You can always run rake routes to get a view at all the routes in your app.

 

Rails make the routes pretty all by itself. Your 

resources :sections do
  member do
     get :set_user_term   
  end
end

instructs Rails to make a resource named sections with a member method named set_user_term. Rails thus creates all sorts of routes for you. If we ran rake routes it would probably give us something like:

set_user_term_section GET    /sections/:id/set_user_term(.:format) sections#set_user_term
sections              GET    /sections(.:format)                   sections#index
                      POST   /sections(.:format)                   sections#create
new_section           GET    /sections/new(.:format)               sections#new
edit_section          GET    /sections/:id/edit(.:format)          sections#edit
section               GET    /sections/:id(.:format)               sections#show
                      PUT    /sections/:id(.:format)               sections#update
                      DELETE /sections/:id(.:format)               sections#destroy

What this tells us is that Rails has created all the default CRUD (Create, Read, Update, Delete) stuff for us. Lets look at the from the bottom up.

 

The destroy and update methods have been given no name (the column at the far left), however, we can see that it is the same route (the /sections/:id(.:format) stuff) as the one named section. The :id here tells us that this is a member method, it needs an id to function. The HTTP-action (GET, PUT, POST, DELETE) used for the request, tells Rails which method to execute (the far right column).

 

Looking at your URL, with set_user_term, Rails want this to be /sections/:id/set_user_term(.:format). So in other for you to test it in your browser, you'll need to direct it to 

http://localhost:3000/sections/2/set_user_term

This is also why you get the error you get. Rails thinks that the set_user_term part in your URL is the id for the section.


Blog: http://ohm.sh | Twitter: madsohm


#16 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 19 August 2013 - 06:26 PM

Thank you Ohm,

 

That was very helpful. I am reading more about routes and trying to understand them better. My problem is that I don't want to call a method for a particular section, In fact, I chose the Section controller arbitrarily, since the method is not related to any existing controllers (it is merely setting a value in the session). But I thought that I needed to put it on a controller, so I chose Section, which seemed most appropriate. But I don't want to call the method for a particular section, so I created a class method on the controller. Perhaps I should find a better place to put the method? 

 

I suspect the way I am doing it is not normal and perhaps not recommended. In the Rails guides under "Singular Resource"  I found this which sounds somewhat similar to what I need, but I haven't got it working yet:

 

"Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like /profile to always show the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action:

get 'profile', to: 'users#show'


#17 Ohm

Ohm

    Guard

  • Members
  • 186 posts
  • LocationCopenhagen

Posted 19 August 2013 - 06:35 PM

Yes, you can do exactly what you write yourself with singular resources.

 

You'd write

get 'set_user_term', to: 'controller#method'

where controller and method are the actual controller and method. If I were you, I'd create a sessions controller to hold this set_user_term method, as it should live where it makes the most sense.

 

In the first post, you have a termid=2 appended. What is this, if not an id for an object?


Blog: http://ohm.sh | Twitter: madsohm


#18 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 19 August 2013 - 07:07 PM

Thank you Ohm,

 

The termid=2 is the selection from the drop down select menu, which is used to filter the enrollments to the selected term. I am passing that value via ajax to the server to set the session value session[:termid]. Then each page checks that in a before filter.

 

I created a sessions controller like this:

class SessionsController < ApplicationController  
  def self.set_user_term(termid)    
    user_session.set_term(termid)
  end
end
   I put this line at the top of the routes.rb file:
get 'set_user_term', to: 'sessions#set_user_term'

When I put this in the browser:

http://localhost:3000/set_user_term?termid=2 

        I get :

 
Unknown action
The action 'set_user_term' could not be found for SessionsController


#19 Jemagee

Jemagee

    Inspector

  • Members
  • 62 posts

Posted 19 August 2013 - 08:04 PM

 

Thank you Ohm,

 

The termid=2 is the selection from the drop down select menu, which is used to filter the enrollments to the selected term. I am passing that value via ajax to the server to set the session value session[:termid]. Then each page checks that in a before filter.

 

I created a sessions controller like this:

class SessionsController < ApplicationController  
  def self.set_user_term(termid)    
    user_session.set_term(termid)
  end
end
   I put this line at the top of the routes.rb file:
get 'set_user_term', to: 'sessions#set_user_term'

When I put this in the browser:

http://localhost:3000/set_user_term?termid=2 

        I get :

 
Unknown action
The action 'set_user_term' could not be found for SessionsController

Don't you need a view called 'set_user_term' within the view/sessions for it to go somewhere?



#20 priorcode

priorcode

    Signalman

  • Members
  • 19 posts
  • LocationCalifornia

Posted 19 August 2013 - 08:18 PM

Jemagee,

 

I didn't think so, but I don't know. I don't need to show anything, I just need to set a value and display the same screen that I'm on. Will a view serve a purpose if it is never seen?






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users