Add verbs to resources of Rails's routing - ruby-on-rails

By default, the resources keyword of Rails routing creates 7 actions.
For example with resources :foos:
-----------------------
| Verb | Action |
-----------------------
| GET | index |
| GET | show |
| GET | edit |
| GET | new |
| PUT/PATCH | update |
| POST | create |
| DELETE | destroy |
-----------------------
How can we add inside this list the OPTIONS verb such as:
--------------------------------
| Verb | Action |
--------------------------------
| ... | ... |
| OPTIONS | member_options |
| OPTIONS | collection_options |
--------------------------------
In other words, by default, for each resource, we have to use something like this:
match '/foos/', via: :options, controller: 'foos', action: 'collection_options'
match '/foos/:id/', via: :options, controller: 'foos', action: 'member_options', as: :foo
resources :foos
Instead, I would prefer a custom settings in order to just do this:
resources :foos

To avoid listing every path for the OPTIONS verb, you could add a catch all route, e.g.
match '*path', to: 'application#cors_preflight_check', via: [:options]

Related

Rails 5: Does ActiveRecord uses id sequence when using build

I have 2 models which have 1 to 1 relationship, namely Project and Inspection, the structure is something like,
class Project < ApplicationRecord
has_one :inspection
def inspection_required?
(inspection || build_inspection).required?
end
end
class Inspection < ApplicationRecord
belongs_to :project
def required?
required_saved || API.check({ id: id})
end
end
As you see above, for a Project if we don't have an Inspection it does build_inspection. I looked at the database and it seems like the inspection record id skips the sequence as shown below,
ID | PROJECT_ID | VENDOR_TYPE | REQUIRED_SAVED | CREATED_AT | UPDATED_AT |
---|--------------|-------------|----------------|---------------------|----------------------|
1 | 7983f1a33d55 | vendor1 | false | 2020-09-12 00:43:52 | 2020-09-12 00:43:52 |
3 | asdereww224f | vendor2 | true | 2020-09-12 00:48:51 | 2020-09-12 00:48:51 |
4 | 3q3332reere1 | vendor1 | false | 2020-09-13 01:02:53 | 2020-09-13 01:02:53 |
7 | 1df343qe233a | vendor2 | true | 2020-09-14 02:43:51 | 2020-09-14 02:43:51 |
The ID column is skipping sequence.
So my question is, does build_inpsection is using the Sequence generated by Postgres SQL even when we don't save the record?
Rails version: Rails 5.2.3
Postgres version: 9.6

Cucumber rails test result

I am learning cucumber / capybara on rails. I working on a scenario that expects to display sorted data from a table. I cannot figure out this message:
pending # express the regexp above with the code you wish you had
I have this table:
| title | rating | release_date |
| Aladdin | G | 25-Nov-1992 |
| The Terminator | R | 26-Oct-1984 |
| When Harry Met Sally | R | 21-Jul-1989 |
| The Help | PG-13 | 10-Aug-2011 |
| Chocolat | PG-13 | 5-Jan-2001 |
| Amelie | R | 25-Apr-2001 |
| 2001: A Space Odyssey | G | 6-Apr-1968 |
| The Incredibles | PG | 5-Nov-2004 |
| Raiders of the Lost Ark | PG | 12-Jun-1981 |
| Chicken Run | G | 21-Jun-2000 |
Below is my step definition:
When(/^I clicked "(.*?)"$/) do |arg1|
if arg1 == "Movie Title"
click_link ("title_header")
end
end
Then(/^I expect "(.*)" before "(.*)"$/) do |arg1, arg2|
assert page.body.expect =~ /arg1.*arg2/
end
The message again I am trying to resolve is below:
You can implement step definitions for undefined steps with these snippets:
Then(/^I expect to see "(.*?)" before "(.*?)"$/) do |arg1, arg2|
pending # express the regexp above with the code you wish you had
end
Thank you for the help.
You need to define the step correctly, you are missing the 'to see' in your step definition

render with the specified mime type not downloading properly in rails

I am using following statement, but it is not downloading the excel file instead it downloading the normal text file to the browser.
render 'employees/checkin_report', :dates_arr => #dates_arr, :employees => #employees, :content_type => "application/vnd.ms-excel"
I am having checkin_report.xls.erb file, in employees view folder.
If you go to config/initializers/mime_types.rb in your project. You'll see something like this.
#Add new mime types for use in respond_to blocks:
#Mime::Type.register "text/richtext", :rtf```
There you can register new MIME types.
| Short name | respond_to symbol | Aliases and explanations |
|:---------------:|:-----------------:| ---------------------------:|
| text/html | :html :html | application/xhtml+xml |
| text/plain | :text, :txt | |
| text/javascript | :js | application/javascript, |
| | | application/x-javascript |
| text/css | :css | Cascading style sheets |
| text/calendar | :ics | iCalendar format for sharing|
| | |meeting requests and tasks |
| text/csv | :csv | Comma-separated values |
| application/xml | :xml | text/xml, application/x-xml |
| application/ | :rss | Really Simple Syndication |
| rss+xml | |format for web feeds |
| application/ | :atom | Atom Syndication Format for |
| atom+xml | |web feeds |
| application/ | :yaml | text/yaml--the human |
| x-yaml | |readable |
| | | Data serialization format |
| application/ | :url_encoded_form | The default content type of |
| x-www-form | |HTML forms |
| urlencoded | | |
| multipart/ | :multipart_form | Used for HTML forms that |
| form-data | |contain files, non-ASCII |
| | |data, and binary data |
| application/json| :json | text/x-json, application/ |
| | |jsonrequest-- |
| | | Javascript object notaion |
I'm sure there are more MIME types you can implement. These are the more common ones.

