How do i check if my user is admin in rails? - ruby-on-rails

User has many profiles such has admin and merchant etc in my rails db schema. Now how do i write code to check if current user is admin ?
More info : User table is separate and profile table is separate. They are linked in user model through has_and_belongs_to_many :profiles
Here is my schema :
create_table "profiles", force: true do |t|
t.string "name", null: false
t.string "description"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "profiles", ["name"], name: "index_profiles_on_name", unique: true, using: :btree
create_table "profiles_roles", id: false, force: true do |t|
t.integer "profile_id"
t.integer "role_id"
end
create_table "profiles_users", id: false, force: true do |t|
t.integer "profile_id"
t.integer "user_id"
end
create_table "role_types", force: true do |t|
t.string "name"
t.string "description"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "roles", force: true do |t|
t.string "name", null: false
t.string "description"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "role_type_id"
t.string "display_name"
end
add_index "roles", ["name"], name: "index_roles_on_name", unique: true, using: :btree
create_table "users", force: true do |t|
t.string "username", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "email", default: ""
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "first_name"
t.string "last_name"
t.string "msisdn"
t.string "city"
t.string "address"
t.integer "e_bills_count", default: 0
t.string "notification_url"
t.string "notification_params", default: [], array: true
t.boolean "notification_post", default: true
t.string "legal_info"
t.string "greeting_message"
t.boolean "email_notification", default: false
t.string "website"
t.string "logo"
t.string "signature"
t.string "additional_notification_params", default: ""
t.string "currency"
end

There is no single dogmatic 'rails-way' to do this. The simplest way is to add a boolean column 'is_admin'. But because this does not scale to well with other scenarios, this is often widened to a schema where there is an extra 'roles' table and a has_many relationship to the user model.
Thare are also gems for more sophisticated authorization models:
https://github.com/ryanb/cancan/wiki/Role-Based-Authorization
An example implementation could be:
self.profiles.map(&:name).include?('admin')

Related

Rails 4 where clause on nested joined tables

