How to pass params to new view in Ruby on Rails app? - ruby-on-rails

I'm trying to make simple app. I input my first name and last name to simple <%= form_for #data do |f| %> rails form and after submitting it, app should render simple text like this. My first name is <%= data.first_name %> and my last name is <%= data.last_name %>. I don't know why but my app is saying this error:
undefined local variable or method `data' for
It's probably saying it because no params are passed to view.
Here is my code.
routes.rb
resources :data, only: [:new, :create, :index]
data_controller.rb
class DataController < ApplicationController
def new
#data = Data.new
end
def index
end
def create
#data = Data.new(data_params)
if #data.valid?
redirect_to #data
else
render :new
end
end
private
def data_params
params.require(:data).permit(:first_name, :second_name)
end
end
/views/data/new.html.erb
<%= form_for #data do |f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
<%= f.label :second_name %>
<%= f.text_field :second_name %>
<%= f.submit 'Continue', class: 'button' %>
<% end %>
/views/data/index.html.erb
<h2>Coolest app ever :D</h2>
<p>My first name is: <%= data.first_name %>.</p>
<p>And my second name is: <%= data.second_name %>.</p>
/models/data.rb
class Data
include ActiveModel::Model
attr_accessor :first_name, :second_name
validates :first_name, :second_name, presence: true
end
Please help to find out why params are not passing to next page. Thanks anyways :D

Your view should look like this:
<h2>Coolest app ever :D</h2>
<p>My first name is: <%= #data.first_name %>.</p>
<p>And my second name is: <%= #data.second_name %>.</p>
Also, I would suggest that calling a model something generic like Data is not a very Rails-y approach. Generally, domain models correspond to real-world things like User and Article, which are easy to understand and relate to. It'll get confusing quite fast if you use need to make another model and want to call it Data2 or something :)

Edit:
Since you specified that you do not wish to use the database, I would recommend passing in the object params through the redirect:
redirect_to(data_path(data: #data))
and in your controller's index method:
def index
#data = Data.new(params[:data])
end
Now your view should render properly, since you're passing the in-memory #data object attributes as params within the redirect. You then recreate this object in the index page or wherever you wish to redirect to.
To expand on Matt's answer, the reason you're getting NilClass errors is because:
You're redirecting to a data#show action when no show action has been enabled within your routes file. Since you've set your views up for the index, I'm assuming you want to redirect there when the #data object has been verified as valid:
redirect_to data_path
However I would recommend you follow Rails conventions and specify the data#show route within your routes.rb:
resources :data, only: [:index, :new, :create, :show]
and in your data_controller.rb:
def show
#data = Data.find(params[:id])
end
Another problem is that you're not actually saving the #data object upon creating it. The new method populates the attributes, and valid? runs all the validations within the specified context of your defined model and returns true if no errors are found, false otherwise. You want to do something like:
def create
#data = Data.new(data_params)
if #data.save
redirect_to data_path
else
render :new
end
end
Using save attempts to save the record to the database, and runs a validation check anyways - if validation fails the save command will return false, the record will not be saved, and the new template will be re-rendered. If it is saved properly, the controller will redirect to the index page, where you can call upon the particular data object you want and display it within your view.

Related

rails different form attributes based on category

I have a rails app!
I'd like to create a form for a product model, where users can choose a product category first and then can fill the form out.
This would be easy, but I'd like to show them different attributes based on the chosen category. Something like if they choose book category, then they will have fields like title, author, published_at, but if they choose shoes category then they can fill out the size, color and type fields.
I saw afew tuts about dynamic forms, but as far as I understand it, I don't need that since the form fields will be predefined and users won't be able to add extra fields.
What is the good approach in this case? Should I create more different models like (shoes,books, etc.) or something else?
Should I create more different models
No, I don't think that's necessary.
What you'd be best doing is using ajax to populate the form on category change. This would require some configuration, but will make it the most efficient and secure:
#config/routes.rb
resources :products do
put :new, on: :new #-> url.com/products/new
end
#app/controllers/products_controller.rb
class ProductsController < ApplicationController
def new
if request.get?
#product = Product.new
#categories = Category.all
elsif request.put?
#category = params[:product][:category_id]
#attributes = ...
end
respond_to do |format|
format.js
format.html
end
end
end
#app/views/products/new.html.erb
<%= form_for #product do |f| %>
<%= f.collection_select :category_id, #categories, :id, :name, {}, { data: { remote: true, url: new_product_path, method: :put }} %>
<div class="attributes"></div>
<%= f.submit %>
<% end %>
#app/views/products/new.js.erb
$attributes = $(...); // need a way to create form elements from #attributes
$("form#new_product .attributes").html( $attributes );
Something important to note is that Rails select & check elements allow you to use the data-remote attribute to send an ajax call to your controller on change.
Not much documentation about it, playing around with the above code should get it to work.

name error uninitialized constant path in rails

I'm trying to make a form that will post to a database, I'm really struggling at the moment and i'm getting this error.
NameError in AddController#index
uninitialized constant AddController::Newevents
Could you advise what i would need to do?
Heres all the code i have
Form
<%= simple_form_for(#newevent) do |f| %>
<%= f.input :eventname, required: true %>
<%= f.input :eventdate %>
<%= f.input :eventimage %>
<%= f.button :submit %>
<% end %>
controller
class AddController < ApplicationController
def index
#newevent = Newevent.new
end
end
Model
class Newevent < ActiveRecord::Base
def event_params
params.require(:Newevent).permit(:eventname, :eventdate, :eventimage)
end
end
Routes
resources :add
Edit
i now have this error undefined methodnewevents_path'` after changing this
#newevents = Newevent.new
It seems that you miscopied your code here. The error message indicates that your index method actually looks like this
def index
#newevent = Newevents.new
end
Remove the s from the end of Newevent and it should work.
RE: your edit
Your routes declare that you have a resource named add, if you want to show and create your Newevent objects, then you should create a controller for that. Declare resources :newevents in your routes and create a controller to handle it.
You should research RESTful routes, because that's what Rails's resource routing works best with. The form to create a new object should be displayed by the new action and not index.
You should be using create method instead of index if you are using POST http method. index will be called if you are using GET method and it shouldn't be used to post the form data. Refer this link for more information on rails routing.
class AddController < ApplicationController
def create
#newevent = Newevent.new
end
end

