How to set some default values in a column in rails - ruby-on-rails

I'm developing an 'expense manager' app which helps the users to manage their expenses and generate reports with Graphs and also they can get the expenses sorted by date or by period of time.
A user can login add expenses and select a category for each expense from a dropdown.
Upto here everything went well, But I was stuck with a doubt if there is any possibility to add some default categories in the categories table when the user sign up. I also have a requirement for the user to delete these default categories which should not effect other users categories.
Please suggest me an idea how we can deal with this requirement instead of using Seed data.
Migration for creating categories
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.string :name
t.timestamps null: false
end
end
end
Category drop down in expense new form
<div class="form-group">
<%= f.label :category, "Category:" %><br>
<div class="col-md-2">
<%= f.collection_select(:category_id, current_user.categories, :id, :name, {}, { :class => "select_box selectpicker picker"}) %>
</div>
</div>
Git repository of this app: https://github.com/atchyut-re/expense_manager
Hope I'm clear if I need to give any further details please mention in comment.

Create a after_create callback in your user model to create some categories. As the categories are user dependent, then there should be an association between user & categories.

You can simply use rails call back to create the default categories for every user, the code will be like:
class User < ActiveRecord::Base
before_create :create_default_categories
DEFAULT_CATEGORIES = [
{name: 'default name 1', other_attribute: 'default other attribute 1'},
{name: 'default name 2', other_attribute: 'default other attribute 2'}
]
def create_default_categories
DEFAULT_CATEGORIES.each do |default_attrs|
self.categories.build(default_attrs)
end
end
end
So when user was created, the default categories would be created as well!

Related

Rails f.select Save Id an Name at the same time

I have a form with the f.select option. I want to add the Company ID and the Company Name when the company name is selected from the options. Is it possible to add multiple attributes in the f.select line of code? This is how my code looks:
<div class="field">
<%= f.label 'Client' %>
<%= f.select :client_id, Client.all.collect { |c| [ c.companyName, c.id ] } %>
I want to also assign the companyName to my :companyName attribute, but the id is the only thing that is being saved right now.
Thanks.
I think you can use associations for this. You should have 2 models as below.
class Company < ApplicationRecord
has_many :clients
end
class Client < ApplicationRecord
belongs_to :company
end
Your should use variable instead in views for rendering all clients list with this
<%= f.select :client_id, #clients.collect { |client| [ client.name, client.id] } %>
Controller:
#clients = Client.all
On Submit the client_id will be passed to controller. You can then find the company associated with the client and other logic.
client = Client.find(params[:client_id])
company = client.company
# etc ..
In the controller action where your form submits you can write before saving or updating record.
params[:your_object][:companyName]=Client.find_by(id: params[:your_object][:client_id]).companyName
Remember to a add params[:your_object][:companyName] to your strong params. e.g.
params.require(:your_object).permit(:client_id, ... , :companyName)
Before anything be sure your client_id is in same object and permitted and apply same to companyName attribute
Hope This Helps

How do I call the name of a user when they belong to a model