currently I have this query:
Mother.joins(camp: [{ sub_center: [{ health_center: :block }] }])
which essentially joins the mother table to the block table through the camp, sub_center, and health_center tables (I know it's a lot to take). I want to be able to do something like this:
Mother.joins(camp: [{ sub_center: [{ health_center: :block }] }]).where(sub_center_id: 1)
However, I get that sub_center_id is an undefined column PG::UndefinedColumn: ERROR: column mothers.sub_center_id does not exist
How do I get it to query camp.sub_center_id instead of mother.sub_center_id? In other words, how do I execute a where clause on nested joined tables?
Here's the schema for given tables:
create_table "mothers", force: :cascade do |t|
t.integer "camp_id"
t.integer "eligible_couple_id"
t.string "pcts_id"
t.integer "thumb_id"
t.string "survey_id"
t.string "necklace_id"
t.integer "necklace_replacement_number", default: 0
t.boolean "facility_referral_true", default: false
t.float "weight_at_las_pnc"
t.integer "created_by"
t.integer "updated_by"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "reg_id"
t.string "nfc_data"
t.datetime "date_of_registration"
t.integer "status", default: 1, null: false
t.datetime "deleted_at"
t.datetime "completed_at"
end
create_table "camps", force: :cascade do |t|
t.string "english_name"
t.string "local_name"
t.float "latitude"
t.float "longitude"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "created_by"
t.integer "updated_by"
t.integer "sub_center_id"
t.integer "week_of_the_month"
t.integer "status", default: 1
t.integer "day"
t.datetime "deleted_at"
end
create_table "health_centers", force: :cascade do |t|
t.integer "block_id"
t.string "english_name"
t.string "local_name"
t.boolean "phc_true", default: false
t.boolean "ipd_true", default: false
t.boolean "fru_true", default: false
t.boolean "always_open_true", default: false
t.string "phone_number"
t.integer "created_by"
t.integer "updated_by"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 1
t.datetime "deleted_at"
end
create_table "sub_centers", force: :cascade do |t|
t.integer "health_center_id"
t.string "english_name"
t.string "local_name"
t.boolean "phc_true", default: false
t.boolean "ipd_true", default: false
t.boolean "fru_true", default: false
t.boolean "always_open_true", default: false
t.string "phone_number"
t.float "latitude"
t.float "longitude"
t.integer "created_by"
t.integer "updated_by"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 1
t.datetime "deleted_at"
end
create_table "blocks", force: :cascade do |t|
t.string "english_name"
t.string "local_name"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "created_by"
t.integer "updated_by"
t.integer "status", default: 1
t.datetime "deleted_at"
end
You can always use the string method to reference the column, instead of the symbol one.
Mother.
joins(camp: { sub_center: { health_center: :block } }).
where('camps.sub_center_id = ?', 1)
or with the symbol method
Mother.
joins(camp: { sub_center: { health_center: :block } }).
where(camps: { sub_center_id: 1 } )

Rails join on user column

I'm trying to get all Activities related to users of the same school (a string on the user object), but the error I'm getting is this:
Can't join 'Activity' to association named 'users'; perhaps you
misspelled it?
activity_controller.rb
#school = current_user.school
#bathroom = Activity.includes(:users).where(name: 'Bathroom').where( :user => { :school => #school} )
and the schema:
create_table "activities", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "student_id"
t.string "status"
t.integer "user_id"
t.index ["student_id"], name: "index_activities_on_student_id"
t.index ["user_id"], name: "index_activities_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.string "grade"
t.string "school"
t.integer "maxout"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Not users but user because Activity belongs to User
#bathroom = Activity.includes(:user).where(name: 'Bathroom').where( :users => { :school => #school} )
But User has many activities so User.includes(:activities)
Of course, you have to provide associations:
class Activity
belongs_to :user
class User
has_many :activities

Issue with geocoder using postgresql

I have a model called room and in the show view I want to display other rooms nearby.
show.html.erb
<div>
<% for room in #room.nearbys(10) %>
<%= image_tag room.photos[0].image.url(:medium) %>
<%= link_to room.listing_name, room %><br>
(<%= room.distance.round(2) %> miles away)
<% end %>
</div>
schema.rb
ActiveRecord::Schema.define(version: 20161006135631) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "active_admin_comments", force: :cascade do |t|
t.string "namespace"
t.text "body"
t.string "resource_id", null: false
t.string "resource_type", null: false
t.string "author_type"
t.integer "author_id"
t.datetime "created_at"
t.datetime "updated_at"
t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id", using: :btree
t.index ["namespace"], name: "index_active_admin_comments_on_namespace", using: :btree
t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id", using: :btree
end
create_table "admin_users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_admin_users_on_email", unique: true, using: :btree
t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true, using: :btree
end
create_table "photos", force: :cascade do |t|
t.integer "room_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.index ["room_id"], name: "index_photos_on_room_id", using: :btree
end
create_table "rooms", force: :cascade do |t|
t.string "listing_name"
t.string "accommodation_type"
t.integer "persons"
t.integer "property"
t.integer "living_area"
t.text "rooms_total"
t.text "features_short"
t.string "pets"
t.string "smoking"
t.string "check_in"
t.string "check_out"
t.string "location"
t.text "distance"
t.text "features_long"
t.text "detailed_description"
t.text "house_rules"
t.string "address"
t.text "video"
t.integer "nightly_price"
t.integer "hourly_price"
t.text "detailed_price"
t.boolean "active"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "latitude"
t.float "longitude"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "firstname"
t.string "lastname"
t.string "provider"
t.string "uid"
t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end
add_foreign_key "photos", "rooms"
end
I have used the RailsCasts Episode for orientation.
Unfortunately I am getting this Error:
How can I make this work?
Any hints for a solution are very appreciated!
Your rooms table have column distance.
And your SQL query is creating an alias distance.(AS DISTANCE).
Hence PostgreS is raising ambiguous column error.
This query is generated by gem which you are using I recommend you to change the column name of column distance to something else like my_distance or something which will not conflict with the query generated by gem.

Errors when migrating heroku

Im attempting to rake my migrations on my heroku distro. im getting this error:
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::UndefinedTable: ERROR: relation "plants" does not exist
: ALTER TABLE "images" ADD CONSTRAINT "fk_rails_d5e1aedcb5"
FOREIGN KEY ("plant_id")
REFERENCES "plants" ("id")
Some of my tables go through, but not this one, im not sure what is even going on here. It works in development, but not in production.
Here is my schema file:
ActiveRecord::Schema.define(version: 20160521081000) do
create_table "appointments", force: :cascade do |t|
t.string "task"
t.datetime "time"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
create_table "cycles", force: :cascade do |t|
t.string "title"
t.datetime "completed_at"
t.boolean "completed"
t.integer "tray_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "due_date"
end
add_index "cycles", ["tray_id"], name: "index_cycles_on_tray_id"
create_table "datalogs", force: :cascade do |t|
t.integer "tray_id"
t.float "ambcur"
t.float "ambmin"
t.float "ambmax"
t.float "folcur"
t.float "folmin"
t.float "folmax"
t.float "ph"
t.float "heatmat"
t.float "h202"
t.float "tds"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "datalogs", ["tray_id"], name: "index_datalogs_on_tray_id"
create_table "events", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "grows", force: :cascade do |t|
t.string "title"
t.text "notes"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
t.integer "user_id"
end
create_table "images", force: :cascade do |t|
t.string "file_id"
t.integer "plant_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "tray_id"
end
add_index "images", ["plant_id"], name: "index_images_on_plant_id"
create_table "nutrient_calcs", force: :cascade do |t|
t.string "product"
t.integer "vegtime"
t.integer "flowertime"
t.float "rezsize"
t.string "rezunits"
t.boolean "aerstone"
t.string "outputunits"
t.integer "nutrient_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "nutrient_calcs", ["nutrient_id"], name: "index_nutrient_calcs_on_nutrient_id"
create_table "nutrients", force: :cascade do |t|
t.string "title"
t.string "manufacturer"
t.float "price"
t.string "unit"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "pages", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "pics", force: :cascade do |t|
t.string "title"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "plant_cycles", force: :cascade do |t|
t.string "title"
t.integer "interval"
t.integer "frequency"
t.integer "plant_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "plant_cycles", ["plant_id"], name: "index_plant_cycles_on_plant_id"
create_table "plantdats", force: :cascade do |t|
t.float "ambtemp"
t.float "foltempcur"
t.float "foltempmin"
t.float "foltempmax"
t.float "ph"
t.float "heatmat"
t.integer "tds"
t.float "h202"
t.integer "plant_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "ambtempmin"
t.float "ambtembmax"
end
add_index "plantdats", ["plant_id"], name: "index_plantdats_on_plant_id"
create_table "plants", force: :cascade do |t|
t.string "title"
t.text "notes"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "species"
t.integer "tray_id"
t.integer "species_id"
t.integer "user_id"
end
add_index "plants", ["category_id"], name: "index_plants_on_category_id"
add_index "plants", ["tray_id"], name: "index_plants_on_tray_id"
add_index "plants", ["user_id"], name: "index_plants_on_user_id"
create_table "schedules", force: :cascade do |t|
t.integer "schedulable_id"
t.string "schedulable_type"
t.date "date"
t.time "time"
t.string "rule"
t.string "interval"
t.text "day"
t.text "day_of_week"
t.datetime "until"
t.integer "count"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "species", force: :cascade do |t|
t.string "name"
t.text "description"
t.integer "plant_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "species", ["plant_id"], name: "index_species_on_plant_id"
create_table "tasks", force: :cascade do |t|
t.integer "plant_id"
t.integer "tray_id"
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "due_date"
end
add_index "tasks", ["plant_id"], name: "index_tasks_on_plant_id"
add_index "tasks", ["tray_id"], name: "index_tasks_on_tray_id"
create_table "tray_cycles", force: :cascade do |t|
t.string "title"
t.integer "tray_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "tray_cycles", ["tray_id"], name: "index_tray_cycles_on_tray_id"
create_table "trays", force: :cascade do |t|
t.string "title"
t.text "notes"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "rescap"
end
add_index "trays", ["category_id"], name: "index_trays_on_category_id"
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.string "firstname"
t.string "lastname"
t.string "username"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Also, my app gets pushed to Heroku, but when I go to 'sign_up', I get the error from the heroku logs:
2016-05-22T07:53:31.678059+00:00 app[web.1]: ActionView::Template::Error (undefined method `firstname' for #<User:0x007fa667e33798>):
2016-05-22T07:53:31.678049+00:00 app[web.1]:
2016-05-22T07:53:31.678060+00:00 app[web.1]: 25:
2016-05-22T07:53:31.678061+00:00 app[web.1]: 26: <div class="field">
2016-05-22T07:53:31.678062+00:00 app[web.1]: 27: <%= f.label 'First Name' %><br />
2016-05-22T07:53:31.678063+00:00 app[web.1]: 28: <%= f.text_field :firstname, autofocus: true, rows: 10, cols: 10, class: 'form-control', placeholder: 'ENTER FIRST NAME' %>
2016-05-22T07:53:31.678064+00:00 app[web.1]: 29: </div>
2016-05-22T07:53:31.678065+00:00 app[web.1]: 30:
2016-05-22T07:53:31.678065+00:00 app[web.1]: 31: <div class="field">
Can anyone help me figure this out? Many thanks :)
Apparently one of the migration files got lost.
If the migration directory is quite full, or not consistent with the database you can use rake db:schema:load to directly create the whole DB.
Thanks to #xyious in the comments. Somehow a few migrations got deleted unbeknownst to me. Running heroku run rake db:schema:load
fixed the problem.

How can I compare an attribute of a instance, which is a date, to the current date?

I am trying to write a scope or a method where I take the attribute (last_eaten) of an instance (line_item) and compare it to the current date. If last_eaten has a date of 1-7 days ago, it gets put in an array that will be called last_week. If last_eaten has a date of 8-14 days ago, it gets put in an array that will be called 2_weeks_ago.
I've tried quite a few things as you can see with the commented out code and several things that I had already erased, but I can't get anything to work. I'm relatively new to rails and any help would be greatly appreciated.
Model
class LineItem < ActiveRecord::Base
belongs_to :recipe
belongs_to :recipe_collection
#scope :last_week, lambda {where("line_item.last_eaten >= ?", 7.days.ago)}
#scope :last_week, lambda { |weeks| where("last_eaten > ?", weeks) }
#scope :three_weeks, lambda { where( #line_item.last_eaten < 21.days.ago.to_date) }
##line_item = LineItem.where(last_eaten: params[:last_eaten]) -- returns nil
##line_item = LineItem.where(last_eaten: params[:last_eaten] < 21.days.ago.to_date)
#def menu
# list = []
# if LineItem.last_eaten.day.to_i > 21.days.ago.day.to_i
# LineItem.last_eaten.each do |recipe_id|
# LineItem.recipe_id << list
# end
# end
# list
#end
end
Schema
ActiveRecord::Schema.define(version: 20151229223926) do
create_table "directions", force: :cascade do |t|
t.text "step"
t.integer "recipe_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "directions", ["recipe_id"], name: "index_directions_on_recipe_id"
create_table "ingredients", force: :cascade do |t|
t.string "name"
t.integer "recipe_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "ingredients", ["recipe_id"], name: "index_ingredients_on_recipe_id"
create_table "line_items", force: :cascade do |t|
t.integer "recipe_id"
t.integer "recipe_collection_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.date "last_eaten"
end
add_index "line_items", ["recipe_collection_id"], name: "index_line_items_on_recipe_collection_id"
add_index "line_items", ["recipe_id"], name: "index_line_items_on_recipe_id"
create_table "recipe_collections", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "recipes", force: :cascade do |t|
t.string "title"
t.text "description"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
scope :last_week, lambda {where("line_item.last_eaten >= ?", 7.days.ago)}
should work...
But further reading made me realise that your table is called line_items, not line_item
When you're doing sql-snippets, you need to refer to the name of the table in SQL, rather than treating it like an individual rails object's name. This means always use the pluralised version :)

Resources