User friendly parent/child routes for categories

I want to have URL like www.mydomain.com/category/parent/child so my routes are get '/category/:name(/:name)' => 'categories#show'
I got a table 'categories' like
> desc categories;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| public_id | int(11) | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
| root | int(11) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
I populate the database like this
Category.create(:public_id => 60, :name => "nues", :root => 0)
Category.create(:public_id => 61, :name => "artistiques", :root => 60)
Category.create(:public_id => 62, :name => "glamours", :root => 60)
Category.create(:public_id => 63, :name => "fetichiste", :root => 60)
Category.create(:public_id => 69, :name => "autres", :root => 60)
So if root = 0 so it's a parent category. If root > 0the category is a child from the root value
My Categorie_Controller show action. The problem is that categories got the same name like 'Nature -> Others' and 'Portrait -> Others'. So my find_by_name doesn't work properly
def show
if request.get?
#photographs = Category.find_by_name(params[:name]).photographs
end
end
Is-it possible to do what I want with my routes system ?
Don't pick the same name for the param variables.
# config/routes.rb
get '/category/:name(/:child_name)', to: 'categories#show'
# app/controllers/categories_controller.rb
def show
# Now params[:name] and params[:child_name] are available
# BTW: Only get requests will be routed anyways with your routes definition
#photographs = if params[:child_name].present?
parent = Category.find_by!(name: params[:name])
Category.find_by!(name: params[:child_name], root: parent.id)
else
Category.find_by!(name: params[:name])
end
end
Hope these hints help.
Additionally, you can see your incoming params by raising them in the controller action:
raise params.inspect

Rails: update mutiple attribute of multiple model concurrently

I want to update values taken from a single form in two different model at the same time, I have written the following code to do so :-
if #mess.update_attributes!(:mess_name => params[:mess_name_update], :mess_capacity => params[:mess_capacity_update]) && #mess_price.update_attributes!(:breakfast_charge => params[:mess_breakfast_charge_update], :lunch_charge => params[:mess_lunch_charge_update], :dinner_charge => params[:mess_dinner_charge_update], :monthly_charge => params[:mess_monthly_charge_update], :semesterly_charge => params[:mess_semesterly_charge_update], :start_date => params[:start_date_update], :end_date => params[:end_date_update], :rebate => params[:rebate_update])
flash[:success] = "Mess Details Updated Successfully!!"
else
flash[:error] = "Some Error! Please Try Again!"
end
But the above code is giving following error
ActiveRecord::RecordInvalid
Validation failed: Start date can't be blank
Following is the two schema I am using, for #mess its MessType model and for #mess_price its MessPrice model:
MessType
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| mess_id | int(11) | NO | PRI | NULL | auto_increment |
| mess_name | varchar(255) | NO | | NULL | |
| mess_capacity | int(11) | NO | | NULL | |
| start_date | date | No | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
MessPrice
+-------------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| breakfast_charge | float | YES | | NULL | |
| lunch_charge | float | YES | | NULL | |
| dinner_charge | float | YES | | NULL | |
| monthly_charge | float | YES | | NULL | |
| semesterly_charge | float | YES | | NULL | |
| rebate | float | YES | | NULL | |
| start_date | date | YES | | NULL | |
| end_date | date | YES | | NULL | |
| mess_id | int(11) | YES | MUL | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+-------------------+----------+------+-----+---------+----------------+
I recommend installing the awesome_print gem - https://github.com/michaeldv/awesome_print
# add to Gemfile
gem 'awesome_print'
# install
bundle
Then the first thing in your controller action do
logger.debug " -----------"
logger.ap params
logger.debug " -----------"
Check your log file log/development.log for the output, it could be the params are coming across correctly but not what you expect?
some of the attributes might be nested in another hash key and need to be accessed via params[:something][:xyz]
I would also recommend making the code more readable and running it in a transaction
#mess.mess_name = params[:mess_name_update]
#mess.mess_capacity = params[:mess_capacity_update]
#mess_price.breakfast_charge = params[:mess_breakfast_charge_update]
#mess_price.lunch_charge = params[:mess_lunch_charge_update]
#mess_price.dinner_charge = params[:mess_dinner_charge_update]
#mess_price.monthly_charge = params[:mess_monthly_charge_update]
#mess_price.semesterly_charge = params[:mess_semesterly_charge_update]
#mess_price.start_date = params[:start_date_update]
#mess_price.end_date = params[:end_date_update]
#mess_price.rebate = params[:rebate_update]
# NOTE: an alternative to above is to name your html input fields the rails way
# so that params are sent in a nested hash, i.e. "mess_price[start_date]" -> params[:mess_price][:start_date]
# then you can do #mess_price.update_attributes(params[:mess_price])
# using form_for html helper will automatically apply this style of naming to html input fields
Mess.transaction do
# you might want save! vs save - depends if you show validation error in the UI or not
if #mess.save && #mess_price.save
flash[:success] = "Mess Details Updated Successfully!!"
else
# don't save changes, show validation errors
raise ActiveRecord::Rollback
flash[:error] = "Some Error! Please Try Again!"
end
end

Resources