I get this error in Rails 2.3.9 but not in 2.3.8. I didn't changed any code. Did I missed anything?
ActionController::InvalidAuthenticityToken in SessionsController#create ActionController::InvalidAuthenticityToken
Thanks :)
Here are the added details.
Request
Parameters:
{"commit"=>"Login",
"authenticity_token"=>"A9A4+sCsA/81FFoXJEUNziQYhgQ38pceGN2i7MUQbQY=",
"password"=>"r3dp0rt"}
Here's the code in the application controller
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery :secret => "r3dp0rtP#$$", :digest => "MD5" # See ActionController::RequestForgeryProtection for details
Here's the code from my session create controller
def create
session[:password] = params[:password]
flash[:notice] = "Sucessfully logged in"
redirect_to "/login"
end
and lastly here's the code from my simple login view
<div id="placeholder">
<% form_tag :action => "create" do %>
<p>
<%= label_tag "This will enable administrative features for the site." %><br>
<%= password_field_tag "password" %>
</p>
<br>
<p>
<%= submit_tag "Login" %>
</p>
<% end %>
</div>
There's a bug in the 2.3.9. It prevents to set the session ID when using an activerecord or memcache session store. See this rails ticket. You can fix it by using the Mislav's patch at http://gist.github.com/570149. You'll have to create and paste the code in config/initializers/sessions_patch.rb. Or you can run the following command in your project root path:
wget http://gist.github.com/570149.txt -O config/initializers/sessions_patch.rb
Finally don't forget to restart your server (and a maybe issue a rake db:sessions:clear).
I don't have enough points to leave as a comment to the accepted answer so I will add this as an answer. The patch does work but just be careful to name it sessions_patch.rb so it will be ordered alphabetically AFTER session_store.rb. As I found out the hard way (by mistakenly naming the patch session_patch.rb, the order of the initializers matters and the patch won't work if it is loaded before your key and secret are set in session_store.rb. Hopefully this saves someone some time.
Have you tried clearing the browsing data of your browser? Most likely it's still sending the old AuthenticityToken.
Related
I have some global settings I want to be able to change through the user interface. The gem ‘rails-settings-cached’ seems to be the tool of choice for this.
I run into a problem with it though when working with a field of type hash.
With the example given in the installation readme (relevant code below for reference), when I first view the settings page in the browser, the default hash displays ok in the form (in YAML format). After form submission, the hash doesn’t get saved to the database and on page re-render the form displays --- !ruby/hash:ActiveSupport::HashWithIndifferentAccess {}.
On investigation, I found the offending line in the source code YAML.safe_load(value).to_h which fails with error ‘
Tried to load unspecified class: Symbol (Psych::DisallowedClass)
’
If I change this line to:
YAML.safe_load(value, permitted_classes: [Symbol, ActiveSupport::HashWithIndifferentAccess]).to_h
It works as expected. I’m on Rails 6.1.6 and Ruby 3.0.1
My questions:
Am I missing something?
How do I apply this workaround in production? One option I think would be to install the gem directly into my project file rather than adding to the gemfile (bundle install --path vendor/bundle) and make the edit directly from there (and then push to production).
How do I give feedback to the gem author?
Thanks
Daniel
app/models/setting.rb
class Setting < RailsSettings::Base
field :hash_test, type: :hash, default: {
logging: true,
email: "foo#bar.com"
}
end
config/routes.rb
resource :settings
settings_controller.rb
class SettingsController < ApplicationController
def create
setting_params.keys.each do |key|
Setting.send("#{key}=", setting_params[key].strip)
end
redirect_to admin_settings_path, notice: "Setting was successfully updated."
end
private
def setting_params
params.require(:setting).permit :notification_options)
end
end
app/views/settings/show.html.erb
<%= form_for(Setting.new, url: admin_settings_path) do |f| %>
<div class="form-group">
<label class="control-label">Notification options</label>
<%= f.text_area :notification_options, value: YAML.dump(Setting.notification_options), class: "form-control"%>
</div>
<div>
<%= f.submit 'Update Settings' %>
</div>
<% end %>
I'm not good at ruby but I have to make a project using rails and I encountered a problem. I'm making a forum application where a user can have multiple profiles and change between them. After many hours I thought that maybe it would be easier if I added a whole column to the Users table called current_profile_id where I'd store the current chosen profile by the user. I am using the PATCH method to insert a profile id into the table but upon doing that the transaction gets rolled back and I am left with nothing. I am a total newbie and kinda don't want to do this so my code is most likely terrible.
view:
<% #user.profiles.each do |profile| %>
<%= link_to content_tag(:div, profile.name), users_profiles_path(:current_profile_id => profile.id), method: :patch %>
<% end %>
<div>
<%= current_user.current_profile_id %>
</div>
user controller:
def setProfile
#user = User.find_by(id: params[:id])
#user.current_profile_id = params[:current_profile_id]
#user.save
end
route:
patch '/users/:id/profiles', to: 'users#setProfile'
screenshot from wsl teminal
I know the idea isn't really thought through but at this point I kind of have to roll with it.
The problem isn't with your patch request per se: it's that you don't have a view template set up for the controller to forward to. Try creating view template to go with your setProfile action, or redirect the request to another location from that action.
I am very new to Rails, and been asking lots of questions recently, I'm getting increasingly frustrated with figuring out how to work things in rails (i.e logging to console, routes, etc..), now I'm trying to figure out how to communicate between an HTML form (and please raw HTML, not form helpers or any of that voodoo magic, I really am trying very hard to like rails, so one thing at a time), if you want to add helpers, please explain what they are doing, where they go, how to use, etc...
I've tried all the examples on the first/second google page (gruesome I know! second google page?!)
What I am looking for is an example, and an explanation.
Also, how does it fit in with routes? (i.e what would be the proper way of setting up a controller/view, and routing them without the controller in the URL)
Please keep in mind, I am not using any models, just controllers, and views.
Your thoughts are much appreciated.
Oh no! Sorry that Rails is giving you grief, especially about form helpers! It's a shame because Rails' form helpers are pretty great, and IMHO are a super useful part of Rails in reducing code duplication, and allowing you to not worry about the specific field names that you are submitting to a server. (They're hard to get accustomed to, but worth it.)
Let me give you a summary of Rails form helpers. For starters, let's take this a simple example
<form action='/users' method='POST'>
<input type='text' name='username' />
<input type='password' name='password' />
<input type='submit' name='Create user' />
</form>
Ah, the most basic user signup form imaginable. This will POST to /users, which is REST-convention for "create a user".
The Rails Routing guide tells you that if you have a controller UsersController (in app/controllers/users_controller.rb -- the filename must be exactly this) and a route resources :users, then this will call the code in the create method of UsersController, and you will have access to the form POST data via the params hash, i.e. params[:username], params[:password], etc.
It is in that controller action where you would create an instance of your User model and save it to the database. (If you aren't using models, you're missing out on most of the magic of Rails's forms.)
Okay. So far so good, right?
Let's spice things up a bit by using Rails's form helpers.
A quick rewrite of the form using basic Rails form helpers would look something like this.
<%= form_tag '/users', method: 'POST' do %>
<%= text_field_tag 'username' %>
<%= password_tag 'password' %>
<%= submit_tag 'Create User' %>
<% end %>
So far, no Rails magic - it's a straight translation into HTML.
Let's add some Rails marrying.
Again, assuming you have a User model with a username column and a password attribute (attr_accessor :password), and your UsersController's #new method looks like this:
def new
#user = User.new
end
Then, in this form (which lives in app/views/users/new.html.erb), you can use that unpersisted User object to make the form more intelligent:
<%= form_for #user do |f| %>
<%= f.text_field :username %>
<%= f.password :password %>
<%= f.submit 'Create User' %>
<% end %>
Note the do |f| part of the form_for line. The f is a form object, which remembers the object it describes. So, you can call f.text_field :username, and the field will magically have the existing value of #user.username populated as the value of the <input>.
Then, if you have a UsersController#create method that looks something like this:
def create
# Instantiate a new user with the inputted parameters from the form
#user = User.new(params[:user])
if #user.save
# user is saved successfully! redirect somewhere....
else
# user couldn't be saved successfully, because of some rule that you
# define on the User model - like making sure that usernames are
# unique, or something like that.
#
# so, we can use the attributes on #user to prepopulate the new user form
render :new
end
end
Anyway, I hope that gives you a good overview of why Rails form helpers can be useful, and how to use them with your models. Let me know if you have any questions!
Why am I getting the following error?
nil is not an ActiveModel-compatible object. It must implement :to_partial_path.
I think the error may relate to the tutorial I'm following is using Rails 3.2 while I'm using Rails 4.
Here is the model code:
class DashboardsController < ApplicationController
def show
#text_shout = TextShout.new
#photo_shout = PhotoShout.new
#shouts = current_user.shouts
end
end
class PhotoShoutsController < ApplicationController
def create
content = build_content
shout = current_user.shouts.build(content: content)
if shout.save
redirect_to dashboard_path
else
flash.alert = "Could not shout."
redirect_to dashboard_path
end
end
private
def build_content
PhotoShout.new(photo_shout_parameters)
end
def photo_shout_parameters
params.require(:photo_shout).permit(:image)
end
end
Here is the view code with the error occurring on the _shout.html partial
# app/view/dashboards/show.html.erb
<%= form_for #text_shout do |form| %>
<%= form.text_field :body, placeholder: 'Shout content here' %>
<%= form.submit 'Shout' %>
<% end %>
<%= form_for #photo_shout do |form| %>
<%= form.file_field :image %>
<%= form.submit 'Shout' %>
<% end %>
<%= render #shouts %>
# app/view/shouts/_shout.html.erb
<%= div_for shout do %>
<%= link_to shout.user.username, shout.user %>
shouted
+---------------------------------+
<%= render shout.content %> <--| ERROR "nil' is not an Active " |
| "Model-compatible object" |
+---------------------------------+
<%= link_to time_ago_in_words(shout.created_at), shout %>
<% end %>
# app/views/photo_shouts/_photo_shout.html.erb
<%= image_tag photo_shout.image.url(:shout) %>
Including ActiveModel into plain Ruby objects
The Thoughtbot Intermediate tutorial in Rails 4 has few complications, but, one problem comes in adding ActiveModel functionality into a plain Ruby object. I see this on the Week 3 Video around the half hour mark while the tutor (AKA Mr Halogenandtoast) is extracting the timeline object.
Instead of: extend ActiveModel::Naming you want to include ActiveModel::Model - Rails 4 change to make it easier to work with plain objects.
class Timeline
include ActiveModel::Model
...
...
For Thoughtbot learn subscribers there's a link to the discussion. Strong parameters were the other problem for this otherwise excellent tutorial.
The problem you are having is because you have existing records in your database that don't have content associated to them. This happens because you went from a non-polymorphic setup to a polymorphic setup. What you need to do is look for shouts that are missing content_type and content_id and remove them from the database. Once those are removed, it could be useful to add
validates_associated :content
to your Shout model to ensure data in the future doesn't end up "corrupting" your database.
#shouts = current_user.shouts on this line your #shouts is setting as nil
check for current_user.shouts, it must be returning as nil
Edit:
instead try this
<%= render #shouts.content %>
I found this error in my development log, which was the issue all along. I was super confused for a little while.
[paperclip] An error was received while processing <Paperclip::Errors::CommandNotFoundError: Could not run the `identify` command. Please install ImageMagick.>
Looks like the fix is just to run brew update (optional) and brew install imagemagick, for anyone else looking for the fix to the thoughtbot tutorial.
Installing imagemagick will solve the issue.
Check requirements section in Readme
https://github.com/thoughtbot/paperclip#requirements
https://github.com/thoughtbot/paperclip#image-processor
brew install imagemagick did the trick.
I was having a similar error, even after cleaning out the database of any old records. The PhotoShout was being saved into the database with content_id: nil, which was clearly the source of the problem.
I cleaned out the database once more, ran brew install imagemagick and the photos began uploading successfully.
I want to have a form that anyone can fill out, but must be logged in to submit it - if not, put the process on hold until they do.
My thought process is if someone comes across the form, it checks if they are logged in, if not the user can still fill it out, but instead prompted to log in or sign up as opposed to "Submit". If they click on either link (log in/sign up) I want it to save the form data, most likely to the session, have them log in/sign up, and then have the computer check to see if there is a saved form, and if so display a confirmation like screen, where the newly registered user can accept it.
I've posted come code below that I thought would work, but it isn't - and I was thinking that knowing rails, theres probably some convention out the to do this much faster and easier!
And I don't believe the way that I am passing the form data around is correct, so if anyone can correct me there that would be great!
View
<%= form_for :comment, :url => {:action => 'create'} %>
form fields here
<% if current_user %>
<%= f.submit "Submit" %>
<% else %>
<%= link_to "Log In", save_to_session_and_log_in_path(:comment => :comment) %> or
<%= link_to "Sign Up", save_to_session_and_sign_up_path(:comment => :comment) %>
<% end %>
Controller
def save_to_session_and_log_in_path
session[:temp_comment] = Comment.new(params[:comment])
redirect_to log_in_path
end
def save_to_session_and_sign_up_path
session[:temp_comment] = Comment.new(params[:comment])
redirect_to sign_up_path
end
User* Controller
def create
#Normal create action, under the redirect:
if session[:temp_comment]
redirect_to confirm_comment
else
redirect_to users_home_page
end
end
The error I am receiving is:
ActiveRecord::RecordNotFound in CommentsController#show
Couldn't find Comment with id=save_to_session_and_log_in
Rails.root: scrubbed
Application Trace | Framework Trace | Full Trace
app/controllers/comments_controller.rb:87:in `show'
Request
Parameters:
{"comment"=>"comment"
"id"=>"save_to_session_and_log_in"}
I've tried tweaking it every which way but it still keeps getting me here so I am unable to test if any of my code is working
What are your CommentsController#create and #show action? About your error, could you paste the rake routes result for the save_to_session_and_log_in_path and the save_to_session_and_sign_up_path methods? Since you don't have an id at that moment, you should set them as collection routes.
--
The way I'd do it, though, is submitting the form to different controllers that will handle each scenario. That way, your CommentsController will be for logged in users and you can have a TemporaryCommentsController that will take care of comments made by guests.
--
Also, depending on the comment's field, I don't know if it's a great idea to store them in the session. You could probably store a tmp_comment_id in the session and recover that from the DB. Also, delete all records with a cron-job. (This is a problem only when "the comment is big and 'hard' to serialize" though).