I have a project that uses Sinatra for static pages and Rails for the application.
I allow the request to hit one or the other by doing this in config.ru:
run Rack::Cascade.new([
EightyEightTactical::Root,
EightyEightTactical::Application
])
Where EightyEightTactical::Root is a subclass of Sinatra::Base and EightyEightTactical::Application is a subclass of Rails::Application.
I'm in a tricky situation where I need to set a flash message in a Rails controller and display it in a Sinatra layout.
I notice that Rails uses ActionDispatch::Flash in middleware, but I can't seem to figure out how to access the flash messages outside of a Rails app. Am I mistaken, or can this be done?
Assuming you are using a Cookie session store, you can do the following:
1) Access the session cookie with the name specified in config/initializers/session_store.rb.
2) Decrypt the session cookie to get the session hash
3) Access the key called flash which contains a hash.
4) Iterate and display the flash message.
You should look at ActionController::Session::CookieStore class for more details.
Related
I want to store a non-critical non-confidential piece of information in the user's session in a Ruby on Rails app. The user model is set up with Devise. How do I do this? Various guides give conflicting and incomplete information about it. session[:foo]? user_session[:foo]? Do I need to set something up to be able to use whichever it is - e.g. get a gem, config something, or insert any lines before setting the session variable?
To provide context - the user may be creating multiple new items back-to-back, so it would be nice if the new form remembered and pre-selected the category based on what they selected previously. If there's a better way to do this, I'm open to suggestions. I'm new to all this. Thank you!!
Are session variables in 'session' or 'user_session' in Rails?
The simple answer is the session variables is named session.
A session usually consists of a hash of values and a session id, usually a 32-character string, to identify the hash. Every cookie sent to the client's browser includes the session id. And the other way round: the browser will send it to the server on every request from the client. In Rails you can save and retrieve values using the session method:
session[:cat_id] = cat_id
Category.find(session[:cat_id])
You can read this Rails Guide about session.
ActionDispatch::Session::CookieStore
The default Rails session object is accessible via the session helper method. It gives you an access to some chunks of data and is bound to a cookie value stored in your browser.
The user_session helper is provided by the Devise gem. It gives you additional security by restricting access to specific session data while user is authenticated on a server.
I am developing a web application using rails and devise for the authentication. There are two types of users, one who are able to have multiple concurrent sessions (super) and the others who can only have a simultaneous session (normal). In order to implement this behaviour, I have added a new field on the User model to store the authentication_token (generated in the SessionsController#create). Also, I added a new filter to the ApplicationController which check if the stored token in the session is equal to the saved on the User model when it is a normal user. When it is not the same authentication token, we logout the normal user.
Now I am developing a new ionic mobile application which needs to login to the same rails application. However, in this case all user types can have multiple concurrent sessions. In order to do this, we would like to continue using devise (although we have also considered to use doorkeeper with password flow).
I am not sure about the best approach to get this. The main problem is to detect if we are accesing the API with the rails or ionic application. One approach is to add a parameter but I don't like to use a parameter in all requests. Another approach it is to use browser gem, but we can access the web from a browser in the mobile.
When we uses the rails application, we can use the same behaviour described above. Otherwise, I think it is not necessary to do anything because devise permits concurrent sessions by default.
Another posibility it is to use a new model to store the authentication token and its type (rails or ionic). If we are using the rails application, then we query the rails authentication token and override it (or create if it does not exist). On the opposite, we add the new authentication_token as a new instance related with the user model. With this behaviour we can manually control the expiration of the tokens and store more information (IP, browser...).
I am not sure about the best approach to achieve this behaviour. Thanks in advance.
I have a mailer class that wants to get the remote user. I access it my request.env['REMOTE_USER'] but get request not defined error. i thought i were able to use request anywhere?
undefined local variable or method request for my mailer
Why don't you try loading the remote user in your controller action, and either storing in the db, or redis when you're compiling your mailer
Request
The problem, as stated by Vimsha, is you're not able to access request params outside of front-facing code
According to Rails, how do you access the raw request data at the absolute lowest level?, you can access the data directly from the middleware if you're working with a direct request (I.E your mailer is not delayed etc)
Structure
Further to this, I would also question why you're accessing request-specific data directly from your mailer
The modular (DRY) nature of Rails means you need to be able to re-use as many of the assets as possible, meaning you may wish to use the mailer in a totally unrelated action
I'd personally store the request data in the db (or redis if you only want it temporarily), and access it on demand
I am using MyApp::Application.config.session_store :active_record_store in my application to store Sessions in the database. It all works fine. However, I'd like to be able to load a specific Session when passed the session_id. This is the value that the server stores as a cookie on the client side.
My Rails application has a client that can't use cookies, so it has to pass me the session_id in a parameter. I'd like to use a before_action or some sort of filter to take that parameter and use it to load the session in my Controllers instead of the app loading a null session due to the lack of proper cookies.
Is there some way I can do this? I don't want to turn off the cookie method altogether because my web client uses cookies, it's just my mobile client that can't.
edit:
if I declare class Session < ActiveRecord::Base and then do Session.find_by_session_id('whatever') I do get a Session ActiveRecord object, but I'm not sure how to make this into a usable session in the normal Rails sense.
Just do request.session_options[:id] = "whatever you want" in a before_action filter and Rails will use that session_id to load the Session when you access it (thanks to lazy loading).
I haven't found a good answer to this yet. How can I get my Rails app and Sinatra app (mounted in my Rails app's config.ru) to share a session successfully? If I visit my Sinatra app first, then the Rails app, I get an error like undefined method sweep for {}:Hash, presumably because Rails uses a custom subclass of Hash for storing session info, and Rack::Session::Cookie doesn't. My code so far:
config.ru
map "/" do
run MyRailsApp::Application
end
map "/sinatra" do
use Rack::Session::Cookie,
key: "_app_session",
secret: "<SECRET_KEY>"
run MySinatraApp
end
config/initializers/session_store.rb
MyRailsApp::Application.config.session_store :cookie_store, key: '_app_session'
config/initializers/secret_token.rb
MyRailsApp::Application.config.secret_token = "<SECRET_KEY>" # same as config.ru
Anything I've missed?
A quick grep of the Rails source reveals sweep is a method on ActionDispatch::Flash::FlashHash, which Rails stores in the session under the flash key.
Sinatra-Flash also uses the flash key of the session, but it stores a plain Hash object there.
Rails is getting the object at session['flash'], which is the Hash put there by Sinatra, assuming it is a FlashHash and trying to call sweep on it, hence the error message: undefined method sweep for {}:Hash.
A possible work around might be to use a different key in the Sinatra app for the flash rather than the default (e.g. flash(:my_flash)[:error]="foo").
That won't help if you want to use the flash to see messages when going between Rails and Sinatra though.
The "undefined method sweep for {}:Hash" issue is with your browser storing previously cached cookies. Just delete the cookies related to the application and refresh the browser. It worked for me.