I have two models, Chasing and User, a chasing belongs_to :user and a user has_many :chasings.
I created a migration for linking the two models together:
class AddUsersToChasings < ActiveRecord::Migration
def change
add_reference :chasings, :user, index: true, foreign_key: true
end
end
I have a controller for creating new users which I then want to be able to assign to chasings. I currently have this code in my chasings form for selecting the user:
<%= f.select :user_id, options_for_select(User.all.map {|c| [c.name, c.id]}), { :include_blank => "Please select user"}, {:class => "form-control"} %>
This seems to do the trick, after calling Chasing.first in rails console I can see the chasing now has user_id relevant to the user I picked. I can also run Chasing.first.user.name to give me the name of the user who is associated with the chasing. I'm wanting to show this name in my index view, the code I currently have for this is:
ChasingsController:
def index
#chasing = Chasing.all
end
Index view:
<% #chasing.each do |chasing| %>
<%= chasing.user %>
<% end %>
This shows a random string (seems to change every time I update a chasing - #<User:0xf5b0ba8> for example). when I change this to chasing.user.name I get 'undefined method `name' for nil:NilClass'.
Is there a way I can call the name for my view?
EDIT:
As per NickM's comment below I had chasings without users assigned to them causing active record to throw the error.
Looks like you have some Chasing objects in your database without user_ids. You can test by doing <%= chasing.user.name if chasing.user %>

Ruby on Rails Form for Calculating Dice Rolls

I am creating a web application as a training project that will take three inputs (Integer values for number of dice, number of sides and number of rolls) and input that into a series of tables that will facilitate calculations and the output of the results, and the saving of historical data (past rolls.)
I'm stuck.
Here is my ERB for the form:
<%= form_for(#run) do |f| %>
How many dice: <%= f.number_field :die_count, :placeholder => "# of dice" %><br>
How many sides: <%= f.number_field :die_sides, :placeholder => "# of sides" %><br>
How many rolls: <%= f.number_field :rolls, :placeholder => "# of rolls" %><br>
<%= f.submit "Roll!" %>
<% end %>
Here's my Model:
class Run < ActiveRecord::Base
has_many :rolls
belongs_to :user
validates_presence_of :die_count, :rolls, :die_sides
validates_numericality_of :die_count, :die_sides, :rolls
end
Here's my pertinent Controller info:
def new
#run = Run.new
end
def create
#run = Run.new(run_params)
end
private
def run_params
params.require(:run).permit(:die_count, :die_sides, :rolls)
end
For good measure, here's the migrate for making my DB table:
class CreateRuns < ActiveRecord::Migration
def change
create_table :runs do |t|
t.integer :die_count
t.integer :die_sides
t.integer :roll_count
t.timestamps null: false
end
end
end
At this point, I just want it to create a new record in the Run model. Here's the error I'm getting with the input of 5, 5, and 5 into the number_fields and click my submit button:
If I am reading this correctly, my application wants to iterate through the individual numbers as if they were arrays, but it can't because they are strings. This confuses me because they aren't strings in the first place. They are integers.
Pulling my hair out on this one.
:rolls is a reference to another model called Roll (have you created it?).
:roll_count is the attribute of your Run model that defines the number of rolls (as visible in your migration table).
They are two very different things, even though it stands to reason that :roll_count should in theory be equal to the number of Roll records your Run record 'owns'.
In your form, replace :rolls by :roll_count. Do the same in the run_params method in your controller. And also in the two validations in your model. (checklist: that's 4 places where you need to modify that symbol name).
In your controller, also change the content of your create method to #run = Run.create(run_params).
Edited (clarity): Run.new(params) creates a new instance of a Run object but doesn't save it in your DB. Run.create(params) creates the object AND saves it.
Finally, in your model, comment out the has_many :rolls until you have actually implemented the Roll model (no pun intended!) ; do the same for belongs_to :user if the User model is not implemented either.
After these changes, your form should normally work and data should be saved in your runs database table.
I believe you meant to replace rolls with roll_count everywhere in your code.
How many rolls: <%= f.number_field :roll_count, :placeholder => "# of rolls" %><br>
and
validates_presence_of :die_count, :roll_count, :die_sides
validates_numericality_of :die_count, :die_sides, :roll_count
and
def run_params
params.require(:run).permit(:die_count, :die_sides, :roll_count)
end

ruby on rails how to use FormOptionHelpers to create dynamic drop down list

I have checked some tutorials but I got confused by the parameters in this method
collection_select (object, attribute, collection, value_method, text_method, options = {}, html_options ={})
I have a map model includes: :area, :system, :file
and I want to read :area from database to a drop down list, and let user choose one
I already did #map = Map.all in the view
what the method should be?
especially the parameter "attribute". In a lot tutorials, people put "id" here. But I don't know what "id" is, and in my situation I don't need any other value, just the "area".
Im not exactly sure what you are asking here but if you are trying to make a dropdown selection for use in an html form will this example help you at all?
<% nations = {'United States of America' => 'USA', 'Canada' => 'Canada', 'Mexico' => 'Mexico', 'United Kingdom'=> 'UK'} %>
<% list = nations.sort %>
<%= f.select :country, list, %>
Here nations is a hash of countries then list becomes the sorted copy of that hash. An html dropdown is then created as a part of the form "f". ":country" is the part of the model that the data is connected to while list is the options to populate the dropdown with
It's not clear from your question what the model is that's being populated with the area.
Typically, collection_select is used between related models.
eg.
class Category < ActiveRecord::Base
has_many :products
end
class Product < ActiveRecord::Base
belongs_to :category
end
When selecting the 'category' for a product, your view would have something like:
<%= f.collection_select(:category_id, :id, Category.all, :name, include_blank: true) %>
What this does is specify the Product.category_id as the attribute being populated with the value of Category.id. The values come from the Category.all collection, and with Category.name being the item displayed in the select. The last (optional) parameter says to include a blank entry.
Something like the following is probably what you need:
<%= f.collection_select(:map_id, :id, #map, :area) %>
However, if the model you're trying to populate has an area attribute (instead of an ID linking to the map), you might need to use:
<%= f.collection_select(:area, :area, #map, :area) %>
This specifies that the area attribute of the receiving table will be populated with Map's area attribute, which is also being used as the "description" in the select.

rails form - checkboxes, FK and datetime -> how to store those attributes in the db?

(rails 2.2.2)
I have 2 models, user and subscription. Each user can have one ore more subscriptions (= premium services). Below the attributes:
user: id, username, ...
subscription: id, user_id (FK), type, started_at, ended_at
The classes:
class User < ActiveRecord::Base
..
has_many :subscriptions, :dependent => :destroy
..
end
class Subscription < ActiveRecord::Base
belongs_to :user, :foreign_key => :user_id
end
Now I want to make the UI part where existing users can subscribe in their account for the premium services. Therefore I wanted to make a first simple version where the user can subscribe by clicking on a checkbox. This is what I get so far
<div class = 'wrapper'>
<%= render :partial => "my_account_leftbar" %>
<% form_for #subscription, :url => subscribe_user_path(current_user) do |f| %>
<div class="field">
<%= (f.check_box :type?) %> <!-- add '?'after the symbol, source: https://github.com/justinfrench/formtastic/issues/269 -->
</div>
<div class="actions">
<%= f.submit "Subscribe", :class => "button mr8" %>
</div>
<% end %>
</div>
Problems:
the app inserts a record into the db, but the attribute I defined in the form (type) has not been set (it should set '1' which stands for 'standard subscription') . How to get the app set this attribute?
how to set the FK? I assume that rails should set the FK automatically, is that assumption correct?
how to set the other values 'started_at' and 'ended_at? Those are datetime(timestamp) values...
Just run out of my beginner rails knowledge, any help really appreciated...
'Type' is a ruby on rails reserved word which should only be used when you are using Single Table Inheritance. You should rename your column name to something else.
I could solve the other questions 2 and 3 as well, wrapping it up:
insert the record: as stated in the answer from Wahaj, renaming the column 'type' into e.g. 'subscription_type' helped. I created a seperate migration as described here: How can I rename a database column in a Ruby on Rails migration?
storing the FK: updated the action in the controller. Instead of just writing
#subscription = Subscription.new(params[:subscription])
I wrote the following method to create a 'user's subscription'
#subscription = current_user.subscriptions.build(params[:subscription])
storing the 'started_at': added a method to the controller:
#subscription.update_attributes(:started_at => Time.zone.now)

Resources