undefined method `_path' in form, with routes defined at :resources

I've been stuck on this for a bit and can't figure out the exact reason why I'm getting the following error:
undefined method `entries_path' for <%= form_for(#entry) do |f| %>
entry_controller:
class EntryController < ApplicationController
def index
end
def new
#entry = Entry.new
end
def create
#entry = Entry.new(user_params)
if #entry.save
redirect_to #entry
else
render 'new'
end
end
private
def user_params
params.require(:entry).permit(:comment, :flag)
end
end
routes has:
resources :entry
and the new page where the error occurs:
<%= form_for(#entry) do |f| %>
<%= f.label :comment %>
<%= f.text_field :comment %>
<%= f.label :flag %>
<%= f.text_field :flag %>
<% end %>
I can't figure out why I'm getting this error.
form_for needs to reference the path associated with #entry (i.e. entries_path), but your routes.rb file uses the singular form of the resource (:entry) rather than the required plural form (:entries), so the proper path names don't exist.
Rails models use the singular form, but the Rails database, controllers, views use the plural form and this is reflected in the routes file. One way to remember this is that a model is describing a single class that each object belongs to. Everything else, pretty much, is responsible for managing multiple instances, so while they themselves are singular (e.g. Controller), they refer to the objects they manage in the plural form (e.g. EntriesController, controller/entries directory).
See Ruby on Rails plural (controller) and singular (model) convention - explanation for more discussion of this.
Controller and views should always be treated in plural form. For example, if you have an object Book, then the controller declaration should be
class BooksController < ApplicationController
and the views( new, edit, show, index ) should be inside a folder named
/books
Also, the declaration of routes should be in plural form. In this case, the routes should be declared as
resources :books
You could try to generate the controller and view folder by running in your terminal:
rails generate controller name_of_object_in_plural_form( for sample, books)
The script will generate a controller named books_controller.rb and /books folder under /views

Getting 'form_for(#something)' to work outside of new.html.erb

I want to place my <%= form_for(#something) do |f| %> which is currently located in app/views/something/new.html -- inside multiple pages, so maybe in app/views/layouts/application.html.erb
How do I get the #something variable and the form to work properly there, or somewhere else -- since it's defined in the controller #new action of SomethingController, it only seems to be available in the appropriate new.html.erb view..
You can put the form anywhere, just provide an instance variable of #something in controller
The basic usage is here.
ThisThingsController
def show
#this_thing = foo
#that_thing = bar
end
end
# View
<%= #this_thing %>
<%= form_for #that_thing %>
Of course you can use partial to render the form, as long as you feed it with variable it needs.
Try
<%= form_for SomeThing.new do |f| %>
Without fully understanding what you are trying to accomplish, I'll make this suggestion.
Add a before filter to your ApplicationController (alternatively you could create a module and mix it in where needed). Then call the before_filter when needed. This example will always run the before filter:
class ApplicationController
before_filter :set_something
private
def set_something
#something = ... # Fill in the logic here
end
end
Then add your form where needed. You can even make it appear conditionally depending on whether #something is set.
<% if #something %>
# Form goes here
<% end %>

Undefined method 'model_name' when attempting to use Simple Form in Rails

I am attempting to get a form generated by simple-form in my modal, however I keep running into the following error upon loading the page.
undefined method 'model_name' for NilClass:Class
Here is the simple code I was using to try to generate the form
_header.html.erb (under the view_pages_controller)
<%= simple_form_for #update do |f| %>
<%= f.input :lang %>
<%= f.input :book %> #temp, just for testing simpform
<%= f.button :submit %>
<% end %>
I am pretty sure the problem lies with my controller code
updates_controller.rb
class UpdatesController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
def create
#update = current_user.updates.build(params[:update])
if #update.save
flash[:success] = "Update successful"
redirect_to root_path
else
flash[:error] = "Failed to update, please try again"
redirect_to root_path
end
end
end
update.rb
class Update < ActiveRecord::Base
attr_accessible :book, :user_id, :lang, :round_id
belongs_to :user
end
Any help/tips would be greatly appreciated. I know my code sucks.
The problem is that #update is null in your view. You should clarify which action renders this view, and set value to #update. The create action only sets it based on the params, and then redirects to root.
I believe you are using some kind of RESTfull controller, and you are rendering your form on action :new. So, to solve your trouble, add
#update = current_user.updates.build(params[:update])
to your new action
Have you tried putting a debugger in above the line in your controller where you declare #update.
You could then see your current_user object and what methods are available using something like current_user.methods
Have you included resource:'updates' or resources:'updates' in routes.rb.This may solve the problem.

Resources