2nd Update
This is the code in my model
after_initialize :start_two_weeks
def start_two_weeks
#subscription = TrialSubscription.all
#subscription.manual_expiry_date =
#subscription.save
end
How do you set the time dynamically from Time.now to Time.now - 2 weeks?
Its a datetime field what is the value for a datetime field?
More Update
this means I didn't log out
Filter chain halted as :require_no_authentication rendered or redirected
I logged out and the user did get created but its through the registration controller.....
Updated
I just realized that the form is posting to /users. The registrations controller is inheritting from devise::registration
Started POST "/users" for 127.0.0.1 at 2014-03-23 19:58:08 -0400
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8xhRi7TBEA+zXfmuzuJLqLjjo5JMkyEjUmgmRT6DsOQ=", "user"=>{"email"=>"helloworld#gmail.com", "password"=>"[FILTERED]"}, "commit"=>"Create User"}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Redirected to http://localhost:3000/
Filter chain halted as :require_no_authentication rendered or redirected
Completed 302 Found in 4.1ms (ActiveRecord: 0.7ms)
The form isn't posting to here
new_trial_subscription GET /trial_subscriptions/new(.:format) trial_subscriptions#new
POST /trial_subscriptions(.:format) trial_subscriptions#create
Ok I am trying to reproduce the stuff that I did in rails console to put them into the controllers.
I have two models
class TrialSubscription < ManualSubscription
accepts_nested_attributes_for :user
attr_accessible :user_attributes
end
ManualSubscription inherits from Subscription and in Subscription model
belongs_to :user
I am building the user model through subscription because of some other reason.
in my rails console I did these
#subscription = TrialSubscription.new
#user = #subscription.build_user(email: "helloworld#gmail.com", password: "thisiseightcharacters")
#subscription.save
I am able to create a user and its associated trial subscription at the same time. I am trying to reproduce this in the controller and the content will be user inputted.
This is my form in
app/views/trial_subscriptions/new.html.erb
<%= simple_form_for #subscription.user do |f| %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>
I added
resources :trial_subscriptions
so the url is trial_subscriptions/new
this is my controller
class TrialSubscriptionsController < ApplicationController
def index
end
def new
#subscription = TrialSubscription.new
#subscription.build_user
end
def create
#subscription = TrialSubscription.new(params[:subscription])
#subscription.email = :email
#subscription.password = :password
if #subscription.save
flash[:notice] = "Trial Subscription has started"
else
flash[:error] = "There was an error creating this subscription, please try again"
end
end
end
1) What is happening between new and create?
2) in my create method the params[:subscription] is pointing to the #subscription object in my form is this correct?
3) The :email is actually user attribute, is it getting passed correctly at #subscription.email = :email?
Your new action looks correct, your create action needs some update. Let's first start from your association then move on to the form and then to your create action.
In the form view code, you are building a form for #subscription.user. The simple_form_for method would translate this to create action in UsersController. But you do not have this and your intention is to create user through TrialSubscriptionsController.
So in order to make this happen, you need to change the form so that when it renders and/or submits it creates the form for trial_subscription along with the defined user_attributes within trial_subscription. So, update your view to:
<%= simple_form_for #subscription do |f| %>
<%= f.simple_fields_for :user do |u| %>
<%= u.input :email %>
<%= u.input :password %>
<% end %>
<%= f.button :submit %>
<% end %>
The changes are simple_form_for #subscription.user to simple_form_for #subscription, and wrapping email and password fields with f.simple_fields_for :user. With these changes, when your form submits, it will execute the create action of the TrialSubscriptionsController.
The next change is on the TrialSubscriptionsController#create action.
def create
#subscription = TrialSubscription.new(params[:trial_subscription])
if #subscription.save
flash[:notice] = "Trial Subscription has started"
else
flash[:error] = "There was an error creating this subscription, please try again"
end
end
The changes here are #subscription = TrialSubscription.new(params[:subscription]) to #subscripition = TrialSubscription.new(params[:trial_subscription]), this is because your object is of type TrialSubscription not Subscription.
The second change is removal of the following lines:
#subscription.email = :email
#subscription.password = :password
This is because, as you say, email and password are members of user not trial_subscription.
Hopefully this helps.
Related
I am building a one page website where visitors will simply be able to submit their email address. The only goal in the database is to get an email (no name, etc). There is only one page visible at first, which is the homepage. If the user submits an email already in use, it sends the user to an error page. If the email is not in use, it sends the user to a success page.
I have asked a question about this previously, and after a lot of comments and trial and error, it appeared that it worked and then it stopped working. When I do Rails C, there is only one user in the system and that user doesnt have an email...
Here is what my user migration looks like :
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :email
t.timestamps
end
add_index :users, :email, unique: true
end
end
Here is what my user model looks like:
class User < ApplicationRecord
end
Here is what users/new.html.erb looks like:
<%= form_for #user, as: :post, url: users_path do |f| %>
<div class="wrapper">
<%= f.email_field :email , id: "search", class:"search input" %> <br />
<%= f.submit "yep", class: "submit input" %>
</div>
<% end %>
Here is my user controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:email])
if #user.save
redirect_to '/users/success'
else
redirect_to '/users/error'
end
end
def show
end
end
Here are my routes:
Rails.application.routes.draw do
root "users#new"
resources :users
end
When i run the code, it renders the homepage but when i click on submit, it sends me on a page called show.html.erb with http://localhost:3000/users/error on my brownser. No users are being saved in the console.
EDIT:
My model is
class User < ApplicationRecord
validates_uniqueness_of :email
end
It is still not working....
change new.html.erb as
<%= form_with(model: #user, local: true) do |f| %>
<div class="wrapper">
<%= f.email_field :email , id: "search", class:"search input" %> <br />
<%= f.submit "yep", class: "submit input" %>
</div>
your controller will be
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to user_path(#user), notice: "yeh!!!!"
else
redirect_to new_user_path, notice: "email already registered"
end
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:email)
end
end
add
<p id="notice"><%= notice %></p> to your application.html.erb in layouts
rest as your question
There are a couple things wrong here.
You're so close, but you're misusing the as: attribute of form_for. Perhaps you think that will send as a POST request, but instead that is actually wrapping your form params in an object called "post". I saw this in the comments on another thread.
Remove the as: attribute and the helper will again wrap your params in the user object. While we're at it, you should also be able to remove the url: attribute as well since Rails form helpers are smart enough to infer that this is a new resourceful record and output the create URL as well as the POST action accordingly.
You need your controller to expect a whole "user" object instead of just checking for the email param. ALSO, assuming you're on Rails 4 or higher, you need to permit the email attribute to be mass-assigned on your User object. See the code.
def create
#user = User.new(params.require(:user).permit(:email)) # Not params[:email]
if #user.save
redirect_to '/users/success'
else
redirect_to '/users/error'
end
end
Also be careful about duplicate emails with different cases. The default in Rails is case-sensitive validation which means "JIM#gmail.com" would not trigger a validation error against "jim#gmail.com". You can fix this with.
class User < ApplicationRecord
validates :email, uniqueness: { case_sensitive: false }
end
BONUS!
Nowadays, it's better to move over to form_with (instead of form_for). It's on its way to becoming the new Rails standard and also makes a few of these things easier. The one point you'll want to keep in mind is that with form_with (and general Rails assumptions), forms are remote by default. So if you want to trigger a full page submit/refresh, add local: true to your form_with helper.
<%= form_with model: #user, local: true do |f| %>
<div class="wrapper">
<%= f.email_field :email , id: "search", class:"search input" %> <br />
<%= f.submit "yep", class: "submit input" %>
</div>
<% end %>
As you are using resources in routes so def show is called when route is /users/:id. That's why its calling show.html.erb file.
When you try to validate an email, then in model write the validation for it
class User < ApplicationRecord
validates_uniqueness_of :email
end
Hope this helps.
Try to add validates_uniqueness_of in your model
class User < ApplicationRecord::Base
attr_accessor :email
validates_uniqueness_of :email
end
And
def show
#user = User.find(email: params[:email])
end
And if you wanna check all
def show
#user = User.all
end
Please try this.
I hope that helpful
I'm stuck trying to get my form with a collection_select to save. I have 3 models (Events, Users, Items), plus a joining model to link Items to Events (Event_Items).
My goal is for each users to be able to join events, and each user can specify a list of items they will bring to the event from an inventory that is unique to each user.
My form partial with collection select looks like this:
<%= form_for [#event, #event_items], remote: true do |f| %>
<%= f.hidden_field :user_id, value: current_user.id %>
<div class="form-group">
<%= f.collection_select(:item_id, current_user.items.all, :id, :title, { :prompt => "Select an Item", :selected => #item_id}, { class: "form-control"}) %>
</div>
<%= f.submit "Submit", class: "btn btn-primary", id: "event-item-button" %>
My event_items_controller looks like:
class EventItemsController < ApplicationController
before_action :authenticate_user!
def new
#event_item = EventItem.new
end
def create
#event_item = EventItem.new
#event = Event.find(params[:id])
if #event_item.save
flash[:success] = "Item Added to List"
redirect_to #event
else
flash.now[:danger] = "Please try again"
redirect_to #event
end
end
def destroy
#event_item = EventItem.find(params[:id])
end
private
def event_item_params
params.require(:event_item).permit(:event_id, :user_id, :item_id)
end
end
In the Event show page, I have this section where I iterate over each attendee and render the Event_Item partials:
<% #event.attendees.each do |user| %>
<div class="col-md-4">
#should render each existing item on the list.
#Doesn't work yet
<%= render 'event_items/event_item' %>
</div>
<% if user == current_user %>
#renders dropdown with only current user's inventory
#currently shows items correctly, just doesn't save to
#database
<%= render 'event_items/form' %>
<% end %>
<% end %>
Whenever I hit the Submit button after selecting an Item in the dropdown, nothing is saved to the database, although the server console shows:
Started POST "/Events/27/event_items" for 127.0.0.1 at 2018-09-26 19:54:32 -0500
Processing by EventItemsController#create as JS
Parameters: {"utf8"=>"✓", "event_item"=>{"user_id"=>"5", "item_id"=>"2"}, "commit"=>"Submit", "event_id"=>"27"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 5], ["LIMIT", 1]]
Completed 404 Not Found in 2ms (ActiveRecord: 0.3ms)
ActiveRecord::RecordNotFound (Couldn't find Event without an ID):
app/controllers/event_items_controller.rb:11:in `create'
In your create action, you do:
#event = Event.find(params[:id])
But, params doesn't have :id, it has :event_id. So, it should probably be:
#event = Event.find(params[:event_id])
And, your create action should probably look more like:
def create
#event = Event.find(params[:event_id])
#event_item = #event.event_items.new(event_item_params)
if #event_item.save
flash[:success] = "Item Added to List"
redirect_to #event
else
flash.now[:danger] = "Please try again"
redirect_to #event
end
end
By doing:
#event_item = #event.event_items.new(event_item_params)
event_id will be set on the new event_item. (This assumes, naturally, that Event has_many :event_items and EventItem belongs_to :event.)
I am trying to build a very simple user authentication for my application. I think the problem is that the 'login' form is not pointing to the :user database. When I create a new user, I have it set to auto-login. That function works great, but when I go to login the same user in the login form, it returns an error of "username is NULL LIMIT 1. I am using Rails 4.2.5 . When I go to the rails console, I can see that the user still exists.
I apologize in advance for my horrible coding habits, I've mostly been teaching myself. Thank you in advance for any help.
Sessions Controller:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_username(params[:username])
if user && user.authenticate(params[:username][:password])
session[:user_id] = user.id
redirect_to root_path, notice: "You are now logged in."
else
redirect_to '/login', notice: "incorrect email or password! "
end
end
def destroy
session[:user_id] = nil
redirect_to root_path, notice: "logged out."
end
end
User Model
class User < ActiveRecord::Base
has_secure_password
validates_uniqueness_of :username, :email
validates :password, length: {minimum: 6}, allow_blank: true
has_many :messages
end
Login Form
<div class="login">
<%= simple_form_for :sessions do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.button :submit, "Login" %>
<% end %>
</div>
When I attempt to login, the terminal returns:
Started POST "/login" for 127.0.0.1 at 2016-06-02 00:02:15 -0400
Processing by SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"WNJziVL/xhAeGdsjNANi6LWlDrAMIGKm2kDWmsVLfxMh6fCwG1LoRWG09wgsn2z3rIZkreODkHZ0GJeYFCW3yQ==", "sessions"=>{"username"=>"crackerjack540", "password"=>"[FILTERED]"}, "commit"=>"Login"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."username" IS NULL LIMIT 1
Redirected to http://localhost:3000/login
Completed 302 Found in 2ms (ActiveRecord: 0.2ms)
Username is within the session object, so instead of this:
user = User.find_by_username(params[:username])
You should be doing this:
user = User.find_by_username(params[:sessions][:username])
Also, further below, to access the password:
user.authenticate(params[:sessions][:password])
Hope this helps!
I have a nested resource placed in a nested form(for email input), and want to send emails using User Mailer. I am facing problems completing following challenges:
1) Have 10 input field generated by :fields_for on my invitation/new page in order to send up to 10 emails at a time.
2) After submission, cycle through the submitted emails and send an email to each of the submitted entries.
3) After emails have been sent, I have no use for the #invitation in the database and want to destroy it.
So far I have the following code:
The Models
class Scoreboard < ActiveRecord::Base
has_many :invitations
accepts_nested_attributes_for :invitations
end
class Invitation < ActiveRecord::Base
belongs_to :scoreboard
def send_invitation_email
UserMailer.send_invitation(self).deliver_now
end
end
The new.html.erb(invitations)
<%= form_for [#scoreboard, #invitation] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.fields_for :invitations do |invites| %> <!-- this gives me one field. Need 10 fields to accept up to 10 emails -->
<div>
<%= invites.label :recipient_email %>
<%= invites.text_field :recipient_email %>
</div>
<% end %>
<%= f.submit "Send Invitation", class: "btn btn-primary" %>
<% end %>
The Invitations Controller
class InvitationsController < ApplicationController
def new
#scoreboard = Scoreboard.find(params[:scoreboard_id])
#invitation = #scoreboard.invitations.build
end
def create
#scoreboard = Scoreboard.find(params[:scoreboard_id])
#invitation = #scoreboard.invitations.build(invitation_params)
if #invitation.save
#invitation.send_invitation_email
flash[:success] = "Invitation sent successfully"
redirect_to new_scoreboard_invitation_path
else
render 'new'
end
end
private
def invitation_params
params.require(:invitation).permit(:recipient_email)
end
end
When I submit the form, in development log I get the following example code for the invitation:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"gS+olMC89noaYs0klYTg6IFgJ2cj4apML/NZbdbu2gia/KXjbPyyvSKrEUoj3rEAWxDknlgNmpnaefy7I6Hk3Q==", "invitation"=>{"invitations"=>{"recipient_email"=>"this#hotmail.com "}}, "commit"=>"Send Invitation", "scoreboard_id"=>"89"}
Using the logic that it's a possible collection of hashes within a hash, I came up with the following code in the User Mailer file:
user_mailer.rb
def send_invitation(invitation)
#invitation = invitation
#invitation.each do |key, value|
value.each do | x, y|
mail to: y , subject: "You have been invited"
end
end
end
Thanks in Advance!
Optional Bonus Question:
send_invitation.html.erb
<p>Hi View this Thanks </p> <br></br>
<%= # if someone could provide me a code to a link_to for the url for the scoreboard that the invitation is attached to that would be awesome %>
I have company model with devise authentication installed on it. It has_many :jobs.
My goal is to successfully create a job record when I am signed in as that existing company and have it be properly linked in my mongoid databse.
I want one form to update multiple models.
I know how to set
accepts_nested_attributes_for :jobs, allow_destroy: true
but I am having trouble passing that instance from my controller to the nested form ?
in my companies controller I have this
def new
#company = current_company.jobs.new()
end
def create
#the actual create process where the params from the forms got sent here
#company = current_company.jobs.new(params[:company])
end
and here is my form
<%= simple_form_for #company do |f| %>
<%= f.simple_fields_for :jobs do |j| %>
<%= j.input :title %>
<%= j.input :description %>
<% end %>
<%= f.button :submit %>
<% end %>
How do I send the current company jobs object to the view and have it posted correctly?
currently in the form when I hit submit I am creating an empty job object. The values are not getting there?
I think the devise authentication on the company model complicated a lot of things. I did it in another time but without authentication.
if I change the controller to this
def new
#company = Company.new
end
def create
#the actual create process where the params from the forms got sent here
#company = Company.new(params[:company])
end
If I am signed in as a company then I am getting 'you are already signed in' if I am not signed in I am redirected to the devise registration path .
Don't you just need build() instead of new():
def new
#company = current_company
#company.jobs.build()
end
def create
#the actual create process where the params from the forms got sent here
#job = current_company.jobs.build(params[:company][:job_attributes])
if #job.save
# redirect somewhere
else
render :new
end
end