How do I embed ruby.rb file via form in a way that ruby.rb would be executed and results visible in view
A simple way to put a basic form up as a web site is Sinatra. The following is a web app in a single file, using Sinatra.
#!/usr/bin/env ruby
require 'sinatra'
get '/' do
erb :guess
end
post '/' do
@guess = params[:guess].to_i
if @guess == 10
@message = "Correct!"
else
@message = "Try again..."
end
erb :guess
end
__END__
@@ layout
<html>
<body>
<%= yield %>
</body>
</html>
@@ guess
<form action="" method="post">
<p>Guess a number: <input type="text" name="guess"/></p>
<p><%= @message %></p>
</form>
Install the sinatra gem and run the file. You'll see a message like
== Sinatra/1.3.3 has taken the stage on 4567
Then point your browser at http://localhost:4567/
and your app is online.
whenever gem schedule.rb file: doesn't recognize RAILS_ROOT variable
Whenever doesn't require or depend on Rails at all, so when it runs, RAILS_ROOT is not defined, however because whenever's schedule.rb is generally kept in /config/schedule.rb, we can make an assumption that it is in a rails project, and set our own RAILS_ROOT like this:
# in schedule.rb
RAILS_ROOT = File.dirname(__FILE__) + '/..'
Edit: in the case that you actually need Rails loaded, do this:
# in schedule.rb
# this will require config/environment and load your entire rails environment
require File.expand_path(File.dirname(__FILE__) + "/environment")
Rails - How to pass data between Rails controller and JavaScript Stimulus controller to dynamically change view
This sounds like plain old pagination.
If there could be thousands of movies you'd be generation markup/html for thousands of movies. With pagination you'd get get 3 records at a time. Could even use a turbo-frame to replace the next 3.
But if you really want to do what your thinking, you'd have hide all cards except for the first 3, then use stimulus to get the next or last three cards.
A test example
Controller
class TestController < ApplicationController
def index
@movies = Array.new(100) { |e| e = e + 1 }
end
Template using slim
.bg-white
div[data-controller="movies"]
- cnt = 0
button.btn[data-action="click->movies#last_set"] Last
button.btn[data-action="click->movies#next_set"] Next
- @movies.each do |m|
- if cnt < 3
div[data-movies-target="movie" class='block'] = "This is movie #{m}"
- cnt += 1
- else
div[data-movies-target="movie" class='hidden'] = "This is movie #{m}"
Stimulus Controller
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="movies"
export default class extends Controller {
static targets = ['movie']
connect() {
this.size = this.movieTargets.length
this.idx = 0
// this.idx points to the first current cards (3 for example)
}
next_set() {
let curr = this.idx
this.idx = curr + 3 // set new idx
if (this.idx > this.size) {this.idx = this.size - 3}
for (var i = curr; i <= curr + 2; i++) {
this.movieTargets[i].classList.add("hidden")
}
for (var i = this.idx; i <= this.idx + 2; i++) {
this.movieTargets[i].classList.remove("hidden")
}
// console.log(`idx = ${this.idx}`)
}
last_set() {
let curr = this.idx
this.idx = curr - 3 // set new idx
if (this.idx < 0 ) {this.idx = 0}
for (var i = curr; i <= curr + 2; i++) {
this.movieTargets[i].classList.add("hidden")
}
for (var i = this.idx; i <= this.idx + 2; i++) {
this.movieTargets[i].classList.remove("hidden")
}
// console.log(`idx = ${this.idx}`)
}
}
Just a rough example.
EDIT Not very good at javascript and cleaned up the stimulus controller, added variable number of elements to display and work with pages instead of elements.
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ['perPage','movie','status','nextBtn','lastBtn']
connect() {
this.size = this.movieTargets.length
this.page = 0
this.perPage = Number(this.perPageTarget.innerHTML)
this.pages = Math.floor(this.size/this.perPage)
if ((this.size % this.perPage) > 0) {this.pages += 1}
this.setStatus()
// this.page points to the current set of cards (3 for example)
}
next_set() {
if (this.page == (this.pages - 1)) {return}
this.hide()
this.page += 1
this.show()
this.setStatus()
}
last_set() {
if (this.page == 0) {return}
this.hide()
this.page -= 1
this.show()
this.setStatus()
}
hide(){
let curr = this.page * this.perPage
let last = curr + this.perPage - 1
while(curr <= last){
if (curr >= 0 && curr < this.size) {
this.movieTargets[curr].classList.add("hidden")
}
curr++
}
}
show(){
let curr = this.page * this.perPage
let last = curr + this.perPage - 1
while(curr <= last){
if (curr >= 0 && curr < this.size) {
this.movieTargets[curr].classList.remove("hidden")
}
curr++
}
}
setStatus(){
this.statusTarget.innerHTML = `Page ${this.page + 1} of ${this.pages}`
if (this.page == 0) {
this.lastBtnTarget.classList.add('hidden')
}else{
this.lastBtnTarget.classList.remove('hidden')
}
if (this.page == this.pages) {
this.nextBtnTarget.classList.add('hidden')
}else{
this.nextBtnTarget.classList.remove('hidden')
}
}
}
search function not working - Ruby on rails
Instead of using 2 different methods for search, try combining both in index method. Your index method will now look as follows:
def index
if params[:search]
@availabilities = Availability.unmatched.search(search_params[:start_city])
else
@availabilities = Availability.unmatched
end
end
Change the form url
to search_rides_path
. This way search results will be rendered in same view upon form submission.
If else statements in .html.erb in views
Unless you can think of a way to re-write this as a helper method, you're basically stuck with it looking kind of ugly. That's just how ERB is, as it was intended to be a minimal way of injecting Ruby into an otherwise plain-text template, not as something necessarily streamlined or elegant.
The good news is a syntax-highlighting editor will usually make your <% ... %>
ERB blocks look visually different from your HTML so that can dramatically improve readability.
It's also why other representations like HAML have been created where that syntax is a lot less cluttered:
- if some_condition_previusly_established_in_a_controller
.one 123
- else
.two something else
How can create records using input date and save the param using ROR?
There are some problems in the codes.
1. params are only accessible in controller, you wanted to read it in your model
There are many ways to pass params value to model, for example, you can add attr_accessor :dateadd
to the model.
But I think a clearer way is to extract the behavior in :save_default_values into a new public method and call it in the controller.
2. params[:name] is an attribute in the model, you should use strong parameters to assign the attributes
3. it's apparently that dateuser is a column of user_jobs, isn't it?
We can use date_field
to pick the date and also add this field into strong parameter.
4. After a record saved, that record is not new record any more since it has id value.
Try to use after_create
or after_save on: :create
. However, I don't use this callback in the code below, but it's just personal choice :)
# user_job.rb
class UserJob < ApplicationModel
# add new public method
def add_additional_jobs!(days)
(1..days).each do |n|
UserJob.create!(name: name, dateuser: dateuser + n.days)
end
end
end
# user_jobs_controller.rb
class UserJobsController < ApplicationController
def new
@user_job = UserJob.new
end
def create
UserJob.transaction do
@user_job = UserJob.create!(user_job_params)
if params[:dateadd].to_i > 0
@user_job.add_additional_jobs!(params[:dateadd].to_i)
end
end
end
private
def user_job_params
params.require(:user_job).permit(:name, :dateuser)
end
end
Then in the view
<%= form_with(model: user_job) do |form| %>
Name:<%= form.text_field :name %>
Date: <%= form.date_field :dateuser %>
Date added: <%= text_field_tag "dateadd", params[:dateadd].to_i %>
<%= form.submit %>
<% end %>
Convert working Ruby on Rails form to AJAX
You're on the right track, now you need to modify the def ping
action with a respond_to
block.
def ping
ping_host(params[:ip])
save_host(params[:ip])
respond_to do |format|
format.html { redirect_to tools_path } ## if you still want to have html
format.js
end
end
and create a file called view/tools/ping.js.erb
where you have javascript that will be run and returned asynchronously
$("#output").html("<%= j @results %>");
The <%= %> block will be evaluated first and replaced with the output of that ruby code. Then this will be inserted into the #output div.
Calling a CoffeeScript function across all views (Ruby on Rails)
Try something like this?
scrollToError = ->
$('*[data-scroll-to-error="true"]').click ->
alertElement = $('.alert-danger:visible:first')
if alertElement.length > 0
$('html, body').animate {
scrollTop: alertElement.offset().top - 220
}, '1000'
# Run with turbolinks.
$(document).on 'page:change', scrollToError
and a submit button with the data-scroll-to-error
attribute set.
<input type="submit" data-scroll-to-error="true" />
I find this statement of yours confusing:
I have the file included in our application.rb file in the config
folder, so that it can be called in any HTML file in the views section
Assuming this is a standard Rails project, you should have included the file containing the Coffeescript code in assets/javascripts/application.js
(the manifest file), and since application.js
is the JS file required in the layout (isn't it? :-/), this code would execute on all of your views. I don't see how config/application.rb
is involved here.
Update: Adding more information.
If you're unsure about how to application.js
file (a manifest file) is used, please take the time to go through Rails' official documentation about it (especially the section about manifests).
http://guides.rubyonrails.org/asset_pipeline.html#manifest-files-and-directives
In your case, you'll want to modify application.js
to include:
...
//= require error
...
Basically, you list all the asset files that you want loaded along with all pages that use a layout (probably application.html.erb
), and then mention only the manifest file the layout. That way, Rails can concatenate and minify to generate a single asset file. The default application.
manifest files are automatically precompiled - so you don't need to manually add new assets to the precompile list.
The reason why I wrote the selector as *[data-scroll-to-error="true"]
was personal preference - the code reads better to me that way. If you're sure that the ID submit
is (and will be in future) applied only to elements that require scrolling to error, then it's fine to change the first selector to $('#submit').click ->
Related Topics
How to Know If an Io Is Empty Without Reading It
Net::Ssh with Non Unix/Linux Host
Chef: Undefined Node Attribute or Method '<<' on 'Node' When Trying to Add
How to Link to a Nested Route Path Inside a Loop
When Joining Table, Rails Anyway Makes Additional Request When Accessing Fields from Joined Table
To_Model Delegated to Attachment, But Attachment Is Nil
How to Find the Average of 3 Date in Ruby on Rails or Ruby
Get Underlined Text with Markdown
Rails Byebug Did Not Stop Application
How to Get Unique Elements in This Array
How to Understand Strptime VS. Strftime
How to Target a Specific Commit Sha with Capistrano Deploy
Rails Console Is Not Outputting SQL Statements to My Development Log
Download All Gems Dependencies