How can I check if a column for a Ruby on Rails column is required? I am building a process where people can import a CSV and match the headers in the file to relevant columns in the model. I can't guarantee that they will match so would rather the user could match them manually.
I'm ideally looking for something like Model.column_names[0].required?
If the column is required I want the user to be able to specify a generic value for all imports so that they don't fail unexpectedly (hence the unused input fields in the demo below).
I can upload the file contents and parse them, and have built a table where the user can select which CSV column matches which model column but would like to warn the use which are required. I am yet to create the actual import element but there are various other questions on SO with that well documented.
I've had a google and cant see anything, maybe I'm using the wrong search terms but any help would be appreciated.
Thanks in advance!
Controller:
require 'csv'
myfile = params[:file]
csv_text = File.read(myfile.path)
#csv = CSV.parse(csv_text, :headers => true)
#table_headers = Patient.column_names
View:
<% #table_headers.each_with_index do |header, table_i| %>
<tr>
<td>
<%= header %>
</td>
<td>
<select id="table_column[<%= table_i %>]"=>
<option value="skip">Skip</option>
<option value="custom">Custom</option>
<% #csv.headers.each_with_index do |column, file_i| %>
<option value="<%= file_i %>"><%= column %></option>
<% end %>
</select>
</td>
<td>
<input>
</td>
<tr>
<% end %>
If I get you right, you can use custom validation that will return specific error (that you want to share for user).
https://guides.rubyonrails.org/active_record_validations.html#performing-custom-validations
Basically you need to override validate! method.
https://apidock.com/rails/ActiveModel/Validations/validate%21
For identification of such record (that is not valid) you can user valid? method.
https://apidock.com/rails/v6.0.0/ActiveModel/Validations/valid%3F
Related
This is my biblios_helper.rb:
def main_language
[["français","frenchLit"],["latin","latinLit"],["ancien français","froLit"],["néerlandais","dutchLit"]]
end
the form for adding a new bibliography contains :
<%= f.select(:langue_main) do %>
<% options_for_select(main_language, selected: params[:biblio] ? params[:biblio][:langue_main] :"") %>
<% end %>
This results in this html :
<select name="biblio[main_language]" id="biblio_main_language"><option value="frenchLit">français</option>
<option value="latinLit">latin</option>
<option value="froLit">ancien français</option>
<option value="dutchLit">néerlandais</option></select>
That works fine. However, I have the same code in the form that allows for the updating of the bibliography.
when in the database, the language is 'froLit', I want the default to show up in the select menu to be 'ancien français'. How do I do that?
On edit form it will automatically select the corresponding option as default which options is saved in database for this object -
<%=f.select :langue_main, options_for_select(main_language) %>
However if you want to be default selected as always to be ["ancien français","froLit"] Then try this one -
<%=f.select :langue_main, options_for_select(main_language, "froLit") %>
maybe just:
= f.select :langue_main, options_for_select(main_language, params.dig(:biblio, :langue_main))
I am using this example for file uploader.
Now it works this way:
I upload a file, after the file is saved,the function(do_picture_analyse) calls R and produces a histogram(simplest version, in the more complicated version 2 packages have to be installed in R), picture of the histogram is saved. The problem is that if I want to upload 50 files, it takes lots of time to load 2 packages in R for each file separately(after_save callback).
What I need:
I upload a file, file is saved, I click on a button "Histogram" and the function do_picture analyses is called on all files that are in the database( It doesnt matter if some of the files have already been analyzed)
So I need only to know how to make an interaction between a button and a call of the function and nothing more.
My show.html.erb:
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
<td></td>
<td class="name">
{%=file.name%}
</td>
<td class="nam">
{%=file.name%}
</td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td class="Pic">
<button class="btn btn-mini btn-info">Pic</button>
</td>
<td class="Hist">
<button class="btn btn-mini btn-primary" >Hist</button>
</td>
<td class="delete">
<button class="btn btn-mini btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">
<i class="icon-trash icon-white"></i>
</button>
<input type="checkbox" name="delete" value="1">
</td>
</tr>
{% } %}
</script>
my upload.rb:
def to_jq_upload
{
"name" => (read_attribute(:upload_file_name)).split(".").first,
"size" => read_attribute(:upload_file_size),
"url" => upload.url(:original),
"delete_url" => upload_path(self),
"delete_type" => "DELETE",
"url_chip_image"=>read_attribute(:chip_image),
}
end
after_save :do_picture_analyse
def do_picture_analyse
if read_attribute(:chip_image)==nil
require 'rinruby'
myr = RinRuby.new(echo=false)
myr.filepath=upload.path(:original)
myr.fileurl=upload.url(:original)
myr.eval <<EOF
s=read.table(filepath)
for(j in nchar(filepath):1){
if(substr(filepath,j,j)=="/"){
savepath<-substr(filepath,1,j-1)
file.name<-filepath
file.name<-substr(file.name,j+1,nchar(filepath)-4)
break
}
}
file.name1<-paste(file.name,"image.jpeg",sep="_")
savepath<-paste(savepath,file.name1,sep="/")
jpeg(filename=savepath,width=250, height=250)
hist(s$V1)
dev.off()
EOF
self.update_attributes(
:chip_image => (((myr.fileurl).split("?").first)[6..-5]+'_image.jpeg')
)
end
end
EDIT:
do_picture_analyse can take a folder as a parameter and analyse all files inside it by loading the the packages only one time for entire folder.There are only two folders for the files(two different types of files, let say .txt and .blabla files will be saved either in the txt-Folder or in a blabla-Folder. The type of the folder is saved in the database as well. By clicking the button, two folders should be passed to the do_picture_analyse and it will do everything
Thanks in advance
you need to create a new route for this :
resources :name_of_your_controller do
# use this if you want a route like resources/:id/analyze (single file)
get :analyze, on: :member
# use this if you want a route like resources/analyze (multiple files)
get :analyze, on: :collection
end
then create a new action on your controller :
def analyze
# for single file analysis do something like this :
#file = File.find( params[:id] )
#file.do_picture_analyse
respond_to do |format|
# render what you need to render, js or html
end
# ... or do something like this for multiple file analysis :
#files = File.where( params[:search] )
#files.each {|f| f.do_picture_analyse )
# etc.
end
you can then link your button to your action :
# single file
<%= link_to "Histogram", analyze_file_path( file ) %>
# multiple files
<%= link_to "Histogram", analyze_files_path( search: your_search_conditions ) %>
PS: if your method needs a lot of processing power (if you use R, i assume that you have complex calculations involved), you should consider to extract it in a Worker to run it as a background task.
edit
response to your comments :
i think you should extract this method and make it a class method, that accepts one or more paths.
Then create a collection route that points to your controller ; in your controller action load the files according to some params and does something like this :
# find the directories to be processed :
paths = #files.map(&:folder_type).uniq
# pass them to your class method :
File.do_picture_analyse(paths)
It is even possible to create a class methods that automatically handles these two steps for all files in a relation :
def self.perform_analysis!
paths = all.map(&:folder_type).uniq # or uniq.pluck(:folder_type) on rails >= 3.2.1
do_picture_analyse(paths)
end
def self.do_picture_analyse( *paths )
# call R from here
end
then you can do :
File.where( your_search_params ).perform_analysis!
The short and sweet answer: in your show.html.erb write:
<td class="Hist">
<%= link_to 'Histogram', histogram_path, ;method => :post, :class => 'btn btn-mini btn-primary" %>
</td>
In your config/routes.rb add the following line
post '/histogram' => 'your-controller#histogram', :as => 'histogram'
THis means that the histogram_path will point to a controller named your-controller and call the action histogram. Please replace those with your names.
And then you should be good to go.
I have taken the liberty to propose a POST action, because I am assuming the action is not idempotent. If it is, you should use a GET.
Hope this helps.
I am building a dynamic form builder.. And i have a problem which i can't seem to fix.
So i have a db table called "forms"
forms can have "fields"..
The problem is that when a user creates a new 'field' (click add-field) then it should ajax the new field for .. that field.
The problem is that i can't just do something like this:
<%= Form.fields_for Field.new do |field| %>
<%= field.text_field :name%>
<% end %>
Does anybody have an idea? Yes i watch railscasts, yes i googled, yes i found the "complex-forms' repo on github.
But no luck (yet)
If you want an all javascript approach (instead of calling your server to produce the field names) then basically you just need to increment the field names for any new fields.
For example, if you have
class Form < ActiveRecord::Base
has_many :fields
accepts_nested_attributes_for :fields
and the HTML in the form has an input field that has something like
<label for="form_fields_attributes_0_name">
<input id="form_fields_attributes_0_name" name="form[fields_attributes][0][name]" type="text" />
then you need to write some javascript to make it look like
<label for="form_fields_attributes_1_name">
<input id="form_fields_attributes_1_name" name="form[fields_attributes][1][name" type="text" />
You can do something like
$('#form_fields_attributes_1_name').attr('id').split('_');
and
$('#form_fields_attributes_1_name').attr('name').split(/\]\[/);
to get at those numbers.
Here's an example which is refactored here.
I'm developing a project and I have a problem about this subject.
I'm constructing ruby on rails project which will provide listing students with name.
First of all , I will list my students information in a table and one part is missing.
When the user clicks on Student Name , another table will appear and show the other information of students(like course or GPA).
The table shows the students name ( this part is succeed.)
But I don't know how to post my variable when user clicks on the students name.
Moreover , I know fundementals of AJAX.But I don't know how to pass my variable while user clicks on students name in the table.
I don't use form , and I try to fix this problem with link_to_remote method but I can't post my variable.Because I can construct my table in for-loop according to my listing variable which contains whole database.I filter for getting only names and surnames in controller part of ruby on rails and i have listing variable for this.when in for-loop i use <%=student.name%> tag for displaying the part of my variable.and I must post this variable to page for filtering GPA or Course name according to names.I need something like link_to_remote method for posting my variable student.name
I'm waiting your help.
Code is below :
<table border="1">
<tr>
<th>
Name
</th>
</tr>
<% #listing.each do |student| %>
<tr>
<td>
<%=student.name%> <%= student.surname %>
</td>
</tr>
<% end %>
problem fixed ,:with => "'id=blabla'" in link_to_remote method
Basically I have a set of checkboxes that are dynamically created from view data like so:
<input type="checkbox" name="Calendars" value="<%= c.ID %>" /><%= c.Name %>
The value being the Calendar Id.
I can get what checkbox has been brought back using the FormsCollection its messy but it works!
(There also seems to be a bug with the checkbox helper that renders a hidden field next to the checkbox which means true is actually returned as "true,false"! I can work around this so its not an issue just thought Id mention it)
The problem comes when trying to hook the checkboxes up on an edit page!
I have a schedule class which can have multiple calendars and I want to show which calendars a schedule has by checking them on the edit!
My view is strongly typed but MVC magic can't map this!
Any ideas on whats the best way to do this??
I had tried passing the calendar ids in ViewData and do some inline code to check the appropriate checkbox but this is getting messy!
Thanks!!
UPDATE:
Done this
s.ID == c.ID).Select(s => s).Count() > 0) ? "checked=checked" : "" %>
You need to add "checked" tag manually to every check box:
<input type="checkbox" name="Calendars" value="<%= c.ID %>" checked="checked" /><%= c.Name %>
You dont need <input type="checkbox" - use Html.Checkbox(). It renders a hidden field next to the checkbox - but it is not a bug. From ASP.NET MVC source, InputExtensions.cs, line 201:
// Render an additional <input type="hidden".../> for checkboxes. This
// addresses scenarios where unchecked checkboxes are not sent in the request.
// Sending a hidden input makes it possible to know that the checkbox was present
// on the page when the request was submitted.
Use this:
<%= Html.CheckBox("Calendars", c.ID) %>