I am building a form to work with a non activerecord model. I have two problems..
When I point to keyword/id/edit my form's submit button says 'create keyword', and pressing that submit button takes me to the create method on my keyword controller. It should be taking me to the update action.
I would also like to send an attribute called 'id' to my update action. I'm not sure how to do this. Like I said this isn't an activerecord model.
/views/keywords/_form.html.erb
<%= form_for(#keyword) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :keyword %><br />
<%= f.text_field :keyword %>
</div>
<div class="field">
<%= f.label :message1 %><br />
<%= f.text_area :message1 %>
</div>
<div class="field">
<%= f.label :message2 %><br />
<%= f.text_area :message2 %>
</div>
<div class="field">
<%= f.label :start_time %><br />
<%= f.text_area :start_time %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
/controller/keywords_controller.rb >> edit action
def edit
result = Keyword.find(params[:id])
result = result.to_array(:get_response, :return, :data, :item)
result = result.first
#keyword = Keyword.new
#keyword.id = result[:item][0][:value]
#keyword.name = result[:item][1][:value]
#keyword.keyword = result[:item][2][:value]
#keyword.message1 = result[:item][3][:value]
if(result[:item][4][:value] != {:"#xsi:type"=>"xsd:string"})
#keyword.message2 = result[:item][4][:value]
end
#keyword.start_time = result[:item][5][:value]
end
/models/keyword.rb
class Keyword
extend ActiveModel::Naming
include ActiveModel::Conversion
def persisted?
false
end
attr_accessor :id, :name, :keyword, :message1, :message2, :start_time
def self.get_keywords(cid)
#get data from webservice
end
end
config/routes.rb
SchoolBeacon::Application.routes.draw do
devise_for :users
devise_for :admins
resources :keywords
end
Change your #keyword = Keyword.new line in your edit action to #keyword = Keyword.find(params[:id]) or however you find the keyword. If you are using normal RESTful rails routes, that should do it.
Actually, you can just do form_for(#keyword, :url => keyword_path(#result) and change your result to an ivar(result becomes #result)
Related
I have a problem in my form, i want to create an entry in my "members" table, each member are connected to a "year" but I keep getting mismatches on the selection of the year.
This is my form:
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year, options_for_select(#years.all.map{|y| [y.year,y.id]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
And here are the models:
class Member < ApplicationRecord
belongs_to :year
mount_uploader :image, ImageUploader
end
class Year < ApplicationRecord
has_many :members, dependent: :destroy
end
When I try to submit I get the following error:
Year(#70050157849460) expected, got "1" which is an instance of String(#9412380)
Where did I go wrong?
EDIT:
Here is the code for the controller
class MembersController < ApplicationController
def home
#members = Member.all
end
def new
#member = Member.new
#years = Year.all
end
def create
#member = Member.new(member_params)
if #member.save
flash[:success] = "Member Created"
redirect_to root_path
else
render 'form'
end
end
private
def member_params
params.require(:member).permit(:name,:nick,:position,:image,:year)
end
end
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year_id, options_for_select(#years.all.map{|y| [y.year,y.id]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
or
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year, options_for_select(#years.all.map{|y| [y.year,y]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
This second I did not check but first will work you need to say year_id because when you did map on collection you set id as parameter that is being passed
but on form select you basically told form to expect active record object.
I have looked at all the posts about this fairly common problem on stackoverflow and elsewhere but I have not yet been able to find an answer. Essentially my nested form is not building, and is therefore not visible when I show the page.
Here is the relevant part of my user controller, users_controller.rb:
def new
#user = User.new
#user.build_user_account
end
Here is the relevant section from my user.rb file:
class User < ActiveRecord::Base
has_one :user_account, :class_name => "UserAccount"
accepts_nested_attributes_for :user_account
And my user_account.rb file:
class UserAccount < ActiveRecord::Base
belongs_to :user
end
Here is my _form.html.erb file:
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br>
<%= f.text_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br>
<%= f.text_field :password_confirmation %>
</div>
<% f.fields_for :user_account, #user.user_account do |user_account| %>
<div class="field">
<%= user_account.label :email %>
<%= user_account.text_field :email %>
</div>
<div class="field">
<%= user_account.label :password %>
<%= user_account.text_field :password %>
</div>
<div class="field">
<%= user_account.label :password_confirmation %>
<%= user_account.text_field :password_confirmation %>
</div>
<% end %>
the first three show up as expected, but the three form fields for user_account do not show up. I've tried everything that I could find online, but I still haven't been able to work out what the problem is - help would be appreciated!
I think you have just missed the = sign in the f.fields_for line. Try like this:
<%= f.fields_for :user_account, #user.user_account do |user_account| %>
The #user.user_account is not necessary either but does not harm.
When I enter something into a number_field and post the form to the controller, Rails can't save because i have a numericality validation:
validates :rating, numericality: { greater_than: 0, less_than: 6 }
I debugged the controller by this piece of code:
raise "It exploded into pieces!" unless #comment.save
The exception I used for debugging said that my :rating was a string instead of an integer. Before this, i rendered the json errors for #comment and that said that :rating was not a number.
These are very useful to spot the problem, but I can't find any solutions to fix the problem. I checked the database schema and it says that :rating should be an integer, as in:
t.integer "rating"
I don't know what to do at this point. Can somebody help me? Thank you in advance.
P.S. I use number_field.
P.P.S.
In my controller:
def ccreate
#comment = Comment.new(params.permit(:rating, :body, :name, :game_id))
raise "It exploded into pieces!" unless #comment.save
end
In my view:
<% if #comments.count < 10 %>
<%= form_for(comment_path) do |f| %>
<div class="field">
<%= f.label :rating %><br>
<%= f.number_field :rating %>
</div>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
It's a strong params thing. Permit :comments, then the attributes
params.require(:comments).permit(:rating, :body, :name, :game_id)
and, use form_for #comment, not comment_path
I think you need to setup the form properly, I think the validation will work fine if the form posts as it should:
comments_controller.rb
def new
#comment = Comment.new
end
def create
#comment = Comment.new(comment_params)
raise "It exploded into pieces!" unless #comment.save
end
private
def comment_params
params.require(:comment).permit(:rating, :body, :name, :game_id)
end
There we are changing the strong params to require the new comment key in params (which will be the result of the second change to the view below). I also moved this into a private function to clean this up.
So then in your view:
<% if #comments.count < 10 %>
<%= form_for(#comment) do |f| %>
<div class="field">
<%= f.label :rating %><br>
<%= f.number_field :rating %>
</div>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
This uses the form_for tag with the model instance which should, I think, solve this issue.
try this in the comment_controller.rb
#rating = params[:comment][:rating].to_i
to make every input of the ratings to be converted as integer
I can't find what I did wrong here, is there something I'm missing?
My new action/view here:
<h1>Submit a new experiment here!</h1>
<%= render "form" %>
My _form.html.erb form partial
<h1>THis is a form</h1>
<%= form_for(#experiment) do |f| %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :plan %><br />
<%= f.text_field :plan %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My experiments controller:
class ExperimentController < ApplicationController
def index
end
def new
#experiment = Experiment.new
end
end
And my routes:
devise_for :users
resources :home
resources :experiment
root to: "home#index"
I am visiting the following url:
http://localhost:3000/experiment/new
In you want to follow rails convention then:
Rename your controller from ExperimentController to ExperimentsController, i.e plural Experiments.
Rename your controller file name app/controllers/experiment_controller.rb to app/controllers/experiments_controller.rb, i.e. plural experiments_controller.rb.
Update your routes by modifying resources :experiment to resources :experiments.
If not, update your form_for call as:
<%= form_for(#experiment, url: url_for(controller: 'experiment', action: 'create')) do |f| %>
...
<% end %>
rarils 4.0.0
I'm trying to post a comments but I have an error:
ActiveModel::ForbiddenAttributesError in CommentsController#create
ActiveModel::ForbiddenAttributesError
def create
#comment = #article.comments.new(params[:comment]) #error point highlight this line
Parameters
{"utf8"=>"✓",
"authenticity_token"=>"zSq3KpEbucFQLa6XStEJ/I0+CpKPLFYcU/WGIdneeMg=",
"comment"=>{"name"=>"g12345",
"email"=>"g12345#12345.com",
"body"=>"hello hello"},
"commit"=>"Add",
"article_id"=>"5"}
my comments/new.html.erb
<%= form_for([#article, #article.comments.new], remote: true) do |f| %>
<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit 'Add' %>
</div>
<% end %>
Rails 4 uses strong parameters by default. Do you have something like:
params.require(:some_param).permit(...)
or
params.permit(:list, :of, :allowed, :params)
in your CommentsController?
It would look something like this:
class CommentsController < ApplicationController
def create
#comment = #article.comments.new(comment_params) #error point highlight this line
end
private
def comment_params
params.require(:comment).permit(:name, :email, :body)
end
end