Rails Modify Scaffold Form - ruby-on-rails

Using rails 5.0.0 for building a simple timecard module for a web application. My question is how do I go about modifying a form which is automatically being rendered by rails scaffold
rails g scaffold Timesheet user:string clock:string time:datetime
=== new.html.erb file ===
<%= render 'form', timesheet: #timesheet %>
In the user string want to add <%= current_user.email %> and in clock string want to add a drop-down? What is the best way to do this? Already have database table in place etc...
Illustration below
Thanks in advance!

The form is in an automatically generated partial, located in app/views/timesheets/_form.html.erb.

Ok, in: app/views/timesheets - you should find your form. If you change something in form, check it with your 'new' merhod (or with last method - if you didn't change/add anything: this method will get your params) in controller.

When you run
$rails generate scaffold <name>
you will auto-generate a ready to use controller, model, and views with a full CRUD (Create, Read, Update, Delete) web interface.
You can modify each of the CRUD operations to your liking, in your case timesheets view which is located in app/views/timesheets/.

Related

Best way to do CSV seed file upload to rails repo through administrate?

The main table in my backend gets populated by a CSV file. When seeding and running rails db:seed , the CSV files in lib/assets/csv is read with file = File.read(Rails.root.join('lib', 'assets', 'csv', 'data.csv'), and the logic in seeds.rb runs through each row to create a table entry, populating the fields with the CSV column data.
I've also implemented Thoughtbot's Administrate for a UI admin dashboard to view this data.
So my question is, what is the best way to configure some kind of custom file upload system on Administrate dashboard if I ever need to replace the files sitting in lib/assets/csv and reseed?
I've looked at ActiveStorage but I've only ever used it to store files like an image specifically related to a table entry, not for seeding the entire table.
Yes, it is possible, and you don't need ActiveStorage. Rails's basic file upload facilities will be enough. Meanwhile, Administrate tries to follow Rails conventions, and provides hooks for you to alter the templates and refer to your own controllers and actions where you can implement this. Here's an example of how you could solve your problem.
First, you'll want to add a form with a file field. Admins will be able to use it to upload CSVs.
There are many places where you could put this form. For this example, let's say that it's "products" that you want to import (model Product), and you want to put the link in the index page.
You can override Administrate's own templates with your own ones. The following command will generate a copy of the index template that you can customize and Administrate will use instead of its own:
$ ./bin/rails g administrate:views:index
This will get you a new file app/views/admin/application/index.html.erb.
Alter it to add a link to a separate page that will host the upload form:
<% if page.resource_name == "product" %>
<div class="link-to-upload"><%= link_to "CSV Import", upload_admin_products_path %></div>
<% end %>
You can put this in between the page title and the search bar. Or wherever you want, really. It does the following:
The if checks that we are in the index page for "products" and not for something else.
The link_to links to a page that we haven't created yet, which will host the upload form.
If you load the products index page now, it will show an error NameError, with message undefined local variable or method 'upload_admin_products_path'. This is because we still don't have a route for this new page of ours. Lets add it now.
In the routes file config/routes.rb, you'll already have a route resources :products. Change it to look like this:
resources :products do
collection do
get :upload, action: 'upload_form'
post :upload, action: 'upload_process'
end
end
This actually adds two routes, not one. One will be for the form page, while the other one will be for the action that will process the uploaded CSV.
For now, you can click on the link and go to the new page. It will break again. This time the error will be Unknown action - The action 'upload_form' could not be found for Admin::ProductsController. That's because we haven't provided a view for this page yet. Let's do it now.
Add a view with the following contents at app/views/admin/products/upload_form.html.erb:
<header class="main-content__header" role="banner">
<h1 class="main-content__page-title" id="page-title">
Import products from CSV
</h1>
</header>
<section class="main-content__body main-content__body">
<%= form_for :products, html: { class: "form" } do |f| %>
<p><%= f.file_field(:file) %></p>
<p><%= f.submit "Upload" %></p>
<% end %>
</section>
Now you should be able to load the page and see the form. I have added additional markup (like those header and section elements) to make it look similar to other pages that Administrate provides.
That form has a file_field and a submit button. On submit, it will send the file to the current URL (/admin/products/upload) as a POST request. It will be handled by the post route we added earlier, on the action upload_process. Let's write that now.
On the controller Admin::ProductsController, add the following method to implement the action:
def upload_process
file = params[:products][:file]
data = CSV.parse(file.to_io, headers: true, encoding: 'utf8')
# Start code to handle CSV data
ActiveRecord::Base.transaction do
data.each do |row|
Product.create(row.to_h)
end
end
# End code to handle CSV data
redirect_to admin_products_url
end
This will create new products based on what's contained in the CSV, and then will redirect the user back to the products index page.
This example action is very simple and may not suit your needs exactly. You probably want to copy your code from seeds.rb and paste it in between my Start and End comments, so that it does what you want exactly. There are many possibilities.

ruby on rails 4.2 - ActionController::UrlGenerationError in Prodotti#new

I'm following the tutorial http://guides.rubyonrails.org/getting_started.html but i'm stuck on section 5.2 'the first form'
The error is after i put prodotti_path
<%= form_for :prodotto, url: prodotti_path do |f| %>
my rake routes:
Prefix Verb URI Pattern Controller#Action
welcome_index GET /welcome/index(.:format) welcome#index
prodotti_index GET /prodotti(.:format) prodotti#index
POST /prodotti(.:format) prodotti#create
new_prodotti GET /prodotti/new(.:format) prodotti#new
edit_prodotti GET /prodotti/:id/edit(.:format) prodotti#edit
prodotti GET /prodotti/:id(.:format) prodotti#show
PATCH /prodotti/:id(.:format) prodotti#update
PUT /prodotti/:id(.:format) prodotti#update
DELETE /prodotti/:id(.:format) prodotti#destroy
root GET / welcome#index
but when i refresh the page http://localhost:3000/prodotti/new/ the rails say:
ActionController::UrlGenerationError in Prodotti#new
Why? i'm new to ruby and ror, sorry !
Firstly, welcome to the Rails community!
Here's what you need to do:
#app/controllers/prodottis_controller.rb
class ProdottisController < ApplicationController
def new
#prodotti = Prodotti.new
end
def create
#prodotti = Prodotti.new prodotti_params
end
private
def prodotti_params
params.require(:prodotti).permit(:x, :y, :z)
end
end
Then in your view:
#app/views/prodotti/new.html.erb
<%= form_for #prodotti do |f| %>
<%= f.text_field :attribute_name %>
<%= f.submit %>
<% end %>
OOP
The problem you have is you're using a symbol in your form_for. Whilst this does work, it is not the best way to get it working, especially for a beginner.
Without going into too much detail, I'll explain that form_for is what's known as a helper method. If you pass this certain credentials, it will construct an HTML form for you:
Typically, a form designed to create or update a resource reflects the
identity of the resource in several ways: (i) the url that the form is
sent to (the form element's action attribute) should result in a
request being routed to the appropriate controller action (with the
appropriate :id parameter in the case of an existing resource), (ii)
input fields should be named in such a way that in the controller
their values appear in the appropriate places within the params hash,
and (iii) for an existing record, when the form is initially
displayed, input fields corresponding to attributes of the resource
should show the current values of those attributes.
In Rails, this is usually achieved by creating the form using form_for
and a number of related helper methods. form_for generates an
appropriate form tag and yields a form builder object that knows the
model the form is about. Input fields are created by calling methods
defined on the form builder, which means they are able to generate the
appropriate names and default values corresponding to the model
attributes, as well as convenient IDs, etc.
This basically means that you're meant to pass objects to the form_for helper - objects which have been built in your model and assigned in your controller.
The objects in Ruby are used by Rails throughout your application. Indeed, as Ruby is object orientated, all the things you do with the language, and frameworks, are meant to revolve around objects too.
Rails is object orientated in its own way. Remember, Rails is a framework which sits on top of Ruby. Thus, anything you do has to have objects at the center of the flow:
Models construct the objects in Rails.
Everything from your routes to controller actions take the idea that your models will be invoking data objects -- making it that each "helper" method in Rails (such as form_for) can be used with the corresponding objects you've built.
This is why I recommended setting the appropriate variable and passing it to your form helper. This will tie into your routes and controller actions, and should work for you.

rails g scaffold needs explanation - form_for submits to index?

I am trying to understand the stuff going on during the creation of an object using the pages generated by the command rails g scaffold ModelName.
What I don't understand is that given a model Location, the _form.html.erb form-tag looks like this:
<%= form_for(#location) do |f| %>
This would, if I understand it correctly, point the form submission to location_path, which is like the index (or list) of all locations stored in the database.
Why is the form not pointing to create or update? Where on the way are the objects actually created? I'd be really grateful if someone could describe the flow here, like
_form.html.erb submits to
create in locations_controller.rb which redirects to
index in locations_controller.rb, which renders
sometemplate.html.erb
Where the form submits depends on #location.new_record?.
If it’s a new record, it will POST to locations_path: /locations. That maps to LocationsController#create.
If it’s an existing record, it will PUT (or PATCH on newer versions of Rails) to location_path(#location): /locations/:id. That maps to LocationsController#update.
As #Pavan suggests in the comment, a look at the existing routes can help with understanding routing:
rake routes

Submit form without using object

It's my first post on stackoverflow! I warn you, I just started learning Ruby on Rails.
Currently, I'm working on a music scanning project in rails. I'm trying to process al the music on the hard disk. To do that, the user can add a folder to scan when he is inside the config part of the app. So I store inside a YAML file all the config of my app.
I create a 'config' controller, that contains 2 view for the moment: "adddir" and "index".
The index view show all parameters, that have been gathered by loading the YAML config file (done by the controller 'config').
Next, I want to give the possibility to the user to add a new folder to scan. So I did a static route to the 'adddir' view:
routes.rb file:
match "/config/adddir" => "config#adddir"
Now, I want to create a form that get the path provided by the user, and add it to the YAML file.
So my question is: How to create a form that be able to use the method config#addfolder I created when the user click on submit button?
I hope this is enough clear.
Best regards
Welcome to SO. Its a very basic question. Just have a look at the screencast. Make a simple project first (with a model), then you will see the ABC of Rails.
http://rubyonrails.org/screencasts/rails3/
Basically:
You generate the controller like:
rails g controller config adddir
This setups the controller, the view and your route.
Then go into your view folder and look inside config. There is adddir.html.erb. This file you need to change in something like a form.
You can open your form:
http://localhost:3000/config/adddir
rake routes
Will print you a list of available routes you can use (inside your form).
Now the magic is that Rails generate your a config_adddir_path (watch the _path). That you can use to hookup the form.
<%= form_tag(config_adddir_path, :method => "get") do %>
<%= label_tag(:q, "Folder:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("index") %>
<% end %>
Inside your controller (def adddir):
You can access the parameters:
def adddir
logger.debug params.inspect
end
Have a look here:
http://guides.rubyonrails.org/form_helpers.html

How to create a website form field in Rails 3?

I have a form where I'd like to be able to input a web address, like "google.com", into a form field, and be able to click on this link in the show view of the submitted form.
How can I accomplish this?
show.html.erb
<p>
<strong>Website:</strong>
<%= link_to #video.website, #video.website %>
</p>
Scaffolding will handle it like Jason Swett said. If you are looking to put it in a link in show just do something like this:
<%=link_to #link.name, "http://"+#link.url%>
If that doesn't work you could always do:
<%=#link.name%>
Scaffolding will handle this for you. I recommend going through the Rails Guides, especially this one: http://guides.rubyonrails.org/generators.html
And more specifically, you can generate a model with an attribute called url like this:
rails generate scaffold Thing url:string
And then run your migrations:
rake db:migrate
You should end up with some views in app/views/thing/ and a controller at app/controllers/thing_controller.rb. That should put you on your way.
If you have a model that has an attribute like web_address, you can do:
= text_field_tag, "web_address", ""
(using HAML syntax and tags for form_tag)
And then in your show you can do:
= link_to model.web_address, model.web_address
Which will make a link like: http://www.google.ca

Resources