So, I'm running into a fairly simple problem, where I cannot enter some simple form values into my SQLite DB (Rails).
Interestingly, the code doesn't fail - I submit the form, and am redirected successfully to the correct URL - and a record IS inserted into the DB, but the columns "name, type and user_id" are not filled with anything. To clarify, the columns are blank, for that new record.
If I comment out the code in the "create" and simply spit out the params (render plain: params[:plan].inspect) I do see all the correct parameters filled out, so I have a feeling there must be something wrong in the line:
#plan = Plan.new(params[:plan])
I'm really stuck here, any guidance would be much appreciated!
The create form
<h1> Create a new plan </h1>
<%= form_for :plan, url: plans_path do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :type %><br>
<%= f.text_field :type %>
</p>
<%= f.hidden_field :user_id, :value => current_user.id %>
<p>
<%= f.submit %>
</p>
<% end %>
plans_controller.rb
class PlansController < ApplicationController
def index
#plans = Plan.all
end
def show
#plan = Plan.find(params[:id])
end
def new
#plan = Plan.new
end
def create
#render plain: params[:plan].inspect
params.permit!
#plan = Plan.new(params[:plan])
if #plan.save
redirect_to #plan
else
redirect_to dashboard_path, :notice => "Plan NOT Created!"
end
end
end
The Model
class Plan < ActiveRecord::Base
end
Edit the plans_controller.rb:-
def create
#render plain: params[:plan].inspect
#plan = Plan.new(plan_params)
if #plan.save
redirect_to #plan
else
redirect_to dashboard_path, :notice => "Plan NOT Created!"
end
end
private
def plan_params
params.require(:plan).permit(:name,:type,:user_id)
end
Change the field name type as :-
rails g migration rename_fields_in_plans
class RenameFieldsInPlans < ActiveRecord::Migration
def change
rename_column :plans, :type, :plan_type
end
end
Then run the command:-
rake db:migrate
Related
I'm trying to make a form object work for new User and edit User actions. The form object creates or updates a User through it's save method, but the form object itself is never persisted so Rails always tries to make a POST even though I'm specifying different routes in the simple_form_for url.
Is there any way to make it work for both actions?
UsersController.rb:
class Admin::UsersController < AdminController
def new
#user_form = UserForm.new(account_id: current_account.id)
end
def create
#user_form = UserForm.new(user_form_params)
if #user = #user_form.save
flash[:success] = "User created"
redirect_to admin_user_path(#user)
else
render "new"
end
end
def edit
#user_form = UserForm.new(existing_user: #user, account_id: current_account.id)
end
def update
if #user.update(user_form_params)
flash[:success] = "User saved"
redirect_to admin_user_path(#user)
else
render "edit"
end
end
end
UserForm.rb
class UserForm
include ActiveModel::Model
include ActiveModel::Validations::Callbacks
attr_accessor :fname, :lname, :email
def initialize(params = {})
super(params)
#account = Account.find(account_id)
#user = existing_user || user
end
def user
#user ||= User.new do |user|
user.fname = fname
user.lname = lname
user.email = email
end
end
def save
#user.save
#user
end
end
_form.html.erb
<%= simple_form_for #user_form, url: (#user.present? ? admin_user_path(#user) : admin_users_path) do |f| %>
<%= f.input :fname %>
<%= f.input :lname %>
<%= f.input :email %>
<%= f.submit %>
end
The new/create flow works fine, but editing an existing User returns
No route matches [POST] "/admin/users/69"
class UserForm
# ...
def to_model
#user
end
end
<%= simple_form_for #user_form, url: [:admin, #user_form] do |f| %>
<%= f.input :fname %>
<%= f.input :lname %>
<%= f.input :email %>
<%= f.submit %>
end
When you pass a record to form_for (which SimpleForm wraps), form_with or link_to the polymorphic routing helpers call to_model.model_name.route_key or singular_route_key depending on if the model is persisted?. Passing [:admin, #user_form] will cause the polymorphic route helpers to use admin_users_path instead of just users_path.
On normal models to_model just returns self.
https://api.rubyonrails.org/v6.1.4/classes/ActionDispatch/Routing/PolymorphicRoutes.html
I try to create a project page with a form to send invitation to other users. The Owner (who have created the project) can invite other users to participate to the project.
Right now, Here is the code :
views/projects/show.html.erb
<div class="container">
<h3> <%= #project.title %> </h3>
<h6> Créé par <%= link_to #project.owner.username, user_path(#project.owner) %> </h6>
<hr>
<h3> Inviter des utilisateurs au projet </h3>
<!-- form for search users -->
<%= form_tag new_invite_path, method: :post, :class => 'form-inline' do %>
<div class="form-group">
<%= text_field_tag :search, params[:search], size: 30, class: 'form-control' %>
</div>
<%= submit_tag 'Ajouter au projet', class: 'btn btn-success' %>
<% end %>
<!-- end form for search users -->
<!-- display users results -->
<% #users.each do |user| %>
<p> <%= user.username %> | <%= user.email %> </p>
<% end %>
<!-- end display results -->
</div>
controllers/projects_controller.rb
class ProjectsController < ApplicationController
def show
#project = Project.find(params[:id])
#users = User.search(params[:search])
end
def new
#project = Project.new
end
def create
#project = Project.new(project_params)
#project.owner = current_user
#project.members = []
if #project.save
puts #project
redirect_to user_path(current_user)
else
puts 'something went wrong'
puts #project.errors.full_messages
render 'new'
end
end
private
def project_params
params.require(:project).permit(:title, :description, :client, :deadline, :owner, :members)
end
end
On the project page, I have an Ajax form to find all the users, with their username and email.
Now, when I submit this form, I want to create an invitation (a notification, but I haven't begin the notification system). So, I have created this model :
class Invite
include Mongoid::Document
field :email
belongs_to :project
belongs_to :sender_id, :class_name => 'User'
belongs_to :recipient_id, :class_name => 'User'
end
And a controller :
class InvitesController < ApplicationController
def new
#invite = Invite.new(email: params[:search], sender_id: current_user.id)
byebug
#invite.save
end
def create
#invite = Invite.new(params[:search])
if #invite.save
flash[:success] = 'the invitation is send'
redirect_to user_path(current_user)
else
render 'projects/show'
end
end
end
So as you can see, I want to save the invite in my db (MongoDB -> Mongoid), but when I submit the form (on the project/show page), I have this error :
No route matches [POST] "/invites/new"
It's normal, but I want to know :
how to insert data in my database without rendering a view ?
how to have access to user ID with the email adresse ? (which is in the DB)
Thank you !
NB: don't hesitate to ask if you need more code to answer
1) You can insert the data on the database without rendering anything with this line on the controller render :nothing => true, :status => 200
so your create method will be like this
def create
#invite = Invite.new(params[:search])
if #invite.save
flash[:success] = 'the invitation is send'
render :nothing => true, :status => 200
else
render 'projects/show'
end
end
and this is wrong No route matches [POST] "/invites/new" when you try to create something, you will need to go to create, not the new action, just change the url on the form, because you are pointing to the wrong action.
2) If you have an User model and want to load an user by email, you can do something like this
User.find_by_email("the email of the user")
this is your model is User and the column where the email is, is named "email"
When i create a new category_item_key in the db the slug isn't being added to the slug column.
here is my coding
migration file
class AddSlugToCategoryItemKeys < ActiveRecord::Migration
def change
add_column :category_item_keys, :slug, :string
add_index :category_item_keys, :slug, unique: true
end
end
category_item_key controller
def new
#guide = Guide.friendly.find(params[:guide_id])
#category = Category.friendly.find(params[:category_id])
#key = Category.friendly.find(params[:category_id]).category_item_keys.new
end
def create
#guide = Guide.friendly.find(params[:guide_id])
#category = Category.friendly.find(params[:category_id])
#key = Category.friendly.find(params[:category_id]).category_item_keys.new(key_params)
if #key.save
flash[:info] = "Key added succesfully!"
redirect_to #guide
else
render 'new'
end
end
private
def key_params
params.require(:category_item_key).permit(:name, :slug)
end
new.html.erb
<%= form_for([#category, #key], url: category_item_keys_create_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, "Key name" %>
<%= f.text_field :name %>
<%= f.submit "Next" %>
<% end %>
When creating a new guide or category friendly id works just fine, with the slug being added. But for category_item_key something is going wrong.
Maybe i'm missing something. But i cant find the problem.
def new
#guide = Guide.find params[:guide_id]
#category = Category.find params[:category_id]
#key = #category.category_item_keys.new
end
def create
#guide = Guide.find params[:guide_id]
#category = Category.find params[:category_id]
#key = #category.category_item_keys.new key_params
if #key.save
redirect_to #guide, notice: "Key added succesfully!"
else
render 'new'
end
end
private
def key_params
params.require(:category_item_key).permit(:name)
end
--
<%= form_for [#guide, #category, #key] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, "Key name" %>
<%= f.text_field :name %>
<%= f.submit "Next" %>
<% end %>
If you've ran your migration (have the columns in the db), the above should work. If it doesn't, you need to post the sent params, and the response you're receiving from the server.
--
As an aside, you'll also want to look at how many levels you're nesting your routes...
Resources should never be nested more than 1 level deep.
Because you've got guides and then categories before you get to keys, you'll probably want to remove the category or guide param:
# config/routes.rb
resources :categories do
resources :keys
end
I think the issue you have is likely that you're only passing [#category, #key] to your form_for. Instead, you'll need to include the #guide as well.
Forgot to add extend FriendlyId
friendly_id :name, use: :slugged into my model. once it was added my problem was solved
Just for your notice
You can rewrite to_params method in your model to generate your uniq slug
to_params
#for instance
your_column + your_column
end
followed a tutorial to help me create instances within a controller. In other words transactions are created on the envelope controller. Like comments on a blog post.
Everything is working perfectly, but I don't know how to edit a transaction now or destroy one. All I need is to find how to edit an existing thing. Let me show you what I have so far:
in views/envelopes/edit (the form code was copied from where you can create new transactions)
<% #envelope.transactions.each do |transaction|%>
<%= form_for [#envelope, #envelope.transactions.build] do |f| %> <!--??? NEED EDIT INSTEAD OF BUILD ???-->
<%= f.text_field :name, "value" => transaction.name %>
<%= f.text_field :cash, "value" => transaction.cash %>
<%= f.submit "Submit" %>
<% end %>
<%= link_to "Remove", root_path %> <!--??? WANT TO REMOVE TRANSACTION ???-->
<% end %>
in routes.rb
resources :envelopes do
resources :transactions
end
in transaction controller
class TransactionsController < ApplicationController
def create
#envelope = Envelope.find(params[:envelope_id])
#transaction = #envelope.transactions.build(transaction_params)#(params[:transaction])
#transaction.save
#envelope.update_attributes :cash => #envelope.cash - #transaction.cash
redirect_to edit_envelope_path(#envelope)
end
def destroy
# ???
end
def update
# ???
end
def transaction_params
params.require(:transaction).permit(:cash, :name, :envelope_id)
end
end
def update
#transaction = #envelope.transactions.find(params[:id])
if #transaction.update(transaction_params)
redirect to #envelope, notice: 'Transaction was successfully updated'
else
redirect_to #envelope, notice: 'Transaction was not updated'
end
end
def destroy
#transaction.destroy
redirect_to #envelope, notice: 'Text here'
end
My app has a user model and a post model, where user has_many posts and posts belong_to users. Posts are displayed on a user's profile page. I'd like for any user to be able to post on his own, or any other user's profile page. However, the problem I'm having is that while I know who is posting (current_user), I don't know whose profile current_user is on. I need to know this in order to assign the new post to that user's posts. How do I extract user id information from the profile currently being viewed, so I know where to assign the new post?
My micropost controller looks like:
class MicropostsController < ApplicationController
before_filter :authenticate_user!
def create
#user_of_page = User.find_by_name(params[:id])
#micropost = #user_of_page.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to :back
else
redirect_to about_path
end
end
def destroy
end
end
But I'm getting a NoMethodError: undefined method `microposts' for nil:NilClass. I assume this is because I'm making some mistake with the creation of the user_of_page variable, but I don't know what that is!
SOLUTION
Thanks Sam. I took your advice and ended up doing it like this:
I added a column to my Micropost table called belongs_to_id.
I then passed the id of the user whose profile is being shown from the user show view to the micropost controller using a hidden field in the micropost form, like so:
<%= form_for #micropost do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :content, "Why that mood?" %>
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.hidden_field :author, :value => current_user.name %>
<%= f.hidden_field :belongs_to_id, :value => #user.id %>
<%= f.hidden_field :agree, :value => "0" %>
<%= f.hidden_field :disagree, :value => "0" %>
<%= f.hidden_field :amused, :value => "0" %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
I then used this id value to search for the user to assign the post to, in the micropost controller, like so:
class MicropostsController < ApplicationController
before_filter :authenticate_user!
def create
#user_of_page = User.find(params[:micropost][:belongs_to_id])
#micropost = #user_of_page.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to :back
else
redirect_to about_path
end
end
def destroy
end
end
Magic! Thanks again, you helped me to see it in the right way.
I would do it like this:
class profiles_controller < AC
...
def show
#profile = User.find(params[:id]).profile || current_user.profile
#post = Post.new
end
..
end
/profiles/show.html.erb
...
Name: <%= #profile.full_name %>
...
<%= form_for #post do |f| %>
<%= hidden_field_tag #profile.user %>
...
<% end %>
class microposts_controller < AC
def create
profile_user = User.find(params[:user_id]) # Owner of the profile current_user is on
..
end
end
Not tested. Hope this helps.