Use a hidden field will fix my issue... i got it..
Hi All,
I am new to rails, trying to do some practice.
The app i am writing is trying to create a new "Post" See the view and controller below.
But it doesn`t work as what i expected...
the parameters pass to function "save", there is no "post_at" field...
How can i fix it???
Thanks
INFO: Parameters: {"authenticity_token"=>"Xc9VuvRL6GsUTaKyyNQxp8ovylEYwOMC+7hMcqdKizg=", "post"=>{"title"=>"First post", "content"=>"Write something"}, "commit"=>"save"}
View new_post.erb
<div class="post">
<% form_for #new_post, :url => { :action => "save" } do |f| %>
<p><%= f.error_messages %></p>
<br/>
<table>
<tr>
<td>Title</td>
<td><%= f.text_field :title %></td>
</tr>
<tr>
<td>Post at</td>
<td><%= #new_post.post_at %></td>
</tr>
<tr>
<td>Message</td>
<td><%= f.text_area :content, :cols => 100, :rows => 10 %></td>
</tr>
</table>
<br/>
<%= f.submit 'save'%>
<% end %>
</div>
Post Controler
class PostController < ApplicationController
def index
#all_posts = Post.find(:all)
render :action => "post"
end
def new
#new_post = Post.new
#new_post.post_at = Time.now
render :action => "new_post"
end
def save
#new_post = params[:post]
Post.create(#new_post)
redirect_to "/post"
end
end
Data Model:
class Post
include DataMapper::Resource
storage_names[:default] = "Post"
property :id, Serial
timestamps :at
property :title, String, :required => true, :length => 500
property :content, Text, :required => true, :lazy => false
property :post_at, DateTime
end
First off, your development will be a lot easier if you follow the REST principles.
Your controller should instead of save implement the create and update methods.
def index
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.create(params[:post])
redirect_to #post
end
def show
#post = Post.get(params[:id])
end
def edit
#post = Post.get(params[:id])
end
def update
#post = Post.get(params[:id])
#post.update_attributes(params[:post])
redirect_to #post
end
def destroy
#post = Post.get(params[:id])
#post.destroy
redirect_to posts_path
end
This is a complete REST controller which has the views index.html.erb, new.html.erb, edit.html.erb, show.html.erb all in app/views/posts.
Sidenote: If you're new to Rails, it might be a good idea to learn how to use it with ActiveRecord before trying on DataMapper. That way you can use rails generate scaffold to get a full example of a way to do all this.
Your post_at value isn't a field, it's just displayed in the table. You want to do this:
<tr>
<td>Post at</td>
<td><%= f.datetime_select :post_at %></td>
</tr>
But in fact, there's more wrong with this code than that. For starters, Rails already has a field for this which will be set automatically called created_at. Next, your save action in your controller should be a create action to follow the Rails conventions.
I really think you should read the Getting Started guide which covers these basic fundamentals and then a book or two about Rails in more depth. These really teach you a lot.
Ryan is right about the cause of the problem.
If you need a readonly field then you could add a hidden field to make sure that the value is posted back:
<td><%= #new_post.post_at %><%= f.hidden_field :post_at %></td>
or you could replace it altogether with a readonly text_field:
<td><%= f.text_field :post_at, :readonly => true %></td>
Related
This is the error I'm getting:
No route matches [POST] "/specials/1"
I understand that it's not able to produce the post route, or it isn't available.
Here's my view/form code:
<%= form_for(:special, :url => {:action => 'update', :id => #special.id}) do |f| %>
<table class="table table-responsive table-striped table-condensed table-hover" summary="Special form fields">
<tr>
<th>Order</th>
<td><%= f.text_field :order, class: "form-control" %></td>
</tr>
<tr>
<th>Name</th>
<td><%= f.text_field :name, class: "form-control" %></td>
</tr>
<tr>
<th>Description</th>
<td><%= f.text_field :description, class: "form-control" %></td>
</tr>
<tr>
<th>Fine Print</th>
<td><%= f.text_field :fine_print, class: "form-control" %></td>
</tr>
<tr>
<th>Active</th>
<td><%= f.text_field :active, class: "form-control" %></td>
</tr>
</table>
<div class="form-buttons">
<%= submit_tag("Update Special") %>
</div>
<% end %>
Heres's my controller code:
class SpecialsController < ApplicationController
def index
#specials = Special.sorted
end
def show
#special = Special.find(params[:id])
end
def new
#special = Special.new
end
def create
#Instantiation of object using form parameters
#special = Special.new(special_params)
#Save the object
if #special.save
#If success, redirect to index action
redirect_to(:action => 'index')
else
# Redisplay the form so user can fix problems
render('new')
end
end
def edit
#special = Special.find(params[:id])
end
def update
#Find an existing object using form parameters
#special = Special.find(params[:id])
#Update the object
if #special.update_attributes(special_params)
#If succeeds, redirect to index action
redirect_to(:action => 'show', :id => #special.id)
else
# If update fails, redisplay the form so user can fix problems
render('edit')
end
end
def delete
end
private
def special_params
params.require(:special).permit(:name, :description, :fine_print, :active, :order)
end
end
I noticed that there is an update path:
PATCH /specials/:id(.:format) specials#update
I can't figure out why the post route isn't being applied. It's looking for the right #special instance, but it doesn't seem to have the route available. Any advice?
Usually when updating a record, we do a patch request to the route. Your form should look like this:
<%= form_for(#special) do |f| %>
Rails will determine the correct route is PATCH /specials/:id based on the fact that #special has been persisted to the database.
If you decide to use this same form as a partial in your new view, just make sure to add this to your controller:
def new
#special = Special.new
end
That way whether you are on the new route or the edit route, there will always be a #special object for form_for to infer whether to POST to /specials or PATCH /specials/:id
I am a noob on Ror. Been looking for my problem answers for 3 days now, I have been looking for the answers but can’t find one with my specific problem. ( I even found it hard to write the right title)
So I have been trying to build a nested form in RoR. I have a simple order form that enable users to specify the quantity they ordered in that form. The form will only store the value into the database if the quantity text field is not empty.
The Order form is simply look like this:
I am storing the quantity data into the join table between order and inventory which has many to many relationship through Inventory_orders table. now in the Inventory_orders table instead of only having orders_id and inventories_id , I also add the quantity column.
now I have been able to get the form working with the code below:
Controller:
def new
#order = Order.new
#customer = Customer.all
#inventories_list = Inventory.all
#inventory_order = #order.inventory_orders.build
end
def create
#order = Order.new(order_params)
#inventories_list = Inventory.all #controller can call any model
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
def order_params
params.require(:order).permit(:customer_id, :order_ids => [],:inventory_orders_attributes => [:id, :quantity, :inventory_id ])
end
View:
<%= form_for(#order) do |f| %>
<div id = “Main_Container">
*** Some Code ***
<table id = "inventory_table">
<tr>
<td class = "prodCodeTitle"><h3>Prod Code</h3></td>
<td class = "prodResult"><h3>Quantity</h3></td>
<td class = "prodResult"><h3>Size</h3></td>
<td class = "prodResult"><h3>Price</h3></td>
</tr>
//Here display all the inventories list
<% #inventories_list.each do |t| %>
<tr>
<td class ="prodResult"><%= link_to t.pName, inventory_path(t), :remote => true %></td>
<td class = “prodResult">
//nested form for the join table
<%= f.fields_for :inventory_orders do |qty| %>
<%= qty.hidden_field :inventory_id , value: t.id %>
<%= qty.number_field :quantity %>
<%end%>
</td>
<td class = "prodResult"><%= t.pMeter %></td>
<td class = "prodResult"><%= t.pSellPrice %></td>
</tr>
<% end %>
*** Some Code***
<% end %>
Model:
class Order < ActiveRecord::Base
belongs_to :customer
has_many :inventory_orders
has_many :inventories, through: :inventory_orders
validates :customer_id, :presence => true
accepts_nested_attributes_for :inventory_orders, :reject_if => lambda { |a| a[:quantity].blank?}
end
class InventoryOrder < ActiveRecord::Base
belongs_to :inventory
belongs_to :order
validates :quantity, :presence => true
end
Now when creating new Orders form , the application works and store the data that I want in the inventory_orders table.
The problem occurs when I try to edit the form. When trying to click on edit button I get this output in my View file:
for example this is what I Input into the form:
when I try to edit the form this is what I get:
this is my controller for edit:
def edit
#order = Order.find(params[:id])
#customer = Customer.all
#inventories_list = Inventory.all
end
I have been looking at the psql database schema by manual do sql query as follow:
select * from inventory_orders where inventory_orders.order_id = 63;
and get this as result:
now it seems that the fields_for Inventory_orders get the number of rows returned , but I don't get why all the quantity also get displayed 4 times for each product. Also how can I ensure that when I try to edit quantity for product “aaa” it will only display one number_field with what users has input before.
Sorry for the long post,otherwise I am not sure how to clearly convey my meaning.
EDITED
this to show my Inventory Model:
Class Inventory < ActiveRecord::Base
has_many :inventory_orders
has_many :orders, through: :inventory_orders
end
You need to use the following:
//Here display all the inventories list
<% #inventories_list.each do |t| %>
<%= link_to t.pName, inventory_path(t), :remote => true %>
<%= f.fields_for :inventory_orders, t do |qty| %>
<%= qty.hidden_field :inventory_id , value: t.id %>
<%= qty.number_field :quantity %>
<% end %>
<%= t.pMeter %>
<%= t.pSellPrice %
<% end %>
The issue is that since f.fields_for populates a form based on the built associated objects, if you're passing 4 fully constructed objects through the edit action, fields_for is going to populate all of them each time.
What you need is to use the instance of the associated data.
I think your code could be improved a lot:
#app/controllers/orders_controller.rb
class OrdersController < ApplicationController
def new
#order = Order.new
#inventory = Inventory.all
#inventory_order = #order.inventory_orders.build
end
def edit
#order = Order.find params[:id]
#inventory = Inventory.all
end
end
#app/views/orders/new.html.erb
<%= form_for #order do |f| %>
<% #inventory.each do |inventory| %>
<%= f.fields_for :inventory_orders, item do |item| %>
<%= item.text_field :quantity %>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
#app/views/orders/edit.html.erb
<%= form_for #order do |f| %>
<%= f.fields_for #order.inventory_orders do |item| %>
<%= item.text_field :quantity %>
<% end %>
<%= f.submit %>
<% end %>
I'm building a very basic rails application, that provides a form, and gets user submissions.
On the delete action, I keep getting the error: Couldn't find <object> (in this case, question) without an id.
I understand the delete action is asking to find the params by ID, and I'm not sure why it doesn't have an ID.
I added the field question_id to the table questions, hoping that would do it. Have read many other similar questions, the answer isn't clicking. THX in advance.
Index page
<% #questions.each do |display| %>
<table>
<th>Your answer</th></br>
<tr><%= display.answer %></tr></br>
<tr><%= link_to("Delete Action Item", {:action => 'delete'}) %></tr></br>
<% end %>
</table>
Delete view
<%= form_for(:question, :url => {:action => 'destroy', :id => #question.id}) do |f| %>
<p>You're deleting this action item forever - Ok?</p>
<%= submit_tag("Do it - Delete it") %>
<% end %>
Questions Controller
class QuestionsController < ApplicationController
def index
#questions = Question.all
end
def delete
#question = Question.find(params[:id])
end
def destroy
#question = Question.find(params[:id]).destroy
flash[:notice] = "Deleted Action - Nice job"
redirect_to(:action => 'new')
end
private
def question_params
params.require(:question).permit(:answer, :question_id)
end
end
In your index where you are creating the link, you aren't specifying the :id as an argument so your delete action has no params[:id]
Turn this:
<tr><%= link_to("Delete Action Item", {:action => 'delete'}) %></tr></br>
Into this:
<tr><%= link_to("Delete Action Item", {:action => 'delete', :id => display.id}) %></tr></br>
I have following code in my view:
<% #m1.map(&:id).each do |id|%>
<%= b.fields_for :modul1hours do |f| %>
<%= f.hidden_field :modul1_id, id %>
<%= f.text_field :module_est_hours, :size => 30 %>
</tr>
<% end %>
<%end%>
params passing in console
Parameters: {"authenticity_token"=>"LJ/ZME2lHZ7VwCDgPKX6OFe326fXSXo5UB4M0cPwbCE=", "esthour"=>{"rfp_id"=>"6", "ecommerce_est_hours"=>"", "modul1hours"=>{"module_est_hours"=>"3"}, "designpages_est_hours"=>"", "cms_est_hours"=>""}, "modul1_ids"=>["12", "13", "14"], "utf8"=>"✓", "project_id"=>"second", "commit"=>"Add Todo"}
Current user: admin (id=1)
modul1_ids is the hidden array based on that three text box is created but when i submit the page gives me:
ActionView::Template::Error (undefined method `merge' for 12:Fixnum):
in first textbox i passed 1
second 2
and in third 3
last value(3) isthe s passing that one can see in the console params module_est_hours"=>"3, but what about rest two fields y not passing and whats the solution for an error. Please help me.
Edit 1
<% #m1.map(&:id).each do |id|%>
<%= b.fields_for :modul1hours do |f| %>
<%= hidden_field_tag "modul1_ids[]", id %>
<%= f.text_field :module_est_hours, :size => 30 %>
</tr>
<% end %>
<%end%>
this code does not give the error, but also value is not stored in modul1hours table
The field of the modul1hours table are:
integer :modul1_id
decimal :module_est_hours
decimal :module_act_hours
integer :esthours_id
]
.rb
belongs_to :esthour
attr_accessible :module_est_hours,:module_act_hours
and controller
Update
def new
#esthour = Esthour.new
#gg = #esthour.modul1hours.build
#project = params[:project_id]
#rfp = params[:rfp_id]
#m1 = Modul1.where(:rfp_id => #rfp.id)
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #esthour }
end
end
over Update
# GET /project_todos/1/edit
def edit
#esthour = Esthour.find(params[:id])
end
def create
#project = params[:project_id]
#esthour = Esthour.new(params[:esthour])
user_params = params.select{|k,v| k.include?('esthour')}
respond_to do |format|
if #esthour.save
get_issue_attribute_param1(user_params)
format.html { redirect_to project_rfp_url(#project,#esthour.rfp_id), :notice => 'hours was successfully created.' }
format.json { render :json => #esthour, :status => :created, :location => #esthour }
else
format.html { render :action => "new" }
format.json { render :json => #esthour.errors, :status => :unprocessable_entity }
end
end
end
is there any build needed?eg Esthour.modul1hour.build in new def of controller coz record not saved in table?
view
<%= form_for #esthour,:rfp_id => #rfp.id,:project_id => #project do |b| %>
<%= b.hidden_field :rfp_id, :value => #rfp.id %>
<%= hidden_field_tag :project_id, #project %>
<table>
<tr> <td><b>Menutype </b></td>
<% if #rfp.menutype.present? %>
<td><%= #rfp.menutype %></td>
<td><%= b.number_field :menutype_est_hours %></td>
<% end %>
</tr>
<tr> <td> <b>Number of menu</b> </td>
<% if #rfp.numberofmenu.present? %>
<td><%= #rfp.numberofmenu %></td>
<td><%= b.number_field :numberofmenu_est_hours %></td>
<% end %>
</tr>
<tr>
<% #m1.map(&:id).each do |id|%>
<%= b.fields_for :modul1hours do |f| %>
<%= f.hidden_field :modul1_id, value => id %>
<%= f.text_field :module_est_hours, :size => 30 %>
</tr>
<% end %>
<% end %>
</table>
<%= b.submit 'Add Todo' %>
<% end %>
#esthour = Esthour.new
#gg = #esthour.modul1hours.build
#project = params[:project_id]
In this line:
<%= f.hidden_field :modul1_id, id %>
You are saying that you want the hidden field binded with modul1hour modul1_id method and options being id. Second parameter for FormBuilder hidden_field is expected to be a hash (which is then merged against default options). To do what you want do:
<%= f.hidden_field :modul1_id, value: id %>
Hidden fields aren't really the issue here
Apart from #BroiStatse's answer, I can see the issue as how you handle the params on your controller
Nested Models
Sending data to a controller sends that data to the relevant models. This is normally handled with accepts_nested_attributes_for, but can be handled manually too
From your controller code, I can't see how you're dealing with your extra data, but your error is caused by the incorrect merge of the params
Instead of saving the data manually, I would use the accepts_nested_attributes_for to save the data, like this:
#app/models/project.rb
Class Project < ActiveRecord::Base
accepts_nested_attributes_for :modul1hours
end
This will pass the params to your modul1hours model, where you'll then have to capture them with the relevant attr_accessible actions
f.fields_for
In order to get accepts_nested_attributes_for working properly, you have to ensure you use the f.fields_for function correctly.
You have to first build the ActiveRecord objects in your new controller action, like this:
def new
#project = Project.new
#project.modul1hours.build
end
Your problem is that you're then cycling through the ID's of your modul1hours model, yielding the f.fields_for artificially. Rails will only output an f.fields_for if the ActiveRecord object has been built in the controller:
"30" %>
This RailsCast gives you a better idea about this
What I would do is this:
#app/controllers/projects_controller.rb
def new
#project = Project.new
#m1.map(&:id).each do |i|
#project.modul1hours.build
end
end
#app/views/projects/new.html.erb
<%= b.fields_for :modul1hours do |f| %>
<%= hidden_field_tag :id, value :id %>
<%= f.text_field :module_est_hours, :size => "30" %>
<% end %>
I'm still thinking about how I would assign the ID's to the hidden field
Update
Try this:
#app/controllers/projects_controller.rb
def new
#project = Project.new
#project.modul1hours.build
end
Replace modul1hours with whatever your projects has_many of
I'm making a twitter-copy and right now I'm trying to show all the posts from the users an other user is following. I'm new at ruby and rails, so i might be doing this a really weird way..
These are the files I have:
session#home.html.erb
<h2 class='User_Header'> Home <h2>
<%= link_to "New Post", controller: "posts", action: "new" %>
<%= link_to "Log Out", :controller => "sessions", :action => "logout" %>
<%= show_tweets("following") %>
sessions_helper
module SessionsHelper
def show_tweets(opt)
if opt == "following"
#sub = Subscription.where("userID = ?", #current_user.id)
#post = Post.where("user_id = ?", #sub.followingID)
render partial: 'shared/follower_tweets'
end
end
def show_tweet(s)
#post = Post.where("user_id = ?", s.id)
render partial: 'shared/tweet'
end
def tweet_username(p)
#username = User.where("id = ?", p.user_id)
Rails.logger.debug #username.inspect
render partial: 'shared/user'
end
end
_follower_tweets.html.erb
<h2>Tweets</h2>
<table>
<tr>
<th>Username</th>
<th>Tweet</th>
</tr>
<% div_for(#post, class: 'post') do %>
<td><%= tweet_username(#post) %></td>
<td><%= #post.content %></td>
<% end %>
</table>
_user.html.erb
<%= #username %>
session.rb
class Session < ActiveRecord::Base
attr_accessible :content, :user_id, :followingID, :userID
end
Error
app/views/sessions/home.html.erb where line #9 raised:
undefined method `followingID' for #<ActiveRecord::Relation:0x007fd74b66f8a8>
What is happening is that you have followingID on your Session model instead of Subscription model. Should be something like the following:
class Subscription < ActiveRecord::Base
attr_accessible :followingID
end
However, the problem is bigger than that. You must read about Active Record Associations, then you would be able to do something like
#subs = #current_user.subscriptions
#posts = #current_user.posts
check if your model's association is correct. the messages indicates that there's an error about this.