Speakers App

Posted by Aniqa Elahi on October 31, 2017

Thinking about a domain model is always challenging. You dont want a model which has unnecessary controllers or models. I made my app for a NGO which helps people finding a job. While working for them I realize a lot of things are done manually before being published to their website. For example every week they have a meeting where different speakers come to give their lectures and we send them forms to manually fill which are then transfered to their IT team to add in the website. Another challenging job is to send email reminders before the meeting. Based on this information I came up with following models .

Admin

Will be able to add/delete/update any user and their topics as well as creating new categories.

User

I used device for Sign Up/Sig In purpose, which gave email and password by default

  • email (provided by devise)
  • password (provided by devise)
  • name
  • education
  • biography
  • website
  • category

User Model Association

  • has_many :topics
  • belongs_to :category
  • has_many :speakerarchives

Topics

Can add all the details About Week topic to be discussed at the meeting date

  • title
  • description
  • date_of_event

Topic Model Association

  • belongs_to :user
  • has_many :speakerarchives through users

Category

  • title

Category Model Association

  • has_many :users
  • has_many :speakerarchives through user_id

Speakerarchive

Is a join table which will hold a user_id from User and topic_id from Topic.

  • user_id
  • topic_id

Speakerarchive Model Association

  • has_many :users
  • has_many :topics
  • has_many :categories, through: :topics

** Installing Devise**

step 1. gem ‘devise’ in gem file step 2. bundle install step 3. rails generate devise:install( ( run generator ) step 4. rails generate devise User

Next I added name,education etc in db/migrate/migration for device user

step 5. run rake db:migrate

Now we have a devise user model which can Sign In/Sign Up/Sig Out

** Creating Manual User Mode**

Next I create a user model as

rail g controller users

giving us userscontroller and view/users

now I created the traditional Restful actions for a user Note: specify resources :users in config/routes.rb under devise_for :users

User Controller

class UsersController < ApplicationController

before_action :user_signin

def index
	@users = User.all
end

def new
	@user = User.new
end

def create
	@user = User.create(email: params[:email])
	@user.save
end

def edit
 @user = User.find(current_user.id)
end

def update
 @user = User.find(current_user.id)
 @user.update(user_params)
 @user.save
 redirect_to user_path(@user)
end

def show
	@user = User.find(params[:id])
end

private

def user_params
	params.require(:user).permit(:name,:education,:biography,:website,category:[])
end

def user_signin
	user_signed_in?
 end

end



 

Once a user sign ups its prompted to create a profile, upon submission its save as a user record. Once user creates a profile he is able to add a Topic for the upcoming meeting he can add/update/delete a topic.

Topic Controller

class TopicsController < ApplicationController
     before_action :currentuser
      def index
        @topics = current_user.topics
      end

      def new
        @topic = Topic.new
      end

      def create
        
        if params[:topic][:title]!= ""  && params[:topic][:description]!= ""  && params[:topic][:date_of_event]!= ""
            @topic = current_user.topics.create(topic_params)
            current_user.save
            Speakerarchive.create(user_id: current_user.id,topic_id: @topic.id).save
            redirect_to topics_path
        else
            flash[:message] = "All fields must be filled"
            redirect_to new_topic_path(@topic)
        end
       end

      def edit
        @topic = Topic.find(params[:id])
      end

      def update
        @topic = Topic.find(params[:id])
        @topic.update(topic_params)
        @topic.save
        redirect_to topics_path
      end

      def show
        #@topic = Topic.find(params[:id])
      end

      def destroy
        topic = Topic.find(params[:id])
        spRecord = Speakerarchive.find_by(topic_id: topic.id, user_id: current_user.id)
        topic.delete
        spRecord.delete
        redirect_to topics_path
      end

  private

       def topic_params
         params.require(:topic).permit(:title,:description,:date_of_event)
           #      binding.pry
       end

       def currentuser
         user_id = current_user.id if current_user
       end

  end

When a user wants to create a topic it is created under his topics(array of objects) and at the same time I create speakerarchives join table record using currently logged in user and the newly created topic also when a user wants to delete a topic I made sure to not only delete the topic from topics table but from the join table “speakerarchives” as well.

To achieve DRY code I made sure to code most of the layout and sign in/signout and other useful links in the layout/application.rb e.g

<body>
<%= yield %>
<br>
	<% if !user_signed_in? %>
			 <%= link_to "Sign In" , new_user_session_path,{:style => 'color: #ffffff', :class=> "css_class"} %>/
			 <%= link_to "Sign Up", new_user_registration_path,{:style => 'color: #ffffff', :class=> "css_class"} %>
	 <% else %>
			 <%= link_to "My Lectures", topics_path,{:style => 'color: #ffffff', :class=> "css_class"}  %>/
			 <%= link_to "Add New Topic", new_topic_path,{:style => 'color: #ffffff', :class=> "css_class"} %>/
			 <%= link_to "Speaker Archive",speakerarchives_path,{:style => 'color: #ffffff', :class=> "css_class"} %>
			 <%= button_to "Sign Out", destroy_user_session_path,method: :delete %>
	 <% end %>

  </body>
</html>

Topics index page where user is directed after creating a profile or signing in

<p>

<h1>All Topics by <%= current_user.name%></h1>

<ul>

  <%if @topics %>
     <% @topics.each do |topic|%>
<br>
    <li> 
			<%= topic.title%>
      <p> 
		  <%= topic.description%>
      <br>Delivered on :<%= topic.date_of_event%>
      <p>
      <div style="float:left"><%= button_to "Delete",topic_path(topic),method: :delete%>
      </div>
      <div style="float:left"><%= button_to "Edit ", edit_topic_path(topic),method: :get%>
      </div>
      <br>
    </li>
        <% end %>
				
    <%else%>
   
	 <h1>There are no topics at this time</h1>
   
	 <%end%>

I also added Admin through rails_admin. No System is perfect and can be improved …. I still need to add the auto email reminder as well as adding calenders for a better and easy user interaction.