I am starting to develop in ROR. The user history that I am doing now is a Contact Page. The codes for the MVC are listed below:
app/controller/contatos_controller.rb
class ContatosController < ApplicationController
def new
#contato = Contato.new
end
def create
#contato = Contato.new(secure_params)
if #contato.valid?
flash[:notice] = "Mensagem enviada de #{#contato.name}."
redirect_to root_path
else
render :new
end
end
private
def secure_params
params.require(:contato).permit(:name, :subject, :email, :content)
end
end
app/models/Contato.rb
class Contato
include ActiveModel::Model
attr_accessor :name, :string
attr_accessor :subject, :string
attr_accessor :email, :string
attr_accessor :content, :string
validates_presence_of :name
validates_presence_of :subject
validates_presence_of :email
validates_presence_of :content
validates_format_of :email,
with: /\A[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i
validates_length_of :content, :maximum => 500
end
app/views/contatos/new.html.erb
<h3>Contato</h3>
<div class="form">
<%= simple_form_for #contato do |form| %>
<%= form.error_notification %>
<%= form.input :name, autofocus: true %>
<%= form.input :subject %>
<%= form.input :email %>
<%= form.input :content, as: :text %>
<%= form.button :submit, 'Submit', class: 'submit' %>
<% end %>
</div>
config/routes.rb
Rails.application.routes.draw do
resources :contatos, only: [:new, :create]
root 'static_pages#home'
end
When I try to access http://localhost:3000/contatos/new, the following error is displayed:
NameError in ContatosController#new
uninitialized constant ContatosController::Contato
app/controllers/contatos_controller.rb:4:in `new'
What I found about this error is that it is related to typos, but this does not seem to be my case. It's probably a silly mistake, but I could not find it. Can anybody help me?
As #Robert already noted in his comment, you need to name your Contato model file in lowercase.
However, since Ruby is looking for your model in the controller itself (ContatosController::Contato), you can solve this problem by putting double colon before the model name like this:
#contato = ::Contato.new
This will force Ruby interpreter to look for Contato model in the "root/top" namescope.
Related
I have a recipient and category model. It's a simple association of 1 category has many recipients. When I try to update the recipient form and assign a category, it won't save to the record. If I use the console and update a record manually, e.g. Recipient.update(9, category_id: 13), I see the correct category assigned to the recipient but when I try to edit/update the record, it won't save to the new chosen category.
Here is my recipient model
class Recipient < ActiveRecord::Base
belongs_to :category
accepts_nested_attributes_for :category
end
Here is my category model
class Category < ActiveRecord::Base
has_many :recipients
validates :category, presence: true
default_scope { order('category')}
end
here is the recipient controller
class RecipientsController < ApplicationController
def index
#recipients = Recipient.order(:recipient_name).page(params[:page])
end
def new
#recipient = Recipient.new
end
def show
#recipient = Recipient.find(params[:id])
end
def create
#recipient = Recipient.new(recipient_params)
if #recipient.save
redirect_to recipients_path
else
render :new
end
end
def edit
#recipient = Recipient.find(params[:id])
end
def update
#recipient = Recipient.find(params[:id])
recipient_params = params.require(:recipient).permit(:recipient_name, :alternate_name, :description, :city, :state, :country, category_attributes: [:category, :id])
#recipient.update_attributes(recipient_params)
redirect_to recipient_path(id: #recipient.id)
end
def destroy
#recipient = Recipient.find(params[:id])
#recipient.destroy
redirect_to recipients_path
end
private
def recipient_params
params.require(:recipient).permit(:recipient_name, :alternate_name, :description, :city, :state, :country, product_attributes: [:product_name, recipient_products: [:recipient_id, :product_id]], channel_attributes: [:channel_name, recipient_channels: [:recipient_id, :channel_id]], category_attributes: [:id, :category])
end
end
here is the edit view
<div class="row">
<div class="col-sm-6">
<h2>Edit <%= #recipient.recipient_name %></h2>
<%= simple_form_for #recipient do |form| %>
<%= form.error_notification %>
<%= form.input :recipient_name, placeholder: 'Recipient', label: 'Recipient Name' %>
<%= form.input :alternate_name, placeholder: 'Alternate Name' %>
<%= form.association :category, label_method: :category, value_method: :id %>
<%= form.input :description, placeholder: 'Description'%>
<%= form.input :city, placeholder: 'City'%>
<%= form.input :state, placeholder: 'State' %>
<%= form.input :country, as: :country, priority: ['US', 'CA'] %>
<%= form.button :submit, 'Update Recipient', {:class=>"btn btn-secondary"} %>
<%= link_to "Cancel", :back, {:class=>"btn btn-default"} %>
<% end %>
</div>
</div>
and here is my routes.rb file
Rails.application.routes.draw do
root to: 'home#index'
resources :media_points
resources :products
resources :channels
resources :recipients
resources :media_point_products
resources :distributions
resources :categories do
resources :recipients
end
get '/listing' => "listing#index"
devise_for :admins
devise_for :users
resources :users
end
I wrote it as an answer since the format is a pain in comments:
Change your recipient_params private method from:
category_attributes: [:category, :id]
to
category_id: param_that_has_category_id_here
Also, you have two routes for recipients and it is going to utilize the first matching route which is not the nested recipients in categories route you have further down. If the first change in your private method didn't fix it I would specify the nested situation in simpleform doing as follows since you are probably looking to use the nested route:
simple_form_for [#category, #recipient], url: 'nested_route_path_here' do |f|
Just add #category = Category.new to your new action in the recipients controller and then in your create action you'll have the category param sent via params[:category_id]
Hello Stackoverflow programmer's,
I'm currently running a small side-project next to my school's project but i'm quite stuck for a while now.
Here's my problem: I have a user with some standerd attributes and that user has_one :spec. A spec is sort of an extended version for a profile.
Now this spec has as i mentioned some extra attributes, but i can't seem to assign it correctly to the current user. The strange thing is i am able to make a spec in the console.
Here's my Spec_controller:
class SpecController < ApplicationController
def index
# redirect_to :controller => "user", :action => "index"
# #user.spec = #spec.new
end
def update
#user = User.find(current_user.id)
#spec.user_id = current_user.id
#spec = current_user.spec(spec_params)
#spec = Spec.find(params[:id])
if #spec.update(params.require(:spec).permit(:first_name, :last_name, :gender, :birthdate, :occupation, :city, :state))
flash[:notice] = "Changes saved."
redirect_to users_path
else
flash[:notice] = "er ging iets mis!"
render 'edit'
end
end
def edit
#user = User.find(session[:user_id])
#spec = Spec.new
end
def new
#user = User.find(session[:user_id])
#spec = Spec.new
end
private
def spec_params
params.require(:spec).permit(:first_name, :last_name, :gender, :birthdate, :occupation, :city, :state)
end
def user_params
params.require(:user).permit(:screen_name, :email, :password)
end
end
The Spec model:
class Spec < ActiveRecord::Base
belongs_to :user
ALL_FIELDS = %w(first_name last_name occupation gender birthdate city state zip_code)
STRING_FIELDS = %w(first_name last_name occupation city state)
VALID_GENDERS = ["Male", "Female"]
START_YEAR = 1900
VALID_DATES = DateTime.new(START_YEAR)..DateTime.now
validates_inclusion_of :gender, in: VALID_GENDERS, allow_nill: false, message: "Must be male or female"
validates_inclusion_of :birthdate, in: VALID_DATES, allow_nill: false, message: "Is invalid"
end
The user model:
class User < ActiveRecord::Base
has_one :spec
validates_presence_of :email, :screen_name
validates_uniqueness_of :email, :screen_name
has_secure_password
extend FriendlyId
friendly_id :screen_name, use: :slugged
end
And the edit view in case if it's needed:
<%= form_for :spec do |form| %>
<fieldset>
<legend><%= #title %></legend>
<%= text_field_tag form, "first_name" %>
<%= text_field_tag form, "last_name" %>
<div class="form_row">
<label for="gender">Gender:</label><br>
<%= radio_button :spec, :gender, "Male" %> Male
<%= radio_button :spec, :gender, "Female" %> Female
</div>
<div class="form_row">
<label for="birthdate">Birthdate:</label><br>
<%= date_select :spec, :birthdate, :start_year => Spec::START_YEAR, :end_year => Time.now.year, :include_blank => true, :order => [:month, :day, :year] %>
</div>
<%= text_field_tag form, "occupation" %>
<%= text_field_tag form, "city" %>
<%= text_field_tag form, "state" %>
</br>
<%= submit_tag "Update", :class => "submit", :controller => :spec, :action => :update %>
</fieldset>
<% end %>
Routes file:
Rails.application.routes.draw do
resources 'spec'
#post ':controller(/:spec(/:id(.:edit)))'
get 'spec/index'
get 'spec/edit'
get 'profile/index'
get 'profile/show'
get 'profile/:screen_name', controller: 'profile', action: 'show'
resources :users, only: [:index, :new, :create, :login, :destroy, :edit, :show, :update]
controller :sessions do
get :login, to: 'sessions#new'
delete :logout, to: 'sessions#destroy'
post :authenticate, to: 'sessions#create'
end
root 'site#index'
get 'site/index'
get 'site/about'
get 'site/help'
end
I hope my code is readable, still trying to figure out alot of stuff inside of rails (first programming language).
Thanks!
Finnaly got it to work! Ive made a new def in Spec controller instead of update i made a create function. Kinda strange in the first place why i made it a update function when you want to create a complete new Spec!
Thanks alot for your help :) much appreciated.
try
#spec = current_user.spec
if #spec.update(spec_params)
...
Update:
I think the link to update spec will be something like this /specs/1/edit, getting and updating spec should be
#spec = Spec.find(params[:id])
if #spec.update(spec_params)
...
I'm having an inordinate amount of trouble using a nested model with fields_for in a form. Specifically, not all of the nested fields save. A User has many Experiences, but when I submit the form, an Experience with the correct user_id but NO CONTENT is inserted into the database.
Looking at the logs, I also get an error:
unpermitted parameters: experience.
Rails 4 nested attributes not saving doesn't help, unfortunately.
Here's the code:
SCHEMA
create_table "experiences", force: true do |t|
t.string "content", null: false, default: ""
t.integer "user_id"
end
MODEL
#user.rb
class User < ActiveRecord::Base
has_many :experiences
accepts_nested_attributes_for :experiences
#experience.rb
class Experience < ActiveRecord::Base
belongs_to :user
end
CONTROLLER
class UsersController < ApplicationController
def new
#user = User.new
#user.experiences.build
end
def update
#user = current_user
#user.experiences.build
#user.update!(user_params)
redirect_to root_path
end
def user_params
params.require(:user).permit(:username, :email, :password,
:password_confirmation, :title, :blurb, :city, :state,
:style_list, :experience_attributes => [:id, :content])
end
VIEW
<%= form_for #user do |f| %>
<!-- (Omitted) user fields -->
<%= f.fields_for :experience do |experience_fields| %>
<%= experience_fields.text_field :content, placeholder: 'Content' %>
<% end %>
<%= f.submit 'Edit profile' %>
<% end %>
Any help would be greatly appreciated!
Here's your problem:
#user.experiences.build # -> note "experience**s**"
This means when you use fields_for, you have to reference :experiences (you're currently referencing the singular):
<%= f.fields_for :experiences do |experience_fields| %>
<%= experience_fields.text_field :content, placeholder: 'Content' %>
<% end %>
This also goes for your strong_params:
params.require(:user).permit(experiences_attributes: [:id, :content])
I'm relatively new to Rails (using Rails 4), and am having a problem with validation for my user model. Even when the form is fully filled in with both the passwords, when I submit the code two errors print out:
{:password=>["can't be blank"], :password_confirmation=>["doesn't match Password"]}
I would like the user to be saved into the database, but these validation errors are preventing that from happening. What I would like to know is what I need to change in order to get rid of these errors.
I am printing out the params object and it looks like this (the authenticity token is omitted here):
params: {"utf8"=>"✓","authenticity_token"=>"[omitted]",
"user"=>{"username"=>"testuser1", "password"=>"test",
"password_confirmation"=>"test", "email_attributes"=>{"email"=>"d#d.com"},
"first_name"=>"test", "last_name"=>"user", "gender"=>"male", "city"=>"la",
"state"=>"ca", "country"=>"usa", "dob"=>"1980-11-20"},
"commit"=>"Create Account", "action"=>"create", "controller"=>"users"}
So it appears that the password and password_confirmation attributes are getting passed correctly. I am wondering if this may have to do with the virtual attribute password I have defined in the user model, but if that is the case I am still not quite sure how to solve this problem. Any help would be greatly appreciated. Let me know if I need to elaborate further.
Here is relevant code for reference:
Controller:
class UsersController < ApplicationController
def new
#user = User.new
#user.build_email
end
def create
if #user = User.create(user_params)
logger.debug "#{#user.errors.messages}"
logger.debug "params: #{params}"
redirect_to :action => "new"
else
logger.debug "#{#user.errors.messages}"
logger.flush
redirect_to :action => "new"
end
end
private
def user_params
params.require(:user).permit(:username, :password, :password_confirmation, :first_name, :last_name, :gender, :dob, :city, :state, :country, :admin_level, email_attributes: [:email])
end
end
Model:
class User < ActiveRecord::Base
has_one :email
validates_presence_of :username, :email, :password
validates_confirmation_of :password, :on => :create
accepts_nested_attributes_for :email
def password_valid?(candidatePass)
candidatePassAndSalt = "#{candidatePass}#{self.salt}"
candidatePasswordDigest = Digest::SHA1.hexdigest(candidatePassAndSalt)
if (candidatePasswordDigest == self.password_digest)
return true
else
return false
end
end
def password
end
def password=(text)
self.salt = Random.new.rand
passAndSalt = "#{text}#{self.salt}"
self.password_digest = Digest::SHA1.hexdigest(passAndSalt)
end
end
View:
<%= form_for #user, url: {action: "create"}, html: {class: "user-creation-form"} do |f| %>
<%= f.text_field :username %>username<br/>
<%= f.password_field :password %>pw<br/>
<%= f.password_field :password_confirmation %>pwcopy<br/>
<%= f.fields_for :email do |email_form| %>
<%= email_form.text_field :email %>email<br />
<% end %>
<%= f.text_field :first_name %>first<br/>
<%= f.text_field :last_name %>last<br/>
<%= f.radio_button :gender, "male" %>
<%= f.label :gender_male, "M" %>
<%= f.radio_button :gender, "female" %>
<%= f.label :gender_female, "F" %><br />
<%= f.text_field :city %>city<br/>
<%= f.text_field :state %>state<br/>
<%= f.text_field :country %>country<br/>
<%= f.date_field :dob %>dob<br/>
<%= f.submit "Create Account" %><br/>
<% end %>
The issue is your empty getter:
def password
end
It always return nil.
2 small additions to the previous answer, which should resolve your issue by the way.
1) If you're using Rails >3 (I assume you are by looking at your user_params method in the controller) you don't have to specify all those password fields and validations.
ActiveRecord automatically includes this ActiveModel method :
has_secure_password
More details at : http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password
2) If the uncrypted password/password_confirmation are shown in your log files your app is insecure. Add this to your config/application.rb :
config.filter_parameters = [:password, :password_confirmation]
This should not be needed if you are using has_secure_password in your User model.
So I have seen other articles here on stack about this and a lot of the time people are not doing #post = post.new. I read some where to use the plural...??
any ways I am getting this error on my discussion code:
Model
class Discussion < ActiveRecord::Base
has_many :comment
belongs_to :author
attr_accessible :author_id, :content, :title
validate :comment, :presence => true
validate :title, :presence => true
end
Discussion Controller
class DiscussionsController < ApplicationController
def index
#discussion = Discussion.new
#discussions = Discussion.all
end
def create
#discussion = Discussion.create(params[:discussion])
if #discussion.save
redirect_to tasks_path, :flash => {:success => 'Created a new discussion'}
else
redirect_to tasks_path, :flash => {:error => 'Failed to create a discussion'}
end
end
end
Discussion Form
<%= form_for #discussion do |f| %>
<p><%= f.label :title %>
<%= f.text_field :title %></p>
<p><%= f.label :content %>
<%= f.text_area :content %></p>
<% end %>
Discussion Routes
resources :discussions do
resources :comments
end
Now as far as I know I am doing this right, because I have a task form set up essentially the same way - but I have looked at my code for hours and have googled and tried other examples and now i see this:
undefined method `model_name' for NilClass:Class
Extracted source (around line #1):
1: <%= form_for #discussion do |f| %>
2:
3: <p><%= f.label :title %>
4: <%= f.text_field :title %></p>
Which should mean that I am missing something from my controller.....is it as asilly as a spelling mistake? >.>
Have you tried putting this in your discussion controller?
def new
#discussion = Discussion.new
end
I believe your problem is that you are trying to create a discussion on a task form but have only defined the discussion controller and not the task controller.
u have to add :method => :post to the form for creating the object else the form will get submitted with GET request.
<%= form_for #discussion , :method => :post do |f| %>
Is that the index view that has the form_for?
If not, then you should add a new action to the controller and do #discussion = Discussion.new there and not in your index action.
if ur model relationships are exactly as u have provided, then they are incorrect
class Discussion < ActiveRecord::Base
has_many :comment #has_many :comments
belongs_to :author
attr_accessible :author_id, :content, :title
validate :comment, :presence => true #valide :comments, :presence => true
validate :title, :presence => true
end