I don't know my heading title good or bed because I'm new in ruby on rails, I'm troubling one conditional issue like below example.
I have three table like user, post & saved_post
user table
user_id | user_name |
---------------------
1 | ABC |
---------------------
2 | efg |
post table
post_id | title |
--------------------
1 | XYZ |
--------------------
2 | xyz |
saved_post table
id | user_id | post_id |
-----------------------------
1 | 1 | 2 |
View
<% #post.each do |p| %>
<%= p.post_title %>
<%= form_for :create, url: home_path(#save), action: :create, method: :post do |f| %>
<%= f.hidden_field :post_id, :value => p.post_id %>
<button class="btn btn-default btn-save" type="submit">Save</button>
<% end %>
<% end %>
If user_id 1 save post_id 2 in the saved_post table then show this post
saved only for user_id 1, otherwise show save.
How can I reach this solution?
You can try has_many :through Association which Active Record have.
Refer this link.
class Users < ActiveRecord::Base
has_many :posts
has_many :saved_posts, through: :posts
end
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :saved_post
end
class SavedPost < ActiveRecord::Base
has_many :posts
has_many :users, through: :posts
end
More details regarding this you will find in above link.
Rails is all about convention over configuration. Meaning if you write your Rails applications following Rails conventions, you'll have huge benefit from it.
Your tables should be named in plural form. Tables and Posts. What I understood from your comments is that user has many posts and posts can belong to many users. This is typical has_and_belongs_to_many association.
If you rename your saved_post table as posts_users (both table names in alphabetical order) Rails will know how to deal with these tables automatically.
Database should look like this:
I made a sample application with your two user and methods to add posts to either of those users.
# routes.rb
root 'posts#index'
resources :posts
# posts_controller.rb
class PostsController < ApplicationController
before_action :set_user
def index
#posts = #current_user.posts
end
def new
#post = #current_user.posts.build(title: 'totally new title')
end
def edit
#post = Post.find(params[:id])
end
def create
#post = Post.new(post_params)
#post.save
redirect_to posts_path
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
redirect_to posts_path
else
render 'edit'
end
end
# --------------------------------------------------------------------------
private
# --------------------------------------------------------------------------
# Sets the user based on the params value
def set_user
if params[:user_id]
#current_user = User.find(params[:user_id])
else
# If not found, sets the first from the Users table
#current_user = User.first
end
end
def post_params
params.require(:post).permit(:title, {user_ids: []})
end
end
index
# index.html.erb
<h3>Users</h3>
<% User.all.each do |user| %>
<%= link_to user.username, posts_path(user_id: user.id) %> <br />
<% end %>
<h3>Posts for the user: <%= #current_user.username %></h3>
<p>
<% #posts.each do |post| %>
<%= link_to post.title, edit_post_path(post) %> <br />
<% end %>
</p>
<p>
<%= link_to 'Create new post', new_post_path %>
</p>
In edit you can choose which users are attached to this post:
# edit.html.erb
<%= render :partial => "post_form", locals: {button_name: 'update'} %>
# _post_form.html.erb
<h3>Post <%= #post.title %> for the user <%= #current_user.username %></h3>
<%= form_for #post do |f| %>
<%= f.text_field :title %> <br />
<p>
<label>
<%= f.collection_check_boxes(:user_ids, User.all, :id, :username) %>
<label><br />
</p>
<p>
<%= f.submit button_name, class: "btn btn-default btn-save" %>
</p>
<% end %>
In post.rb and user.rb files you need to specify association between these two classes. And when you have posts_users table named correctly, Rails finds it automatically.
# post.rb
class Post < ActiveRecord::Base
has_and_belongs_to_many :users
end
# user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :posts
end
And if you create a new title, if will use the same form:
# new.html.erb
<%= render :partial => "post_form", locals: {button_name: 'create'} %>
Related
My rails app has a games model, and each game has multiple players. When a game is created, a set number of players are created with a default name like so:
def create
#game = Game.new(game_params)
#game.player_number.times do
#game.players << Player.new(name: 'Santa')
end
if #game.save
redirect_to action: "players", id: #game.id
else
render 'new'
end
end
The redirect takes the user to a page that has a form with inputs for each player's name. The actions associated with this page are:
def players
#game = Game.find(params[:id])
end
def playersUpdate
#game = Game.find(params[:id])
puts player_params
if #game.players.update(player_params)
redirect_to #game
else
render 'players'
end
end
private
def player_params
params.require(players: [:name])
end
The editing page itself is:
<h2> Edit Players </h2>
<%= form_tag({:action => 'playersUpdate'},{:id => #game.id}) do %>
<%= #game.players.count %>
<% #game.players.each.with_index do |player,index| %>
<%= fields_for "players[#{index}]", player do |pl| %>
<div>
<%= pl.label :name %><br>
<%= pl.text_field :name %><br>
<%= pl.hidden_field :id %>
</div>
<% end %>
<% end %>
<div>
<%= submit_tag %>
</div>
<% end %>
Here's the routes.rb:
Rails.application.routes.draw do
get 'welcome/index'
resources :games do
collection do
match "/:id/players" => "games#players", :via => :get
match "/:id/players" => "games#playersUpdate", :via => :post
end
end
root 'welcome#index'
end
I get an error:
param is missing or the value is empty: {:players=>[:name]}
And I'm at a loss for what I could be missing. Any tips?
Here are the parameters being passed in, George is the name I'm trying to edit in, all others default to 'Santa':
Processing by GamesController#playersUpdate as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wNwt9v2ckO/Bl8YGr/a2CDCjSsRec30E51VjZ/Qv2i5BgEnzVbH5M9DsrVfCxdLusS4Ue6Mq+aPSFOiA4K5jJg==", "players"=>{"0"=>{"name"=>"George", "id"=>"122"}, "1"=>{"name"=>"Santa", "id"=>"123"}, "2"=>{"name"=>"Santa", "id"=>"124"}, "3"=>{"name"=>"Santa", "id"=>"125"}}, "commit"=>"Save changes", "id"=>"22"}
You are not breaking any new ground here, and Rails has standard ways to do all of this. But it's easy to get "off the Rails" and make it harder than it needs to be.
Conceptually, stop thinking about updating a bunch of Players, and start thinking about updating a Game that happens to have some Players. The docs are surprisingly helpful here.
Let's go first to your Game model. You'll need to tell it that it's OK to update nested attributes for players, like this:
# models/game.rb
model Game < ApplicationRecord
has_many :players
accepts_nested_attributes_for :players
end
Your view is generating parameters that are not quite standard. Again, let Rails do the work for you. You don't need hidden fields or each_with_index. Since we're in Rails 5, let's use the new form_with helper, and we'll let fields_for do its job without our trying to tell it how to index:
# views/games/edit_players.html.erb
<h2> Edit Players </h2>
<%= form_with(model: game, local: true) do |form| %>
<div>
Game name: <%= form.text_field :name %>
</div>
<%= form.fields_for :players do |player_fields| %>
<div>
Player name: <%= player_fields.text_field :name %><br>
</div>
<% end %>
<div>
<%= form.submit %>
</div>
<% end %>
This will generate params that look something like this:
Parameters: {"game"=>
{"name"=>"Risk",
"players_attributes"=>
{"0"=>{"name"=>"Abel", "id"=>"1"},
"1"=>{"name"=>"Baker", "id"=>"2"},
"2"=>{"name"=>"Charlie", "id"=>"3"}}},
"commit"=>"Update Game",
"id"=>"1"}
Now you don't even need a custom update endpoint. Just use your standard GamesController#update action:
# controllers/games_controller.rb
class GamesController < ApplicationController
...
def edit_players
#game = Game.find(params[:id])
end
def update
#game = Game.find(params[:id])
if #game.update(game_params)
redirect_to #game
else
render :edit
end
end
private
def game_params
params.require(:game).permit(:name, players_attributes: [:id, :name])
end
end
Finally, your routes file is confusing because you are using collection (which doesn't expect an :id) instead of member. The routes file should look something like this:
# routes.rb
Rails.application.routes.draw do
resources :players
resources :games do
member { get :edit_players }
end
end
First of all I have this:
https://polar-scrubland-30279.herokuapp.com/ - my project which is deployed on heroku (Captain Obvious)
I've got projects and todos inside them.
For this moment I show all projects using this way:
------index.html.erb------
<%= render #projects %>
------_project.html.erb-----
<div class="project">
<div class="project-header">
<h2><%= project.title %></h2>
</div>
<div class="project-todos">
<% project.todos.all.each do |todo| %>
<p><%= check_box('tag', todo.__id__, {class: 'icheckbox_square-blue', checked: todo.isCompleted}) %> <%= content_tag :todotext, todo.text %></p>
<% end %>
</div>
</div>
And as you understand it doesn't allow me to change my todo's status when checkbox is checked. So that's why I need a form that will allow me to track all the checkboxes. Also I wanna make text-decoration: line-through when checkbox is pressed, but don't get how to.
Is there a way to creat a form which will satisfy my needs? Please can you help me, Any information will be appreciated.
ADDITIONAL INFORAMTION:
GitHub - https://github.com/NanoBreaker/taskmanager
project.rb
class Project < ActiveRecord::Base
has_many :todos
end
todo.rb
class Todo < ActiveRecord::Base
belongs_to :project
end
Lets start with the models:
class Project < ApplicationRecord
has_many :todos
accepts_nested_attributes_for :todos
end
class Todo < ApplicationRecord
belongs_to :project
end
accepts_nested_attributes_for lets you create or modify several nested Todo records at once when creating or updating a Project.
# will update 2 todos at once
#project.update(
todos_attributes: [ { id: 1, isComplete: true }, { id: 2, isComplete: false }]
)
We can use fields_for to create nested inputs for todos:
<%= f.form_for(#project) do |f| %>
<%= f.fields_for(:todos) do |tf| %>
<%= tf.check_box :isCompleted %>
<% end %>
<% end %>
This generates fields for todos nested under the key todos_attributes. We can whitelist them by using a hash key containing a array of permitted attributes.
class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
def new
#project = Project.new
# this seeds the project with 3 empty tasks
# otherwise we don't have any inputs.
3.times { #project.todos.new }
end
def create
#project = Project.new(project_params)
if #project.save
# ...
else
# ...
end
end
def update
if #project.update(project_params)
# ...
else
# ...
end
end
private
def set_project
#project = Project.find(params[:id])
end
def project_params
params.require(:project)
.permit(:foo, :bar,
todos_attributes: [:isCompleted, :text]
)
end
end
You can create a form for each project by creating a partial which uses a local instead of an instance variable:
# app/views/projects/_form.html.erb
<%= f.form_for(local_assigns[:project] || #project) do |f| %>
<%= f.fields_for(:todos) do |tf| %>
<%= tf.check_box :isCompleted %>
<% end %>
<% end %>
# app/views/projects/index.html.erb
<% #projects.each do |project| %>
<%= render partial: 'projects/form', project: project %>
<% end %>
You can reuse the same partial for the other views as well:
# app/views/projects/new.html.erb
<%= render partial: 'projects/form' %>
# app/views/projects/edit.html.erb
<%= render partial: 'projects/form' %>
Within my Ruby on Rails application I am trying to implement a relationship between Group and Contact, whereby one group can contain many contacts and one contact can be part of many groups. I am using a model called Contactgroup to deal with this relationship, and so the tables are:
Group (id, name)
Contact (id, firstname, surname)
Contactgroup (group_id, contact_id)
With example data being:
Groups:
ID Name
1 Singers
2 Drummers
Contacts:
ID Firstname Surname
1 Freddy Mercury
2 Roger Taylor
3 Kurt Cobain
4 Dave Grohl
Contact Groups:
Group_ID Contact_ID
1 1
1 3
1 4
2 2
2 4
What I am trying to do is get it so that when a user creates a group, they can select the contacts that they want to add to that group. This means that there is the group form, whereby the user types the group name, and on this form I want to display checkboxes for each of the user's contacts so that the user can select the contacts they want to add to the group, and when they click submit the new group will be saved in the Group table and the new contact group records will be saved in the Contactgroup table.
This is the app/views/groups/_form.html.erb code:
<%= form_for #group do |f| %>
<% if #group.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#group.errors.count, "error") %> prohibited this group from being saved:
</h2>
<ul>
<% #group.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<h2>Add members:</h2>
<%= form_for([#group, #group.contactgroups.build]) do |f| %>
<p>
<%= f.collection_check_boxes(:contact_id, #contacts, :id, :firstname) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<p>
<%= f.submit %>
</p>
<% end %>
On here you can see the code I am trying to use to do this:
<h2>Add members:</h2>
<%= form_for([#group, #group.contactgroups.build]) do |f| %>
<p>
<%= f.collection_check_boxes(:contact_id, #contacts, :id, :firstname) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<p>
<%= f.submit %>
</p>
<% end %>
I have got this from rails guides (http://guides.rubyonrails.org/getting_started.html) but I get the error undefined methodcontactgroups' for #` and don't think this will give me what I want.
My routes file is:
Rails.application.routes.draw do
get 'sessions/new'
get 'sessions/create'
get 'sessions/destroy'
resources :users
get 'welcome/index'
root 'welcome#index'
resources :contacts
resources :groups do
resources :contactgroups
end
resources :contactgroups
get 'sessions/new'
get 'sessions/create'
get 'sessions/destroy'
controller :sessions do
get 'login' => :new
post 'login' => :create
get 'logout' => :destroy
end
end
My groups_controller:
class GroupsController < ApplicationController
def index
#groups = Group.where(user_id: session[:user_id])
end
def show
#group = Group.find(params[:id])
#members = Contactgroup.where(group_id: #group.id)
end
def new
#group = Group.new
#contacts = Contact.where(user_id: session[:user_id])
end
def edit
#group = Group.find(params[:id])
end
def create
#group = Group.new(group_params)
#group.user_id = session[:user_id]
if #group.save
redirect_to #group
else
render 'new'
end
end
def update
#group = Group.find(params[:id])
if #group.update(group_params)
redirect_to #group
else
render 'edit'
end
end
def destroy
#group = Group.find(params[:id])
#group.destroy
redirect_to groups_path
end
private
def group_params
params.require(:group).permit(:name, :user_id)
end
end
And contactgroups_controller:
class ContactgroupsController < ApplicationController
def destroy
#contactgroup = Contactgroup.find(params[:id])
#contactgroup.destroy
redirect_to(:back)
end
end
My models are as follows:
Contact.rb:
class Contact < ActiveRecord::Base
end
Group.rb:
class Group < ActiveRecord::Base
end
Contactgroup.rb:
class Contactgroup < ActiveRecord::Base
belongs_to :contact
belongs_to :group
end
There must be a simple solution to solve this as I assume it is commonly done on other systems, but I am not sure how to do this.
Can someone please help.
You cannot use form inside form. The correct way to use collection_check_boxes is following.
Replace
<%= form_for([#group, #group.contactgroups.build]) do |f| %>
<p>
<%= f.collection_check_boxes(:contact_id, #contacts, :id, :firstname) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
With just
<p>
<%= f.collection_check_boxes(:contact_ids, #contacts, :id, :firstname) %>
</p>
This was much simpler than initially thought/suggested.
What I needed to do was change the models to:
Contactgroup
belongs_to :contact
belongs_to :group
Contact
has_many :contactgroups
has_many :groups, through: :contactgroups, :dependent => :destroy
Group
has_many :contactgroups
has_many :contacts, through: :contactgroups, :dependent => :destroy
In the groups_controller I needed to change the new method and params to:
def new
#group = Group.new
#group.contactgroups.build
end
private
def group_params
params.require(:group).permit(:name, :user_id, { contact_ids: [] })
end
And then add the following line of code into app/views/groups/_form.html.erb:
<%= f.collection_check_boxes :contact_ids, Contact.where(user_id: session[:user_id]), :id, :firstname ,{ prompt: "firstname" } %>
This provides me with a checkbox for each contact, and allows contactgroup records to be created from the group form.
Ok so the issue is very simple. You are calling #group.contactgroups but you haven't actually set up that association on the group model yet. only have associations set up from the contactgroup side. So you can do contactgroup.group but not group.contactgroups
Your best bet is to actually model this as habtm - as I mentioned earlier. This is how you'd do that:
Contact.rb:
class Contact < ActiveRecord::Base
has_and_belongs_to_many :groups
end
Group.rb:
class Group < ActiveRecord::Base
has_and_belongs_to_many :contacts
end
Note: you still have the concept of the contact-group for HABTM but using Rails standard naming it would be in your database as the contacts_groups table. Then you could build your forms that way.
With a quick google, here's a S/O question on using checkboxes with HABTM (haven't vetted it for usefulness to your situation): Rails 4 - checkboxes for has_and_belongs_to_many association
Using HABTM is Rails standard practice for lots of very good reasons. It really does actually fit your situation (honest!) and it does not actually break the requirement you have of wanting to see it in the SQL (seriously!).
Give it a try first :)
I can tell you how to break Rails conventions... but it's generally well-understood that you shouldn't break conventions until you know what the conventions are there for.
I have been trying to fix an error associated with using the Ancestry gem for comments on my app for Rails 4. I used railscast episode 262 as a guide. However, unlike the episode, my comments model is a nested resource inside another model.Before I go further, I will supply the necessary code for reference. If you like to read the error right away, it is mentioned right after all the code snippets.
The Relevant Models:
class Comment < ActiveRecord::Base
has_ancestry
belongs_to :user
belongs_to :scoreboard
end
class Scoreboard < ActiveRecord::Base
#scoreboard model is like an article page on which users can post comments
belongs_to :user
has_many :teams, dependent: :destroy
has_many :comments, dependent: :destroy
end
Relevant code in the route file:
resources :scoreboards do
resources :comments
resources :teams, only: [:edit, :create, :destroy, :update]
end
The Scoreboards Controller Method for the page on which one can post comments:
def show
#scoreboard = Scoreboard.find_by_id(params[:id])
#team = #scoreboard.teams.build
#comment = #scoreboard.comments.new
end
The Comments Controller:
class CommentsController < ApplicationController
def new
#scoreboard = Scoreboard.find(params[:scoreboard_id])
#comment = #scoreboard.comments.new(:parent_id => params[:parent_id])
end
def create
#scoreboard = Scoreboard.find(params[:scoreboard_id])
#comment = #scoreboard.comments.new comment_params
if #comment.save
redirect_to scoreboard_url(#comment.scoreboard_id)
else
render 'new'
end
end
private
def comment_params
params.require(:comment).permit(:body, :parent_id).merge(user_id: current_user.id)
end
end
I will include the migration for the ancestry gem if any mistakes were made on that :
class AddAncestryToComments < ActiveRecord::Migration
def change
add_column :comments, :ancestry, :string
add_index :comments, :ancestry
end
end
The following code shows the view code:
Scoreboard#show View which is giving me the error in the last line:
<div class= "comment-section">
<%= form_for [#scoreboard, #comment] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.text_area :body, class: "comment-field" %>
<%= f.hidden_field :parent_id %> #is it needed to include this here? because this form is for new comments not replies
<%= f.submit "Join the discussion...", class: " comment-button btn btn-primary" %>
<% end %>
<%= nested_comments #scoreboard.comments.reject(&:new_record?).arrange(:order => :created_at) %>
</div>
The (comments partial)_comment.html.erb View:
<div class=" comment-div">
<p> Posted by <%= link_to "#{comment.user.name}", comment.user %>
<%= time_ago_in_words(comment.created_at) %> ago
</p>
<div class="comment-body">
<%= comment.body %>
<%= link_to "Reply", new_scoreboard_comment_path(#scoreboard, comment, :parent_id => comment) %>
</div>
</div>
The helper method to render comments:
def nested_comments(comments)
comments.map do |comment, sub_comment| #the comments.map also gives me an error if I choose to render the comments without the .arrange ancestry method
render(comment) + content_tag(:div, nested_comments(sub_comment), class: "nested_messages")
end.join.html_safe
end
The new.html.erb for Comments which one is redirected to for the replies form submission:
<%= form_for [#scoreboard, #comment] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.text_area :body, class: "comment-field" %>
<%= f.hidden_field :parent_id %>
<%= f.submit "Join the discussion...", class: " comment-button btn btn-primary" %>
<% end %>
Upon creating a scoreboard, I am redirected to the show page, where i get the following error:
undefined method `arrange' for []:Array
Even though the array of comments is empty, I get the same error if it wasnt. I have tried .subtree.arrange but that gives me the same error. Also, the ancestry documentation said that .arrange works on scoped classes only. I don't know what that means. I would appreciate some help on making the page work so the comments show properly ordered with the replies after their parent comments. If this is the wrong approach for threaded comments(replies and all), I would appreciate some guidance on what to research next.
.reject(&:new_record?) this will return an array. The error sounds like arrange is a scope on ActiveRecord. So move the reject to the end and it should work.
#scoreboard.comments.arrange(:order => :created_at).reject(&:new_record?)
In regards your comment nesting, I have implemented this before, and found the Railscasts recommendation of a helper to be extremely weak.
Passing parent_id to a comment
Instead, you're better using a partial which becomes recursive depending on the number of children each comment has:
#app/views/scoreboards/show.html.erb
<%= render #comments %>
#app/views/scoreboards/_comment.html.erb
<%= link_to comment.title, comment_path(comment) %>
<div class="nested">
<%= render comment.children if comment.has_children? %>
</div>
I have an app where users can create courses, and each course has_one syllabus. How could I go about configuring my courses and syllabuses (I know it's Syllabi but apparently Rails doesn't) controller, and my routes, so on a course's page there is a link to create or show the course's syllabus, and a link back to the course from the show syllabus page?
In my routes I have:
resources :courses do
resources :syllabuses
member do
put :enroll #this is so users can enroll in the course
end
end
Currently , so the course_id will be saved in the syllabus table in my courses_controller, I have:
def create_syllabus
#course = Course.find(params[:id])
#syllabus = #course.build_syllabus(params[:syllabus])
if #syllabus.save
redirect_to #syllabus, notice: "Successfully created syllabus."
else
render :new
end
end
then in my courses show page I have:
<section>
<% if (current_user.courses.includes(#course) ||
current_user.coursegroups.find_by_course_id_and_role(#course.id, "admin")) %>
<%= render 'create_syllabus' %>
<% end %>
</section>
then in my create_syllabus form (in my courses views folder) I have tried starting it off with:
# I have #course = Course.find(params[:id]) defined in show in the
#courses_controller
<%= form_for #course.create_syllabus do |f| %>
<%= form_for #course.syllabus.create_syllabus do |f| %>
<%= form_for #course.syllabus.create do |f| %>
and I get an undefined method error for each of those.
If you want to create a new syllabus in your show action of a specific course, you can add this to your controllers and views:
courses_controller.rb
#course = Course.find(params[:id])
# Build a new #syllabus object, only if there is none for the current course
unless #course.syllabus
#syllabus = #course.build_syllabus
end
views/courses/show.html.erb
# Show the syllabus name if there is one, or show the form to create a new one
<% if #course.syllabus.name %>
<p>Syllabus: <%= #course.syllabus.name %></p>
<% else %>
<p>Create Syllabus:</p>
<%= form_for([#course, #syllabus]) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
syllabuses_controller.rb
def create
#course = Course.find(params[:course_id])
# Build new syllabus object based on form input
#syllabus = #course.build_syllabus(params[:syllabus])
if #syllabus.save
# redirect to /course/:id
redirect_to #course, notice: 'Syllabus was successfully created.' }
end
end
course.rb
class Course < ActiveRecord::Base
attr_accessible :name
has_one :syllabus
end
syllabus.rb
class Syllabus < ActiveRecord::Base
belongs_to :course
attr_accessible :name, :course_id
end
Some things that I left out but you should still include:
validations
rerendering form if something goes wrong
pulling things out into partials
fixing bad code like if #course.syllabus.name
pull out if/else logic into a helper
…